diff --git a/Cargo.lock b/Cargo.lock
index bc7a283..b9eda87 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -682,6 +682,17 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "axum-htmx"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36cdb6062317f732ed3acf4e9c28c3824092e226726616f46ebdd8cd32c82a41"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "http",
+]
+
[[package]]
name = "axum-macros"
version = "0.4.2"
@@ -1702,6 +1713,18 @@ version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
+[[package]]
+name = "filetime"
+version = "0.2.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "libredox",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "fixedbitset"
version = "0.4.2"
@@ -1762,6 +1785,15 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
+[[package]]
+name = "fsevent-sys"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "fst"
version = "0.4.7"
@@ -2329,6 +2361,26 @@ dependencies = [
"serde",
]
+[[package]]
+name = "inotify"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc"
+dependencies = [
+ "bitflags 1.3.2",
+ "inotify-sys",
+ "libc",
+]
+
+[[package]]
+name = "inotify-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "inout"
version = "0.1.3"
@@ -2422,6 +2474,26 @@ dependencies = [
"simple_asn1",
]
+[[package]]
+name = "kqueue"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
+dependencies = [
+ "kqueue-sys",
+ "libc",
+]
+
+[[package]]
+name = "kqueue-sys"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+]
+
[[package]]
name = "lalrpop"
version = "0.20.2"
@@ -2511,6 +2583,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"libc",
+ "redox_syscall",
]
[[package]]
@@ -2620,6 +2693,12 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+[[package]]
+name = "memo-map"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b"
+
[[package]]
name = "miette"
version = "5.10.0"
@@ -2659,6 +2738,27 @@ dependencies = [
"unicase",
]
+[[package]]
+name = "minijinja"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c37e1b517d1dcd0e51dc36c4567b9d5a29262b3ec8da6cb5d35e27a8fb529b5"
+dependencies = [
+ "memo-map",
+ "self_cell",
+ "serde",
+]
+
+[[package]]
+name = "minijinja-autoreload"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14f1f548cc19d59543f8e69ffb71e9da745f996c688384307835ce7cb4dabe06"
+dependencies = [
+ "minijinja",
+ "notify",
+]
+
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -2682,6 +2782,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
"hermit-abi 0.3.9",
"libc",
+ "log",
"wasi",
"windows-sys 0.52.0",
]
@@ -2807,6 +2908,34 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
+[[package]]
+name = "notify"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009"
+dependencies = [
+ "bitflags 2.6.0",
+ "filetime",
+ "fsevent-sys",
+ "inotify",
+ "kqueue",
+ "libc",
+ "log",
+ "mio",
+ "notify-types",
+ "walkdir",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "notify-types"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174"
+dependencies = [
+ "instant",
+]
+
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@@ -4144,6 +4273,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "self_cell"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe"
+
[[package]]
name = "semver"
version = "1.0.23"
@@ -5846,6 +5981,7 @@ dependencies = [
"anyhow",
"async-openai",
"axum",
+ "axum-htmx",
"axum_session",
"axum_session_auth",
"axum_session_surreal",
@@ -5854,6 +5990,8 @@ dependencies = [
"lapin",
"mime",
"mime_guess",
+ "minijinja",
+ "minijinja-autoreload",
"mockall",
"serde",
"serde_json",
diff --git a/Cargo.toml b/Cargo.toml
index b405e5e..8c56efc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
anyhow = "1.0.94"
async-openai = "0.24.1"
axum = { version = "0.7.5", features = ["multipart", "macros"] }
+axum-htmx = "0.6.0"
axum_session = "0.14.4"
axum_session_auth = "0.14.1"
axum_session_surreal = "0.2.1"
@@ -15,6 +16,8 @@ futures = "0.3.31"
lapin = { version = "2.5.0", features = ["serde_json"] }
mime = "0.3.17"
mime_guess = "2.0.5"
+minijinja = { version = "2.5.0", features = ["loader", "multi_template"] }
+minijinja-autoreload = "2.5.0"
mockall = "0.13.0"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
diff --git a/src/server/assets/hi.txt b/assets/hi.txt
similarity index 100%
rename from src/server/assets/hi.txt
rename to assets/hi.txt
diff --git a/src/server/assets/input.css b/assets/input.css
similarity index 100%
rename from src/server/assets/input.css
rename to assets/input.css
diff --git a/assets/style.css b/assets/style.css
new file mode 100644
index 0000000..ac0d94f
--- /dev/null
+++ b/assets/style.css
@@ -0,0 +1,852 @@
+*, ::before, ::after {
+ --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: rgb(59 130 246 / 0.5);
+ --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: ;
+ --tw-contain-size: ;
+ --tw-contain-layout: ;
+ --tw-contain-paint: ;
+ --tw-contain-style: ;
+}
+
+::backdrop {
+ --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: rgb(59 130 246 / 0.5);
+ --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: ;
+ --tw-contain-size: ;
+ --tw-contain-layout: ;
+ --tw-contain-paint: ;
+ --tw-contain-style: ;
+}
+
+/*
+! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com
+*/
+
+/*
+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
+*/
+
+*,
+::before,
+::after {
+ box-sizing: border-box;
+ /* 1 */
+ border-width: 0;
+ /* 2 */
+ border-style: solid;
+ /* 2 */
+ border-color: #e5e7eb;
+ /* 2 */
+}
+
+::before,
+::after {
+ --tw-content: '';
+}
+
+/*
+1. Use a consistent sensible line-height in all browsers.
+2. Prevent adjustments of font size after orientation changes in iOS.
+3. Use a more readable tab size.
+4. Use the user's configured `sans` font-family by default.
+5. Use the user's configured `sans` font-feature-settings by default.
+6. Use the user's configured `sans` font-variation-settings by default.
+7. Disable tap highlights on iOS
+*/
+
+html,
+:host {
+ line-height: 1.5;
+ /* 1 */
+ -webkit-text-size-adjust: 100%;
+ /* 2 */
+ -moz-tab-size: 4;
+ /* 3 */
+ -o-tab-size: 4;
+ tab-size: 4;
+ /* 3 */
+ font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ /* 4 */
+ font-feature-settings: normal;
+ /* 5 */
+ font-variation-settings: normal;
+ /* 6 */
+ -webkit-tap-highlight-color: transparent;
+ /* 7 */
+}
+
+/*
+1. Remove the margin in all browsers.
+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
+*/
+
+body {
+ margin: 0;
+ /* 1 */
+ line-height: inherit;
+ /* 2 */
+}
+
+/*
+1. Add the correct height in Firefox.
+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
+3. Ensure horizontal rules are visible by default.
+*/
+
+hr {
+ height: 0;
+ /* 1 */
+ color: inherit;
+ /* 2 */
+ border-top-width: 1px;
+ /* 3 */
+}
+
+/*
+Add the correct text decoration in Chrome, Edge, and Safari.
+*/
+
+abbr:where([title]) {
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted;
+}
+
+/*
+Remove the default font size and weight for headings.
+*/
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+/*
+Reset links to optimize for opt-in styling instead of opt-out.
+*/
+
+a {
+ color: inherit;
+ text-decoration: inherit;
+}
+
+/*
+Add the correct font weight in Edge and Safari.
+*/
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/*
+1. Use the user's configured `mono` font-family by default.
+2. Use the user's configured `mono` font-feature-settings by default.
+3. Use the user's configured `mono` font-variation-settings by default.
+4. Correct the odd `em` font sizing in all browsers.
+*/
+
+code,
+kbd,
+samp,
+pre {
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ /* 1 */
+ font-feature-settings: normal;
+ /* 2 */
+ font-variation-settings: normal;
+ /* 3 */
+ font-size: 1em;
+ /* 4 */
+}
+
+/*
+Add the correct font size in all browsers.
+*/
+
+small {
+ font-size: 80%;
+}
+
+/*
+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
+*/
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/*
+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)
+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)
+3. Remove gaps between table borders by default.
+*/
+
+table {
+ text-indent: 0;
+ /* 1 */
+ border-color: inherit;
+ /* 2 */
+ border-collapse: collapse;
+ /* 3 */
+}
+
+/*
+1. Change the font styles in all browsers.
+2. Remove the margin in Firefox and Safari.
+3. Remove default padding in all browsers.
+*/
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit;
+ /* 1 */
+ font-feature-settings: inherit;
+ /* 1 */
+ font-variation-settings: inherit;
+ /* 1 */
+ font-size: 100%;
+ /* 1 */
+ font-weight: inherit;
+ /* 1 */
+ line-height: inherit;
+ /* 1 */
+ letter-spacing: inherit;
+ /* 1 */
+ color: inherit;
+ /* 1 */
+ margin: 0;
+ /* 2 */
+ padding: 0;
+ /* 3 */
+}
+
+/*
+Remove the inheritance of text transform in Edge and Firefox.
+*/
+
+button,
+select {
+ text-transform: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Remove default button styles.
+*/
+
+button,
+input:where([type='button']),
+input:where([type='reset']),
+input:where([type='submit']) {
+ -webkit-appearance: button;
+ /* 1 */
+ background-color: transparent;
+ /* 2 */
+ background-image: none;
+ /* 2 */
+}
+
+/*
+Use the modern Firefox focus style for all focusable elements.
+*/
+
+:-moz-focusring {
+ outline: auto;
+}
+
+/*
+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
+*/
+
+:-moz-ui-invalid {
+ box-shadow: none;
+}
+
+/*
+Add the correct vertical alignment in Chrome and Firefox.
+*/
+
+progress {
+ vertical-align: baseline;
+}
+
+/*
+Correct the cursor style of increment and decrement buttons in Safari.
+*/
+
+::-webkit-inner-spin-button,
+::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/*
+1. Correct the odd appearance in Chrome and Safari.
+2. Correct the outline style in Safari.
+*/
+
+[type='search'] {
+ -webkit-appearance: textfield;
+ /* 1 */
+ outline-offset: -2px;
+ /* 2 */
+}
+
+/*
+Remove the inner padding in Chrome and Safari on macOS.
+*/
+
+::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+1. Correct the inability to style clickable types in iOS and Safari.
+2. Change font properties to `inherit` in Safari.
+*/
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ /* 1 */
+ font: inherit;
+ /* 2 */
+}
+
+/*
+Add the correct display in Chrome and Safari.
+*/
+
+summary {
+ display: list-item;
+}
+
+/*
+Removes the default spacing and border for appropriate elements.
+*/
+
+blockquote,
+dl,
+dd,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+hr,
+figure,
+p,
+pre {
+ margin: 0;
+}
+
+fieldset {
+ margin: 0;
+ padding: 0;
+}
+
+legend {
+ padding: 0;
+}
+
+ol,
+ul,
+menu {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/*
+Reset default styling for dialogs.
+*/
+
+dialog {
+ padding: 0;
+}
+
+/*
+Prevent resizing textareas horizontally by default.
+*/
+
+textarea {
+ resize: vertical;
+}
+
+/*
+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
+2. Set the default placeholder color to the user's configured gray 400 color.
+*/
+
+input::-moz-placeholder, textarea::-moz-placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+input::placeholder,
+textarea::placeholder {
+ opacity: 1;
+ /* 1 */
+ color: #9ca3af;
+ /* 2 */
+}
+
+/*
+Set the default cursor for buttons.
+*/
+
+button,
+[role="button"] {
+ cursor: pointer;
+}
+
+/*
+Make sure disabled buttons don't get the pointer cursor.
+*/
+
+:disabled {
+ cursor: default;
+}
+
+/*
+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
+ This can trigger a poorly considered lint error in some tools but is included by design.
+*/
+
+img,
+svg,
+video,
+canvas,
+audio,
+iframe,
+embed,
+object {
+ display: block;
+ /* 1 */
+ vertical-align: middle;
+ /* 2 */
+}
+
+/*
+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
+*/
+
+img,
+video {
+ max-width: 100%;
+ height: auto;
+}
+
+/* Make elements with the HTML hidden attribute stay hidden by default */
+
+[hidden]:where(:not([hidden="until-found"])) {
+ display: none;
+}
+
+:root,
+[data-theme] {
+ background-color: var(--fallback-b1,oklch(var(--b1)/1));
+ color: var(--fallback-bc,oklch(var(--bc)/1));
+}
+
+@supports not (color: oklch(0% 0 0)) {
+ :root {
+ color-scheme: light;
+ --fallback-p: #491eff;
+ --fallback-pc: #d4dbff;
+ --fallback-s: #ff41c7;
+ --fallback-sc: #fff9fc;
+ --fallback-a: #00cfbd;
+ --fallback-ac: #00100d;
+ --fallback-n: #2b3440;
+ --fallback-nc: #d7dde4;
+ --fallback-b1: #ffffff;
+ --fallback-b2: #e5e6e6;
+ --fallback-b3: #e5e6e6;
+ --fallback-bc: #1f2937;
+ --fallback-in: #00b3f0;
+ --fallback-inc: #000000;
+ --fallback-su: #00ca92;
+ --fallback-suc: #000000;
+ --fallback-wa: #ffc22d;
+ --fallback-wac: #000000;
+ --fallback-er: #ff6f70;
+ --fallback-erc: #000000;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ :root {
+ color-scheme: dark;
+ --fallback-p: #7582ff;
+ --fallback-pc: #050617;
+ --fallback-s: #ff71cf;
+ --fallback-sc: #190211;
+ --fallback-a: #00c7b5;
+ --fallback-ac: #000e0c;
+ --fallback-n: #2a323c;
+ --fallback-nc: #a6adbb;
+ --fallback-b1: #1d232a;
+ --fallback-b2: #191e24;
+ --fallback-b3: #15191e;
+ --fallback-bc: #a6adbb;
+ --fallback-in: #00b3f0;
+ --fallback-inc: #000000;
+ --fallback-su: #00ca92;
+ --fallback-suc: #000000;
+ --fallback-wa: #ffc22d;
+ --fallback-wac: #000000;
+ --fallback-er: #ff6f70;
+ --fallback-erc: #000000;
+ }
+ }
+}
+
+html {
+ -webkit-tap-highlight-color: transparent;
+}
+
+* {
+ scrollbar-color: color-mix(in oklch, currentColor 35%, transparent) transparent;
+}
+
+*:hover {
+ scrollbar-color: color-mix(in oklch, currentColor 60%, transparent) transparent;
+}
+
+:root {
+ color-scheme: light;
+ --in: 72.06% 0.191 231.6;
+ --su: 64.8% 0.150 160;
+ --wa: 84.71% 0.199 83.87;
+ --er: 71.76% 0.221 22.18;
+ --pc: 89.824% 0.06192 275.75;
+ --ac: 15.352% 0.0368 183.61;
+ --inc: 0% 0 0;
+ --suc: 0% 0 0;
+ --wac: 0% 0 0;
+ --erc: 0% 0 0;
+ --rounded-box: 1rem;
+ --rounded-btn: 0.5rem;
+ --rounded-badge: 1.9rem;
+ --animation-btn: 0.25s;
+ --animation-input: .2s;
+ --btn-focus-scale: 0.95;
+ --border-btn: 1px;
+ --tab-border: 1px;
+ --tab-radius: 0.5rem;
+ --p: 49.12% 0.3096 275.75;
+ --s: 69.71% 0.329 342.55;
+ --sc: 98.71% 0.0106 342.55;
+ --a: 76.76% 0.184 183.61;
+ --n: 32.1785% 0.02476 255.701624;
+ --nc: 89.4994% 0.011585 252.096176;
+ --b1: 100% 0 0;
+ --b2: 96.1151% 0 0;
+ --b3: 92.4169% 0.00108 197.137559;
+ --bc: 27.8078% 0.029596 256.847952;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ color-scheme: dark;
+ --in: 72.06% 0.191 231.6;
+ --su: 64.8% 0.150 160;
+ --wa: 84.71% 0.199 83.87;
+ --er: 71.76% 0.221 22.18;
+ --pc: 13.138% 0.0392 275.75;
+ --sc: 14.96% 0.052 342.55;
+ --ac: 14.902% 0.0334 183.61;
+ --inc: 0% 0 0;
+ --suc: 0% 0 0;
+ --wac: 0% 0 0;
+ --erc: 0% 0 0;
+ --rounded-box: 1rem;
+ --rounded-btn: 0.5rem;
+ --rounded-badge: 1.9rem;
+ --animation-btn: 0.25s;
+ --animation-input: .2s;
+ --btn-focus-scale: 0.95;
+ --border-btn: 1px;
+ --tab-border: 1px;
+ --tab-radius: 0.5rem;
+ --p: 65.69% 0.196 275.75;
+ --s: 74.8% 0.26 342.55;
+ --a: 74.51% 0.167 183.61;
+ --n: 31.3815% 0.021108 254.139175;
+ --nc: 74.6477% 0.0216 264.435964;
+ --b1: 25.3267% 0.015896 252.417568;
+ --b2: 23.2607% 0.013807 253.100675;
+ --b3: 21.1484% 0.01165 254.087939;
+ --bc: 74.6477% 0.0216 264.435964;
+ }
+}
+
+[data-theme=light] {
+ color-scheme: light;
+ --in: 72.06% 0.191 231.6;
+ --su: 64.8% 0.150 160;
+ --wa: 84.71% 0.199 83.87;
+ --er: 71.76% 0.221 22.18;
+ --pc: 89.824% 0.06192 275.75;
+ --ac: 15.352% 0.0368 183.61;
+ --inc: 0% 0 0;
+ --suc: 0% 0 0;
+ --wac: 0% 0 0;
+ --erc: 0% 0 0;
+ --rounded-box: 1rem;
+ --rounded-btn: 0.5rem;
+ --rounded-badge: 1.9rem;
+ --animation-btn: 0.25s;
+ --animation-input: .2s;
+ --btn-focus-scale: 0.95;
+ --border-btn: 1px;
+ --tab-border: 1px;
+ --tab-radius: 0.5rem;
+ --p: 49.12% 0.3096 275.75;
+ --s: 69.71% 0.329 342.55;
+ --sc: 98.71% 0.0106 342.55;
+ --a: 76.76% 0.184 183.61;
+ --n: 32.1785% 0.02476 255.701624;
+ --nc: 89.4994% 0.011585 252.096176;
+ --b1: 100% 0 0;
+ --b2: 96.1151% 0 0;
+ --b3: 92.4169% 0.00108 197.137559;
+ --bc: 27.8078% 0.029596 256.847952;
+}
+
+[data-theme=dark] {
+ color-scheme: dark;
+ --in: 72.06% 0.191 231.6;
+ --su: 64.8% 0.150 160;
+ --wa: 84.71% 0.199 83.87;
+ --er: 71.76% 0.221 22.18;
+ --pc: 13.138% 0.0392 275.75;
+ --sc: 14.96% 0.052 342.55;
+ --ac: 14.902% 0.0334 183.61;
+ --inc: 0% 0 0;
+ --suc: 0% 0 0;
+ --wac: 0% 0 0;
+ --erc: 0% 0 0;
+ --rounded-box: 1rem;
+ --rounded-btn: 0.5rem;
+ --rounded-badge: 1.9rem;
+ --animation-btn: 0.25s;
+ --animation-input: .2s;
+ --btn-focus-scale: 0.95;
+ --border-btn: 1px;
+ --tab-border: 1px;
+ --tab-radius: 0.5rem;
+ --p: 65.69% 0.196 275.75;
+ --s: 74.8% 0.26 342.55;
+ --a: 74.51% 0.167 183.61;
+ --n: 31.3815% 0.021108 254.139175;
+ --nc: 74.6477% 0.0216 264.435964;
+ --b1: 25.3267% 0.015896 252.417568;
+ --b2: 23.2607% 0.013807 253.100675;
+ --b3: 21.1484% 0.01165 254.087939;
+ --bc: 74.6477% 0.0216 264.435964;
+}
+
+@keyframes button-pop {
+ 0% {
+ transform: scale(var(--btn-focus-scale, 0.98));
+ }
+
+ 40% {
+ transform: scale(1.02);
+ }
+
+ 100% {
+ transform: scale(1);
+ }
+}
+
+@keyframes checkmark {
+ 0% {
+ background-position-y: 5px;
+ }
+
+ 50% {
+ background-position-y: -2px;
+ }
+
+ 100% {
+ background-position-y: 0;
+ }
+}
+
+@keyframes modal-pop {
+ 0% {
+ opacity: 0;
+ }
+}
+
+@keyframes progress-loading {
+ 50% {
+ background-position-x: -115%;
+ }
+}
+
+@keyframes radiomark {
+ 0% {
+ box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,
+ 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset;
+ }
+
+ 50% {
+ box-shadow: 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset,
+ 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset;
+ }
+
+ 100% {
+ box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,
+ 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset;
+ }
+}
+
+@keyframes rating-pop {
+ 0% {
+ transform: translateY(-0.125em);
+ }
+
+ 40% {
+ transform: translateY(-0.125em);
+ }
+
+ 100% {
+ transform: translateY(0);
+ }
+}
+
+@keyframes skeleton {
+ from {
+ background-position: 150%;
+ }
+
+ to {
+ background-position: -50%;
+ }
+}
+
+@keyframes toast-pop {
+ 0% {
+ transform: scale(0.9);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
\ No newline at end of file
diff --git a/src/bin/server.rs b/src/bin/server.rs
index f9d9113..a7d9168 100644
--- a/src/bin/server.rs
+++ b/src/bin/server.rs
@@ -7,7 +7,9 @@ use axum::{
use axum_session::{SessionConfig, SessionLayer, SessionStore};
use axum_session_auth::{AuthConfig, AuthSessionLayer};
use axum_session_surreal::SessionSurrealPool;
-use std::sync::Arc;
+use minijinja::{path_loader, Environment};
+use minijinja_autoreload::AutoReloader;
+use std::{path::PathBuf, sync::Arc};
use surrealdb::{engine::any::Any, Surreal};
use tera::Tera;
use tower_http::services::ServeDir;
@@ -48,12 +50,23 @@ async fn main() -> Result<(), Box> {
routing_key: "my_key".to_string(),
};
+ let reloader = AutoReloader::new(move |notifier| {
+ let template_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("templates");
+ let mut env = Environment::new();
+ env.set_loader(path_loader(&template_path));
+
+ notifier.set_fast_reload(true);
+ notifier.watch_path(&template_path, true);
+ Ok(env)
+ });
+
let app_state = AppState {
rabbitmq_producer: Arc::new(RabbitMQProducer::new(&config).await?),
rabbitmq_consumer: Arc::new(RabbitMQConsumer::new(&config, false).await?),
surreal_db_client: Arc::new(SurrealDbClient::new().await?),
- tera: Arc::new(Tera::new("src/server/templates/**/*.html").unwrap()),
+ // tera: Arc::new(Tera::new("templates/**/*.html").unwrap()),
openai_client: Arc::new(async_openai::Client::new()),
+ templates: Arc::new(reloader),
};
// setup_auth(&app_state.surreal_db_client).await?;
@@ -116,7 +129,7 @@ fn html_routes(
.route("/", get(index_handler))
.route("/search", get(search_result_handler))
.route("/signup", get(show_signup_form).post(signup_handler))
- .nest_service("/assets", ServeDir::new("src/server/assets"))
+ .nest_service("/assets", ServeDir::new("assets/"))
.layer(
AuthSessionLayer::, Surreal>::new(Some(
db_client,
diff --git a/src/server/assets/style.css b/src/server/assets/style.css
deleted file mode 100644
index 97d4dc0..0000000
--- a/src/server/assets/style.css
+++ /dev/null
@@ -1,2009 +0,0 @@
-*, ::before, ::after {
- --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: rgb(59 130 246 / 0.5);
- --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: ;
- --tw-contain-size: ;
- --tw-contain-layout: ;
- --tw-contain-paint: ;
- --tw-contain-style: ;
-}
-
-::backdrop {
- --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: rgb(59 130 246 / 0.5);
- --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: ;
- --tw-contain-size: ;
- --tw-contain-layout: ;
- --tw-contain-paint: ;
- --tw-contain-style: ;
-}
-
-/*
-! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com
-*/
-
-/*
-1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
-2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
-*/
-
-*,
-::before,
-::after {
- box-sizing: border-box;
- /* 1 */
- border-width: 0;
- /* 2 */
- border-style: solid;
- /* 2 */
- border-color: #e5e7eb;
- /* 2 */
-}
-
-::before,
-::after {
- --tw-content: '';
-}
-
-/*
-1. Use a consistent sensible line-height in all browsers.
-2. Prevent adjustments of font size after orientation changes in iOS.
-3. Use a more readable tab size.
-4. Use the user's configured `sans` font-family by default.
-5. Use the user's configured `sans` font-feature-settings by default.
-6. Use the user's configured `sans` font-variation-settings by default.
-7. Disable tap highlights on iOS
-*/
-
-html,
-:host {
- line-height: 1.5;
- /* 1 */
- -webkit-text-size-adjust: 100%;
- /* 2 */
- -moz-tab-size: 4;
- /* 3 */
- -o-tab-size: 4;
- tab-size: 4;
- /* 3 */
- font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- /* 4 */
- font-feature-settings: normal;
- /* 5 */
- font-variation-settings: normal;
- /* 6 */
- -webkit-tap-highlight-color: transparent;
- /* 7 */
-}
-
-/*
-1. Remove the margin in all browsers.
-2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
-*/
-
-body {
- margin: 0;
- /* 1 */
- line-height: inherit;
- /* 2 */
-}
-
-/*
-1. Add the correct height in Firefox.
-2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
-3. Ensure horizontal rules are visible by default.
-*/
-
-hr {
- height: 0;
- /* 1 */
- color: inherit;
- /* 2 */
- border-top-width: 1px;
- /* 3 */
-}
-
-/*
-Add the correct text decoration in Chrome, Edge, and Safari.
-*/
-
-abbr:where([title]) {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
-}
-
-/*
-Remove the default font size and weight for headings.
-*/
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-size: inherit;
- font-weight: inherit;
-}
-
-/*
-Reset links to optimize for opt-in styling instead of opt-out.
-*/
-
-a {
- color: inherit;
- text-decoration: inherit;
-}
-
-/*
-Add the correct font weight in Edge and Safari.
-*/
-
-b,
-strong {
- font-weight: bolder;
-}
-
-/*
-1. Use the user's configured `mono` font-family by default.
-2. Use the user's configured `mono` font-feature-settings by default.
-3. Use the user's configured `mono` font-variation-settings by default.
-4. Correct the odd `em` font sizing in all browsers.
-*/
-
-code,
-kbd,
-samp,
-pre {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
- /* 1 */
- font-feature-settings: normal;
- /* 2 */
- font-variation-settings: normal;
- /* 3 */
- font-size: 1em;
- /* 4 */
-}
-
-/*
-Add the correct font size in all browsers.
-*/
-
-small {
- font-size: 80%;
-}
-
-/*
-Prevent `sub` and `sup` elements from affecting the line height in all browsers.
-*/
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-/*
-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)
-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)
-3. Remove gaps between table borders by default.
-*/
-
-table {
- text-indent: 0;
- /* 1 */
- border-color: inherit;
- /* 2 */
- border-collapse: collapse;
- /* 3 */
-}
-
-/*
-1. Change the font styles in all browsers.
-2. Remove the margin in Firefox and Safari.
-3. Remove default padding in all browsers.
-*/
-
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: inherit;
- /* 1 */
- font-feature-settings: inherit;
- /* 1 */
- font-variation-settings: inherit;
- /* 1 */
- font-size: 100%;
- /* 1 */
- font-weight: inherit;
- /* 1 */
- line-height: inherit;
- /* 1 */
- letter-spacing: inherit;
- /* 1 */
- color: inherit;
- /* 1 */
- margin: 0;
- /* 2 */
- padding: 0;
- /* 3 */
-}
-
-/*
-Remove the inheritance of text transform in Edge and Firefox.
-*/
-
-button,
-select {
- text-transform: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Remove default button styles.
-*/
-
-button,
-input:where([type='button']),
-input:where([type='reset']),
-input:where([type='submit']) {
- -webkit-appearance: button;
- /* 1 */
- background-color: transparent;
- /* 2 */
- background-image: none;
- /* 2 */
-}
-
-/*
-Use the modern Firefox focus style for all focusable elements.
-*/
-
-:-moz-focusring {
- outline: auto;
-}
-
-/*
-Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
-*/
-
-:-moz-ui-invalid {
- box-shadow: none;
-}
-
-/*
-Add the correct vertical alignment in Chrome and Firefox.
-*/
-
-progress {
- vertical-align: baseline;
-}
-
-/*
-Correct the cursor style of increment and decrement buttons in Safari.
-*/
-
-::-webkit-inner-spin-button,
-::-webkit-outer-spin-button {
- height: auto;
-}
-
-/*
-1. Correct the odd appearance in Chrome and Safari.
-2. Correct the outline style in Safari.
-*/
-
-[type='search'] {
- -webkit-appearance: textfield;
- /* 1 */
- outline-offset: -2px;
- /* 2 */
-}
-
-/*
-Remove the inner padding in Chrome and Safari on macOS.
-*/
-
-::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Change font properties to `inherit` in Safari.
-*/
-
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- /* 1 */
- font: inherit;
- /* 2 */
-}
-
-/*
-Add the correct display in Chrome and Safari.
-*/
-
-summary {
- display: list-item;
-}
-
-/*
-Removes the default spacing and border for appropriate elements.
-*/
-
-blockquote,
-dl,
-dd,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-hr,
-figure,
-p,
-pre {
- margin: 0;
-}
-
-fieldset {
- margin: 0;
- padding: 0;
-}
-
-legend {
- padding: 0;
-}
-
-ol,
-ul,
-menu {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/*
-Reset default styling for dialogs.
-*/
-
-dialog {
- padding: 0;
-}
-
-/*
-Prevent resizing textareas horizontally by default.
-*/
-
-textarea {
- resize: vertical;
-}
-
-/*
-1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
-2. Set the default placeholder color to the user's configured gray 400 color.
-*/
-
-input::-moz-placeholder, textarea::-moz-placeholder {
- opacity: 1;
- /* 1 */
- color: #9ca3af;
- /* 2 */
-}
-
-input::placeholder,
-textarea::placeholder {
- opacity: 1;
- /* 1 */
- color: #9ca3af;
- /* 2 */
-}
-
-/*
-Set the default cursor for buttons.
-*/
-
-button,
-[role="button"] {
- cursor: pointer;
-}
-
-/*
-Make sure disabled buttons don't get the pointer cursor.
-*/
-
-:disabled {
- cursor: default;
-}
-
-/*
-1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
-2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
- This can trigger a poorly considered lint error in some tools but is included by design.
-*/
-
-img,
-svg,
-video,
-canvas,
-audio,
-iframe,
-embed,
-object {
- display: block;
- /* 1 */
- vertical-align: middle;
- /* 2 */
-}
-
-/*
-Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
-*/
-
-img,
-video {
- max-width: 100%;
- height: auto;
-}
-
-/* Make elements with the HTML hidden attribute stay hidden by default */
-
-[hidden]:where(:not([hidden="until-found"])) {
- display: none;
-}
-
-:root,
-[data-theme] {
- background-color: var(--fallback-b1,oklch(var(--b1)/1));
- color: var(--fallback-bc,oklch(var(--bc)/1));
-}
-
-@supports not (color: oklch(0% 0 0)) {
- :root {
- color-scheme: light;
- --fallback-p: #491eff;
- --fallback-pc: #d4dbff;
- --fallback-s: #ff41c7;
- --fallback-sc: #fff9fc;
- --fallback-a: #00cfbd;
- --fallback-ac: #00100d;
- --fallback-n: #2b3440;
- --fallback-nc: #d7dde4;
- --fallback-b1: #ffffff;
- --fallback-b2: #e5e6e6;
- --fallback-b3: #e5e6e6;
- --fallback-bc: #1f2937;
- --fallback-in: #00b3f0;
- --fallback-inc: #000000;
- --fallback-su: #00ca92;
- --fallback-suc: #000000;
- --fallback-wa: #ffc22d;
- --fallback-wac: #000000;
- --fallback-er: #ff6f70;
- --fallback-erc: #000000;
- }
-
- @media (prefers-color-scheme: dark) {
- :root {
- color-scheme: dark;
- --fallback-p: #7582ff;
- --fallback-pc: #050617;
- --fallback-s: #ff71cf;
- --fallback-sc: #190211;
- --fallback-a: #00c7b5;
- --fallback-ac: #000e0c;
- --fallback-n: #2a323c;
- --fallback-nc: #a6adbb;
- --fallback-b1: #1d232a;
- --fallback-b2: #191e24;
- --fallback-b3: #15191e;
- --fallback-bc: #a6adbb;
- --fallback-in: #00b3f0;
- --fallback-inc: #000000;
- --fallback-su: #00ca92;
- --fallback-suc: #000000;
- --fallback-wa: #ffc22d;
- --fallback-wac: #000000;
- --fallback-er: #ff6f70;
- --fallback-erc: #000000;
- }
- }
-}
-
-html {
- -webkit-tap-highlight-color: transparent;
-}
-
-* {
- scrollbar-color: color-mix(in oklch, currentColor 35%, transparent) transparent;
-}
-
-*:hover {
- scrollbar-color: color-mix(in oklch, currentColor 60%, transparent) transparent;
-}
-
-:root {
- color-scheme: dark;
- --in: 72.06% 0.191 231.6;
- --su: 64.8% 0.150 160;
- --wa: 84.71% 0.199 83.87;
- --er: 71.76% 0.221 22.18;
- --pc: 13.138% 0.0392 275.75;
- --sc: 14.96% 0.052 342.55;
- --ac: 14.902% 0.0334 183.61;
- --inc: 0% 0 0;
- --suc: 0% 0 0;
- --wac: 0% 0 0;
- --erc: 0% 0 0;
- --rounded-box: 1rem;
- --rounded-btn: 0.5rem;
- --rounded-badge: 1.9rem;
- --animation-btn: 0.25s;
- --animation-input: .2s;
- --btn-focus-scale: 0.95;
- --border-btn: 1px;
- --tab-border: 1px;
- --tab-radius: 0.5rem;
- --p: 65.69% 0.196 275.75;
- --s: 74.8% 0.26 342.55;
- --a: 74.51% 0.167 183.61;
- --n: 31.3815% 0.021108 254.139175;
- --nc: 74.6477% 0.0216 264.435964;
- --b1: 25.3267% 0.015896 252.417568;
- --b2: 23.2607% 0.013807 253.100675;
- --b3: 21.1484% 0.01165 254.087939;
- --bc: 74.6477% 0.0216 264.435964;
-}
-
-.container {
- width: 100%;
-}
-
-@media (min-width: 640px) {
- .container {
- max-width: 640px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 768px;
- }
-}
-
-@media (min-width: 1024px) {
- .container {
- max-width: 1024px;
- }
-}
-
-@media (min-width: 1280px) {
- .container {
- max-width: 1280px;
- }
-}
-
-@media (min-width: 1536px) {
- .container {
- max-width: 1536px;
- }
-}
-
-.avatar.placeholder > div {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-@media (hover:hover) {
- .label a:hover {
- --tw-text-opacity: 1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- }
-
- .menu li > *:not(ul, .menu-title, details, .btn):active,
-.menu li > *:not(ul, .menu-title, details, .btn).active,
-.menu li > details > summary:active {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-text-opacity: 1;
- color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
- }
-}
-
-.btn {
- display: inline-flex;
- height: 3rem;
- min-height: 3rem;
- flex-shrink: 0;
- cursor: pointer;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- flex-wrap: wrap;
- align-items: center;
- justify-content: center;
- border-radius: var(--rounded-btn, 0.5rem);
- border-color: transparent;
- border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity));
- padding-left: 1rem;
- padding-right: 1rem;
- text-align: center;
- font-size: 0.875rem;
- line-height: 1em;
- gap: 0.5rem;
- font-weight: 600;
- text-decoration-line: none;
- transition-duration: 200ms;
- transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
- border-width: var(--border-btn, 1px);
- transition-property: color, background-color, border-color, opacity, box-shadow, transform;
- --tw-text-opacity: 1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
- --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
- outline-color: var(--fallback-bc,oklch(var(--bc)/1));
- background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity));
- --tw-bg-opacity: 1;
- --tw-border-opacity: 1;
-}
-
-.btn-disabled,
- .btn[disabled],
- .btn:disabled {
- pointer-events: none;
-}
-
-:where(.btn:is(input[type="checkbox"])),
-:where(.btn:is(input[type="radio"])) {
- width: auto;
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
-}
-
-.btn:is(input[type="checkbox"]):after,
-.btn:is(input[type="radio"]):after {
- --tw-content: attr(aria-label);
- content: var(--tw-content);
-}
-
-.card {
- position: relative;
- display: flex;
- flex-direction: column;
- border-radius: var(--rounded-box, 1rem);
-}
-
-.card:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
-}
-
-.card-body {
- display: flex;
- flex: 1 1 auto;
- flex-direction: column;
- padding: var(--padding-card, 2rem);
- gap: 0.5rem;
-}
-
-.card-body :where(p) {
- flex-grow: 1;
-}
-
-.card figure {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.card.image-full {
- display: grid;
-}
-
-.card.image-full:before {
- position: relative;
- content: "";
- z-index: 10;
- border-radius: var(--rounded-box, 1rem);
- --tw-bg-opacity: 1;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- opacity: 0.75;
-}
-
-.card.image-full:before,
- .card.image-full > * {
- grid-column-start: 1;
- grid-row-start: 1;
-}
-
-.card.image-full > figure img {
- height: 100%;
- -o-object-fit: cover;
- object-fit: cover;
-}
-
-.card.image-full > .card-body {
- position: relative;
- z-index: 20;
- --tw-text-opacity: 1;
- color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
-}
-
-.chat {
- display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
- -moz-column-gap: 0.75rem;
- column-gap: 0.75rem;
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
-}
-
-.chat-bubble {
- position: relative;
- display: block;
- width: -moz-fit-content;
- width: fit-content;
- padding-left: 1rem;
- padding-right: 1rem;
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
- max-width: 90%;
- border-radius: var(--rounded-box, 1rem);
- min-height: 2.75rem;
- min-width: 2.75rem;
- --tw-bg-opacity: 1;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-text-opacity: 1;
- color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
-}
-
-.chat-bubble:before {
- position: absolute;
- bottom: 0px;
- height: 0.75rem;
- width: 0.75rem;
- background-color: inherit;
- content: "";
- -webkit-mask-size: contain;
- mask-size: contain;
- -webkit-mask-repeat: no-repeat;
- mask-repeat: no-repeat;
- -webkit-mask-position: center;
- mask-position: center;
-}
-
-.chat-start {
- place-items: start;
- grid-template-columns: auto 1fr;
-}
-
-.chat-start .chat-header {
- grid-column-start: 2;
-}
-
-.chat-start .chat-footer {
- grid-column-start: 2;
-}
-
-.chat-start .chat-image {
- grid-column-start: 1;
-}
-
-.chat-start .chat-bubble {
- grid-column-start: 2;
- border-end-start-radius: 0px;
-}
-
-.chat-start .chat-bubble:before {
- -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
- mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
- inset-inline-start: -0.749rem;
-}
-
-[dir="rtl"] .chat-start .chat-bubble:before {
- -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e");
- mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e");
-}
-
-.chat-end .chat-bubble {
- grid-column-start: 1;
- border-end-end-radius: 0px;
-}
-
-.chat-end .chat-bubble:before {
- -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e");
- mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 1 3 L 3 3 C 2 3 0 1 0 0'/%3e%3c/svg%3e");
- inset-inline-start: 99.9%;
-}
-
-[dir="rtl"] .chat-end .chat-bubble:before {
- -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
- mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
-}
-
-.divider {
- display: flex;
- flex-direction: row;
- align-items: center;
- align-self: stretch;
- margin-top: 1rem;
- margin-bottom: 1rem;
- height: 1rem;
- white-space: nowrap;
-}
-
-.divider:before,
- .divider:after {
- height: 0.125rem;
- width: 100%;
- flex-grow: 1;
- --tw-content: '';
- content: var(--tw-content);
- background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
-}
-
-@media (hover: hover) {
- .btm-nav > *.disabled:hover,
- .btm-nav > *[disabled]:hover {
- pointer-events: none;
- --tw-border-opacity: 0;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-bg-opacity: 0.1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- --tw-text-opacity: 0.2;
- }
-
- .btn:hover {
- --tw-border-opacity: 1;
- border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));
- }
-
- @supports (color: color-mix(in oklab, black, black)) {
- .btn:hover {
- background-color: color-mix(
- in oklab,
- oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%,
- black
- );
- border-color: color-mix(
- in oklab,
- oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%,
- black
- );
- }
- }
-
- @supports not (color: oklch(0% 0 0)) {
- .btn:hover {
- background-color: var(--btn-color, var(--fallback-b2));
- border-color: var(--btn-color, var(--fallback-b2));
- }
- }
-
- .btn.glass:hover {
- --glass-opacity: 25%;
- --glass-border-opacity: 15%;
- }
-
- .btn-ghost:hover {
- border-color: transparent;
- }
-
- @supports (color: oklch(0% 0 0)) {
- .btn-ghost:hover {
- background-color: var(--fallback-bc,oklch(var(--bc)/0.2));
- }
- }
-
- .btn-outline.btn-primary:hover {
- --tw-text-opacity: 1;
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
- }
-
- @supports (color: color-mix(in oklab, black, black)) {
- .btn-outline.btn-primary:hover {
- background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- }
- }
-
- .btn-disabled:hover,
- .btn[disabled]:hover,
- .btn:disabled:hover {
- --tw-border-opacity: 0;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-bg-opacity: 0.2;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- --tw-text-opacity: 0.2;
- }
-
- @supports (color: color-mix(in oklab, black, black)) {
- .btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover {
- background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- }
- }
-
- :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
- cursor: pointer;
- outline: 2px solid transparent;
- outline-offset: 2px;
- }
-
- @supports (color: oklch(0% 0 0)) {
- :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
- background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
- }
- }
-}
-
-.form-control {
- display: flex;
- flex-direction: column;
-}
-
-.label {
- display: flex;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- align-items: center;
- justify-content: space-between;
- padding-left: 0.25rem;
- padding-right: 0.25rem;
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
-}
-
-.indicator {
- position: relative;
- display: inline-flex;
- width: -moz-max-content;
- width: max-content;
-}
-
-.indicator :where(.indicator-item) {
- z-index: 1;
- position: absolute;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
- white-space: nowrap;
-}
-
-.input {
- flex-shrink: 1;
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- height: 3rem;
- padding-left: 1rem;
- padding-right: 1rem;
- font-size: 1rem;
- line-height: 2;
- line-height: 1.5rem;
- border-radius: var(--rounded-btn, 0.5rem);
- border-width: 1px;
- border-color: transparent;
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
-}
-
-.input[type="number"]::-webkit-inner-spin-button,
-.input-md[type="number"]::-webkit-inner-spin-button {
- margin-top: -1rem;
- margin-bottom: -1rem;
- margin-inline-end: -1rem;
-}
-
-.link {
- cursor: pointer;
- text-decoration-line: underline;
-}
-
-.menu {
- display: flex;
- flex-direction: column;
- flex-wrap: wrap;
- font-size: 0.875rem;
- line-height: 1.25rem;
- padding: 0.5rem;
-}
-
-.menu :where(li ul) {
- position: relative;
- white-space: nowrap;
- margin-inline-start: 1rem;
- padding-inline-start: 0.5rem;
-}
-
-.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), .menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
- display: grid;
- grid-auto-flow: column;
- align-content: flex-start;
- align-items: center;
- gap: 0.5rem;
- grid-auto-columns: minmax(auto, max-content) auto max-content;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
-}
-
-.menu li.disabled {
- cursor: not-allowed;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- color: var(--fallback-bc,oklch(var(--bc)/0.3));
-}
-
-.menu :where(li > .menu-dropdown:not(.menu-dropdown-show)) {
- display: none;
-}
-
-:where(.menu li) {
- position: relative;
- display: flex;
- flex-shrink: 0;
- flex-direction: column;
- flex-wrap: wrap;
- align-items: stretch;
-}
-
-:where(.menu li) .badge {
- justify-self: end;
-}
-
-.navbar {
- display: flex;
- align-items: center;
- padding: var(--navbar-padding, 0.5rem);
- min-height: 4rem;
- width: 100%;
-}
-
-:where(.navbar > *:not(script, style)) {
- display: inline-flex;
- align-items: center;
-}
-
-.btm-nav > *.disabled,
- .btm-nav > *[disabled] {
- pointer-events: none;
- --tw-border-opacity: 0;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-bg-opacity: 0.1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- --tw-text-opacity: 0.2;
-}
-
-.btm-nav > * .label {
- font-size: 1rem;
- line-height: 1.5rem;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .btn {
- animation: button-pop var(--animation-btn, 0.25s) ease-out;
- }
-}
-
-.btn:active:hover,
- .btn:active:focus {
- animation: button-pop 0s ease-out;
- transform: scale(var(--btn-focus-scale, 0.97));
-}
-
-@supports not (color: oklch(0% 0 0)) {
- .btn {
- background-color: var(--btn-color, var(--fallback-b2));
- border-color: var(--btn-color, var(--fallback-b2));
- }
-
- .btn-primary {
- --btn-color: var(--fallback-p);
- }
-}
-
-@supports (color: color-mix(in oklab, black, black)) {
- .btn-outline.btn-primary.btn-active {
- background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
- }
-}
-
-.btn:focus-visible {
- outline-style: solid;
- outline-width: 2px;
- outline-offset: 2px;
-}
-
-.btn-primary {
- --tw-text-opacity: 1;
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
- outline-color: var(--fallback-p,oklch(var(--p)/1));
-}
-
-@supports (color: oklch(0% 0 0)) {
- .btn-primary {
- --btn-color: var(--p);
- }
-}
-
-.btn.glass {
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
- outline-color: currentColor;
-}
-
-.btn.glass.btn-active {
- --glass-opacity: 25%;
- --glass-border-opacity: 15%;
-}
-
-.btn-ghost {
- border-width: 1px;
- border-color: transparent;
- background-color: transparent;
- color: currentColor;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
- outline-color: currentColor;
-}
-
-.btn-ghost.btn-active {
- border-color: transparent;
- background-color: var(--fallback-bc,oklch(var(--bc)/0.2));
-}
-
-.btn-outline.btn-primary {
- --tw-text-opacity: 1;
- color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
-}
-
-.btn-outline.btn-primary.btn-active {
- --tw-text-opacity: 1;
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
-}
-
-.btn.btn-disabled,
- .btn[disabled],
- .btn:disabled {
- --tw-border-opacity: 0;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-bg-opacity: 0.2;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- --tw-text-opacity: 0.2;
-}
-
-.btn:is(input[type="checkbox"]:checked),
-.btn:is(input[type="radio"]:checked) {
- --tw-border-opacity: 1;
- border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));
- --tw-bg-opacity: 1;
- background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));
- --tw-text-opacity: 1;
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
-}
-
-.btn:is(input[type="checkbox"]:checked):focus-visible, .btn:is(input[type="radio"]:checked):focus-visible {
- outline-color: var(--fallback-p,oklch(var(--p)/1));
-}
-
-@keyframes button-pop {
- 0% {
- transform: scale(var(--btn-focus-scale, 0.98));
- }
-
- 40% {
- transform: scale(1.02);
- }
-
- 100% {
- transform: scale(1);
- }
-}
-
-.card :where(figure:first-child) {
- overflow: hidden;
- border-start-start-radius: inherit;
- border-start-end-radius: inherit;
- border-end-start-radius: unset;
- border-end-end-radius: unset;
-}
-
-.card :where(figure:last-child) {
- overflow: hidden;
- border-start-start-radius: unset;
- border-start-end-radius: unset;
- border-end-start-radius: inherit;
- border-end-end-radius: inherit;
-}
-
-.card:focus-visible {
- outline: 2px solid currentColor;
- outline-offset: 2px;
-}
-
-.card.bordered {
- border-width: 1px;
- --tw-border-opacity: 1;
- border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
-}
-
-.card.compact .card-body {
- padding: 1rem;
- font-size: 0.875rem;
- line-height: 1.25rem;
-}
-
-.card-title {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: 1.25rem;
- line-height: 1.75rem;
- font-weight: 600;
-}
-
-.card.image-full :where(figure) {
- overflow: hidden;
- border-radius: inherit;
-}
-
-@keyframes checkmark {
- 0% {
- background-position-y: 5px;
- }
-
- 50% {
- background-position-y: -2px;
- }
-
- 100% {
- background-position-y: 0;
- }
-}
-
-.divider:not(:empty) {
- gap: 1rem;
-}
-
-.label-text {
- font-size: 0.875rem;
- line-height: 1.25rem;
- --tw-text-opacity: 1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
-}
-
-.input input {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));
- background-color: transparent;
-}
-
-.input input:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
-}
-
-.input[list]::-webkit-calendar-picker-indicator {
- line-height: 1em;
-}
-
-.input-bordered {
- border-color: var(--fallback-bc,oklch(var(--bc)/0.2));
-}
-
-.input:focus,
- .input:focus-within {
- box-shadow: none;
- border-color: var(--fallback-bc,oklch(var(--bc)/0.2));
- outline-style: solid;
- outline-width: 2px;
- outline-offset: 2px;
- outline-color: var(--fallback-bc,oklch(var(--bc)/0.2));
-}
-
-.input:has(> input[disabled]),
- .input-disabled,
- .input:disabled,
- .input[disabled] {
- cursor: not-allowed;
- --tw-border-opacity: 1;
- border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
- color: var(--fallback-bc,oklch(var(--bc)/0.4));
-}
-
-.input:has(> input[disabled])::-moz-placeholder, .input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder {
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
- --tw-placeholder-opacity: 0.2;
-}
-
-.input:has(> input[disabled])::placeholder,
- .input-disabled::placeholder,
- .input:disabled::placeholder,
- .input[disabled]::placeholder {
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
- --tw-placeholder-opacity: 0.2;
-}
-
-.input:has(> input[disabled]) > input[disabled] {
- cursor: not-allowed;
-}
-
-.input::-webkit-date-and-time-value {
- text-align: inherit;
-}
-
-.join > :where(*:not(:first-child)):is(.btn) {
- margin-inline-start: calc(var(--border-btn) * -1);
-}
-
-.link-primary {
- --tw-text-opacity: 1;
- color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
-}
-
-@supports (color:color-mix(in oklab,black,black)) {
- @media (hover:hover) {
- .link-primary:hover {
- color: color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 80%,black);
- }
- }
-}
-
-.link:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
-}
-
-.link:focus-visible {
- outline: 2px solid currentColor;
- outline-offset: 2px;
-}
-
-.loading {
- pointer-events: none;
- display: inline-block;
- aspect-ratio: 1 / 1;
- width: 1.5rem;
- background-color: currentColor;
- -webkit-mask-size: 100%;
- mask-size: 100%;
- -webkit-mask-repeat: no-repeat;
- mask-repeat: no-repeat;
- -webkit-mask-position: center;
- mask-position: center;
- -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
- mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
-}
-
-.loading-spinner {
- -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
- mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
-}
-
-:where(.menu li:empty) {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
- opacity: 0.1;
- margin: 0.5rem 1rem;
- height: 1px;
-}
-
-.menu :where(li ul):before {
- position: absolute;
- bottom: 0.75rem;
- inset-inline-start: 0px;
- top: 0.75rem;
- width: 1px;
- --tw-bg-opacity: 1;
- background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
- opacity: 0.1;
- content: "";
-}
-
-.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)),
-.menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
- border-radius: var(--rounded-btn, 0.5rem);
- padding-left: 1rem;
- padding-right: 1rem;
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
- text-align: start;
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
- transition-duration: 200ms;
- text-wrap: balance;
-}
-
-:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible {
- cursor: pointer;
- background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
- --tw-text-opacity: 1;
- color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
- outline: 2px solid transparent;
- outline-offset: 2px;
-}
-
-.menu li > *:not(ul, .menu-title, details, .btn):active,
-.menu li > *:not(ul, .menu-title, details, .btn).active,
-.menu li > details > summary:active {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));
- --tw-text-opacity: 1;
- color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));
-}
-
-.menu :where(li > details > summary)::-webkit-details-marker {
- display: none;
-}
-
-.menu :where(li > details > summary):after,
-.menu :where(li > .menu-dropdown-toggle):after {
- justify-self: end;
- display: block;
- margin-top: -0.5rem;
- height: 0.5rem;
- width: 0.5rem;
- transform: rotate(45deg);
- transition-property: transform, margin-top;
- transition-duration: 0.3s;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- content: "";
- transform-origin: 75% 75%;
- box-shadow: 2px 2px;
- pointer-events: none;
-}
-
-.menu :where(li > details[open] > summary):after,
-.menu :where(li > .menu-dropdown-toggle.menu-dropdown-show):after {
- transform: rotate(225deg);
- margin-top: 0;
-}
-
-.mockup-browser .mockup-browser-toolbar .input {
- position: relative;
- margin-left: auto;
- margin-right: auto;
- display: block;
- height: 1.75rem;
- width: 24rem;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
- padding-left: 2rem;
- direction: ltr;
-}
-
-.mockup-browser .mockup-browser-toolbar .input:before {
- content: "";
- position: absolute;
- left: 0.5rem;
- top: 50%;
- aspect-ratio: 1 / 1;
- height: 0.75rem;
- --tw-translate-y: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
- border-radius: 9999px;
- border-width: 2px;
- border-color: currentColor;
- opacity: 0.6;
-}
-
-.mockup-browser .mockup-browser-toolbar .input:after {
- content: "";
- position: absolute;
- left: 1.25rem;
- top: 50%;
- height: 0.5rem;
- --tw-translate-y: 25%;
- --tw-rotate: -45deg;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
- border-radius: 9999px;
- border-width: 1px;
- border-color: currentColor;
- opacity: 0.6;
-}
-
-@keyframes modal-pop {
- 0% {
- opacity: 0;
- }
-}
-
-@keyframes progress-loading {
- 50% {
- background-position-x: -115%;
- }
-}
-
-@keyframes radiomark {
- 0% {
- box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,
- 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset;
- }
-
- 50% {
- box-shadow: 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset,
- 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset;
- }
-
- 100% {
- box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,
- 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset;
- }
-}
-
-@keyframes rating-pop {
- 0% {
- transform: translateY(-0.125em);
- }
-
- 40% {
- transform: translateY(-0.125em);
- }
-
- 100% {
- transform: translateY(0);
- }
-}
-
-@keyframes skeleton {
- from {
- background-position: 150%;
- }
-
- to {
- background-position: -50%;
- }
-}
-
-@keyframes toast-pop {
- 0% {
- transform: scale(0.9);
- opacity: 0;
- }
-
- 100% {
- transform: scale(1);
- opacity: 1;
- }
-}
-
-.indicator :where(.indicator-item) {
- bottom: auto;
- inset-inline-end: 0px;
- inset-inline-start: auto;
- top: 0px;
- --tw-translate-y: -50%;
- --tw-translate-x: 50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item):where([dir="rtl"], [dir="rtl"] *) {
- --tw-translate-x: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-start) {
- inset-inline-end: auto;
- inset-inline-start: 0px;
- --tw-translate-x: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-start):where([dir="rtl"], [dir="rtl"] *) {
- --tw-translate-x: 50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-center) {
- inset-inline-end: 50%;
- inset-inline-start: 50%;
- --tw-translate-x: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-center):where([dir="rtl"], [dir="rtl"] *) {
- --tw-translate-x: 50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-end) {
- inset-inline-end: 0px;
- inset-inline-start: auto;
- --tw-translate-x: 50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-end):where([dir="rtl"], [dir="rtl"] *) {
- --tw-translate-x: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-bottom) {
- bottom: 0px;
- top: auto;
- --tw-translate-y: 50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-middle) {
- bottom: 50%;
- top: 50%;
- --tw-translate-y: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.indicator :where(.indicator-item.indicator-top) {
- bottom: auto;
- top: 0px;
- --tw-translate-y: -50%;
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-}
-
-.menu-horizontal {
- display: inline-flex;
- flex-direction: row;
-}
-
-.menu-horizontal > li:not(.menu-title) > details > ul {
- position: absolute;
-}
-
-.card-compact .card-body {
- padding: 1rem;
- font-size: 0.875rem;
- line-height: 1.25rem;
-}
-
-.card-compact .card-title {
- margin-bottom: 0.25rem;
-}
-
-.card-normal .card-body {
- padding: var(--padding-card, 2rem);
- font-size: 1rem;
- line-height: 1.5rem;
-}
-
-.card-normal .card-title {
- margin-bottom: 0.75rem;
-}
-
-.join.join-vertical > :where(*:not(:first-child)):is(.btn) {
- margin-top: calc(var(--border-btn) * -1);
-}
-
-.join.join-horizontal > :where(*:not(:first-child)):is(.btn) {
- margin-inline-start: calc(var(--border-btn) * -1);
- margin-top: 0px;
-}
-
-.menu-horizontal > li:not(.menu-title) > details > ul {
- margin-inline-start: 0px;
- margin-top: 1rem;
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
- padding-inline-end: 0.5rem;
-}
-
-.menu-horizontal > li > details > ul:before {
- content: none;
-}
-
-:where(.menu-horizontal > li:not(.menu-title) > details > ul) {
- border-radius: var(--rounded-box, 1rem);
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
- --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.mx-auto {
- margin-left: auto;
- margin-right: auto;
-}
-
-.mb-4 {
- margin-bottom: 1rem;
-}
-
-.mb-8 {
- margin-bottom: 2rem;
-}
-
-.mt-4 {
- margin-top: 1rem;
-}
-
-.mt-6 {
- margin-top: 1.5rem;
-}
-
-.block {
- display: block;
-}
-
-.flex {
- display: flex;
-}
-
-.hidden {
- display: none;
-}
-
-.min-h-\[80vh\] {
- min-height: 80vh;
-}
-
-.min-h-screen {
- min-height: 100vh;
-}
-
-.w-96 {
- width: 24rem;
-}
-
-.w-full {
- width: 100%;
-}
-
-.max-w-2xl {
- max-width: 42rem;
-}
-
-.flex-1 {
- flex: 1 1 0%;
-}
-
-.flex-none {
- flex: none;
-}
-
-.flex-col {
- flex-direction: column;
-}
-
-.items-center {
- align-items: center;
-}
-
-.justify-center {
- justify-content: center;
-}
-
-.space-y-4 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(1rem * var(--tw-space-y-reverse));
-}
-
-.space-y-8 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(2rem * var(--tw-space-y-reverse));
-}
-
-.rounded-t-none {
- border-top-left-radius: 0px;
- border-top-right-radius: 0px;
-}
-
-.bg-base-100 {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity, 1)));
-}
-
-.bg-base-200 {
- --tw-bg-opacity: 1;
- background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity, 1)));
-}
-
-.bg-gradient-to-r {
- background-image: linear-gradient(to right, var(--tw-gradient-stops));
-}
-
-.from-blue-400 {
- --tw-gradient-from: #60a5fa var(--tw-gradient-from-position);
- --tw-gradient-to: rgb(96 165 250 / 0) var(--tw-gradient-to-position);
- --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
-}
-
-.via-purple-500 {
- --tw-gradient-to: rgb(168 85 247 / 0) var(--tw-gradient-to-position);
- --tw-gradient-stops: var(--tw-gradient-from), #a855f7 var(--tw-gradient-via-position), var(--tw-gradient-to);
-}
-
-.to-pink-500 {
- --tw-gradient-to: #ec4899 var(--tw-gradient-to-position);
-}
-
-.bg-clip-text {
- -webkit-background-clip: text;
- background-clip: text;
-}
-
-.p-2 {
- padding: 0.5rem;
-}
-
-.px-1 {
- padding-left: 0.25rem;
- padding-right: 0.25rem;
-}
-
-.px-4 {
- padding-left: 1rem;
- padding-right: 1rem;
-}
-
-.py-8 {
- padding-top: 2rem;
- padding-bottom: 2rem;
-}
-
-.text-center {
- text-align: center;
-}
-
-.text-2xl {
- font-size: 1.5rem;
- line-height: 2rem;
-}
-
-.text-5xl {
- font-size: 3rem;
- line-height: 1;
-}
-
-.text-lg {
- font-size: 1.125rem;
- line-height: 1.75rem;
-}
-
-.text-sm {
- font-size: 0.875rem;
- line-height: 1.25rem;
-}
-
-.text-xl {
- font-size: 1.25rem;
- line-height: 1.75rem;
-}
-
-.font-bold {
- font-weight: 700;
-}
-
-.text-gray-400 {
- --tw-text-opacity: 1;
- color: rgb(156 163 175 / var(--tw-text-opacity, 1));
-}
-
-.text-transparent {
- color: transparent;
-}
-
-.shadow-xl {
- --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
\ No newline at end of file
diff --git a/src/server/mod.rs b/src/server/mod.rs
index c5070ee..e8f1d97 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -1,8 +1,9 @@
use crate::rabbitmq::consumer::RabbitMQConsumer;
use crate::rabbitmq::publisher::RabbitMQProducer;
use crate::storage::db::SurrealDbClient;
+use minijinja_autoreload::AutoReloader;
use std::sync::Arc;
-use tera::Tera;
+// use tera::Tera;
pub mod middleware_api_auth;
pub mod routes;
@@ -12,6 +13,7 @@ pub struct AppState {
pub rabbitmq_producer: Arc,
pub rabbitmq_consumer: Arc,
pub surreal_db_client: Arc,
- pub tera: Arc,
+ // pub tera: Arc,
pub openai_client: Arc>,
+ pub templates: Arc,
}
diff --git a/src/server/routes/auth.rs b/src/server/routes/auth.rs
index e0b61f3..c26c7c6 100644
--- a/src/server/routes/auth.rs
+++ b/src/server/routes/auth.rs
@@ -3,6 +3,7 @@ use axum::{
response::{Html, IntoResponse},
Form,
};
+use axum_htmx::HxBoosted;
use axum_session_auth::AuthSession;
use axum_session_surreal::SessionSurrealPool;
use serde::{Deserialize, Serialize};
@@ -16,13 +17,17 @@ pub struct SignupParams {
pub password: String,
}
-pub async fn show_signup_form(State(state): State) -> Html {
- let context = tera::Context::new();
- let html = state
- .tera
- .render("auth/signup.html", &context)
- .unwrap_or_else(|_| "Error rendering template ".to_string());
- Html(html)
+pub async fn show_signup_form(
+ State(state): State,
+ HxBoosted(boosted): HxBoosted,
+) -> Html {
+ let mut context = tera::Context::new();
+ context.insert("boosted", &boosted);
+ // let html = state
+ // .tera
+ // .render("auth/signup_form.html", &context)
+ // .unwrap_or_else(|_| "Error rendering template ".to_string());
+ Html("html".to_string())
}
pub async fn signup_handler(
diff --git a/src/server/routes/index.rs b/src/server/routes/index.rs
index c544ece..82dd44e 100644
--- a/src/server/routes/index.rs
+++ b/src/server/routes/index.rs
@@ -1,9 +1,11 @@
use axum::{extract::State, response::Html};
use axum_session_auth::AuthSession;
use axum_session_surreal::SessionSurrealPool;
+use minijinja::context;
use serde_json::json;
-use surrealdb::{engine::any::Any, Surreal};
+use surrealdb::{engine::any::Any, sql::Relation, Surreal};
use tera::Context;
+// use tera::Context;
use tracing::info;
use crate::{error::ApiError, server::AppState, storage::types::user::User};
@@ -18,14 +20,21 @@ pub async fn index_handler(
let queue_length = state.rabbitmq_consumer.get_queue_length().await?;
- let output = state
- .tera
- .render(
- "index.html",
- &Context::from_value(json!({"adjective": "CRAYCRAY", "queue_length": queue_length}))
- .unwrap(),
- )
- .unwrap();
+ // let output = state
+ // .tera
+ // .render(
+ // "index.html",
+ // &Context::from_value(json!({"adjective": "CRAYCRAY", "queue_length": queue_length}))
+ // .unwrap(),
+ // )
+ // .unwrap();
+
+ // Ok(output.into())
+ //
+ let env = state.templates.acquire_env().unwrap();
+ let context = context!(queue_length => "2000");
+ let tmpl = env.get_template("index.html").unwrap();
+ let output = tmpl.render(context).unwrap();
Ok(output.into())
}
diff --git a/src/server/routes/search_result.rs b/src/server/routes/search_result.rs
index b348ce3..992a58f 100644
--- a/src/server/routes/search_result.rs
+++ b/src/server/routes/search_result.rs
@@ -37,16 +37,17 @@ pub async fn search_result_handler(
)
.await?;
- let output = state
- .tera
- .render(
- "search_result.html",
- &Context::from_value(
- json!({"result": answer.content, "references": answer.references}),
- )
- .unwrap(),
- )
- .unwrap();
+ Ok(Html("Hello".to_string()))
+ // let output = state
+ // .tera
+ // .render(
+ // "search_result.html",
+ // &Context::from_value(
+ // json!({"result": answer.content, "references": answer.references}),
+ // )
+ // .unwrap(),
+ // )
+ // .unwrap();
- Ok(output.into())
+ // Ok(output.into())
}
diff --git a/src/server/templates/auth/signup.html b/src/server/templates/auth/signup.html
deleted file mode 100644
index 4761c57..0000000
--- a/src/server/templates/auth/signup.html
+++ /dev/null
@@ -1,62 +0,0 @@
-{% extends "base.html" %}
-
-{% block content %}
-
-
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index 354ad6e..f4b1d3d 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -8,7 +8,7 @@ module.exports = {
},
plugins: [require('daisyui')],
daisyui: {
- themes: ["dark"],
+ themes: ["light", "dark"],
},
}
diff --git a/templates/auth/login.html b/templates/auth/login.html
new file mode 100644
index 0000000..f508d35
--- /dev/null
+++ b/templates/auth/login.html
@@ -0,0 +1,47 @@
+{% block content %}
+
+
Sign in to your account
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/auth/signup.html b/templates/auth/signup.html
new file mode 100644
index 0000000..e69de29
diff --git a/templates/auth/signup_form.html b/templates/auth/signup_form.html
new file mode 100644
index 0000000..a3e5eca
--- /dev/null
+++ b/templates/auth/signup_form.html
@@ -0,0 +1,43 @@
+{% block content %}
+
+
+
Create your account
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/base_template.html b/templates/base_template.html
new file mode 100644
index 0000000..6bb170e
--- /dev/null
+++ b/templates/base_template.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ {% block title %}minnet{% endblock %}
+
+
+ {% block head %}{% endblock %}
+
+{% block body %}{% endblock %}
+
+
\ No newline at end of file
diff --git a/templates/body_base.html b/templates/body_base.html
new file mode 100644
index 0000000..edd12e8
--- /dev/null
+++ b/templates/body_base.html
@@ -0,0 +1,31 @@
+{% extends "head_base.html" %}
+
+{% block body %}
+
+
+
+
+
+
+
+
+
+
+ {% block content %}{% endblock %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/server/templates/base.html b/templates/full_body_template.html
similarity index 57%
rename from src/server/templates/base.html
rename to templates/full_body_template.html
index ec8fa87..ddf7df0 100644
--- a/src/server/templates/base.html
+++ b/templates/full_body_template.html
@@ -1,23 +1,13 @@
-
-
-
-
-
-
- {% block title %}radien{% endblock %}
-
-
-
-
\ No newline at end of file
diff --git a/templates/head_base.html b/templates/head_base.html
new file mode 100644
index 0000000..6bb170e
--- /dev/null
+++ b/templates/head_base.html
@@ -0,0 +1,14 @@
+
+
+
+