+1
-1
.gitignore
+1
-1
.gitignore
+55
-3
Cargo.lock
+55
-3
Cargo.lock
···
240
240
source = "registry+https://github.com/rust-lang/crates.io-index"
241
241
checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
242
242
dependencies = [
243
-
"axum-core",
243
+
"axum-core 0.5.2",
244
244
"bytes",
245
245
"form_urlencoded",
246
246
"futures-util",
···
270
270
271
271
[[package]]
272
272
name = "axum-core"
273
+
version = "0.4.5"
274
+
source = "registry+https://github.com/rust-lang/crates.io-index"
275
+
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
276
+
dependencies = [
277
+
"async-trait",
278
+
"bytes",
279
+
"futures-util",
280
+
"http",
281
+
"http-body",
282
+
"http-body-util",
283
+
"mime",
284
+
"pin-project-lite",
285
+
"rustversion",
286
+
"sync_wrapper",
287
+
"tower-layer",
288
+
"tower-service",
289
+
]
290
+
291
+
[[package]]
292
+
name = "axum-core"
273
293
version = "0.5.2"
274
294
source = "registry+https://github.com/rust-lang/crates.io-index"
275
295
checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
···
289
309
]
290
310
291
311
[[package]]
312
+
name = "axum-embed"
313
+
version = "0.1.0"
314
+
source = "registry+https://github.com/rust-lang/crates.io-index"
315
+
checksum = "077959a7f8cf438676af90b483304528eb7e16eadadb7f44e9ada4f9dceb9e62"
316
+
dependencies = [
317
+
"axum-core 0.4.5",
318
+
"chrono",
319
+
"http",
320
+
"mime_guess",
321
+
"rust-embed",
322
+
"tower-service",
323
+
]
324
+
325
+
[[package]]
292
326
name = "backtrace"
293
327
version = "0.3.75"
294
328
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1780
1814
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
1781
1815
1782
1816
[[package]]
1817
+
name = "mime_guess"
1818
+
version = "2.0.5"
1819
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1820
+
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
1821
+
dependencies = [
1822
+
"mime",
1823
+
"unicase",
1824
+
]
1825
+
1826
+
[[package]]
1783
1827
name = "miniz_oxide"
1784
1828
version = "0.8.9"
1785
1829
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3271
3315
source = "registry+https://github.com/rust-lang/crates.io-index"
3272
3316
checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36"
3273
3317
dependencies = [
3274
-
"axum-core",
3318
+
"axum-core 0.5.2",
3275
3319
"cookie",
3276
3320
"futures-util",
3277
3321
"http",
···
3337
3381
checksum = "ce8cce604865576b7751b7a6bc3058f754569a60d689328bb74c52b1d87e355b"
3338
3382
dependencies = [
3339
3383
"async-trait",
3340
-
"axum-core",
3384
+
"axum-core 0.5.2",
3341
3385
"base64",
3342
3386
"futures",
3343
3387
"http",
···
3453
3497
version = "0.1.7"
3454
3498
source = "registry+https://github.com/rust-lang/crates.io-index"
3455
3499
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
3500
+
3501
+
[[package]]
3502
+
name = "unicase"
3503
+
version = "2.8.1"
3504
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3505
+
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
3456
3506
3457
3507
[[package]]
3458
3508
name = "unicode-bidi"
···
3667
3717
"atrium-identity",
3668
3718
"atrium-oauth",
3669
3719
"axum",
3720
+
"axum-embed",
3670
3721
"bb8",
3671
3722
"bb8-redis",
3672
3723
"chrono",
···
3675
3726
"log",
3676
3727
"pool",
3677
3728
"redis",
3729
+
"rust-embed",
3678
3730
"serde",
3679
3731
"serde_json",
3680
3732
"shared",
+1
-1
compose.dev.yml
+1
-1
compose.dev.yml
+3
-1
web/Cargo.toml
+3
-1
web/Cargo.toml
+28
web/assets/css/base.css
+28
web/assets/css/base.css
···
1
+
@import "tailwindcss";
2
+
3
+
@plugin "@tailwindcss/typography";
4
+
5
+
@plugin "daisyui" {
6
+
themes: light --default, dark --prefersdark, forest;
7
+
}
8
+
9
+
@layer base {
10
+
body {
11
+
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
12
+
}
13
+
}
14
+
15
+
.advent-header {
16
+
/*background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);*/
17
+
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
18
+
}
19
+
20
+
.advent-title {
21
+
/* Festive Christmas gradient: deep red โ bright red โ gold โ green โ deep green */
22
+
background: linear-gradient(90deg, #b91c1c 0%, #ef4444 22%, #f59e0b 50%, #22c55e 78%, #065f46 100%);
23
+
-webkit-background-clip: text;
24
+
background-clip: text;
25
+
-webkit-text-fill-color: transparent;
26
+
font-weight: 800;
27
+
letter-spacing: -0.025em;
28
+
}
+2
web/build/style.css
+2
web/build/style.css
···
1
+
/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */
2
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-9xl:8rem;--text-9xl--line-height:1;--font-weight-semibold:600;--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,Helvetica,Arial,Apple Color Emoji,Segoe UI Emoji}:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@media (prefers-color-scheme:dark){:root:not([data-theme]){color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}}:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=forest]:checked),[data-theme=forest]{color-scheme:dark;--color-base-100:oklch(20.84% .008 17.911);--color-base-200:oklch(18.522% .007 17.911);--color-base-300:oklch(16.203% .007 17.911);--color-base-content:oklch(83.768% .001 17.911);--color-primary:oklch(68.628% .185 148.958);--color-primary-content:oklch(0% 0 0);--color-secondary:oklch(69.776% .135 168.327);--color-secondary-content:oklch(13.955% .027 168.327);--color-accent:oklch(70.628% .119 185.713);--color-accent-content:oklch(14.125% .023 185.713);--color-neutral:oklch(30.698% .039 171.364);--color-neutral-content:oklch(86.139% .007 171.364);--color-info:oklch(72.06% .191 231.6);--color-info-content:oklch(0% 0 0);--color-success:oklch(64.8% .15 160);--color-success-content:oklch(0% 0 0);--color-warning:oklch(84.71% .199 83.87);--color-warning-content:oklch(0% 0 0);--color-error:oklch(71.76% .221 22.18);--color-error-content:oklch(0% 0 0);--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}:root{--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");scrollbar-color:currentColor #0000}@supports (color:color-mix(in lab, red, red)){:root{scrollbar-color:color-mix(in oklch,currentColor 35%,#0000)#0000}}@property --radialprogress{syntax: "<percentage>"; inherits: true; initial-value: 0%;}:root:not(span){overflow:var(--page-overflow)}:root{--page-scroll-bg-on:linear-gradient(var(--root-bg),var(--root-bg))var(--root-bg)}@supports (color:color-mix(in lab, red, red)){:root{--page-scroll-bg-on:linear-gradient(var(--root-bg),var(--root-bg))color-mix(in srgb,var(--root-bg),oklch(0% 0 0) calc(var(--page-has-backdrop,0)*40%))}}:root{--page-scroll-transition-on:background-color .3s ease-out;transition:var(--page-scroll-transition);scrollbar-gutter:var(--page-scroll-gutter,unset);scrollbar-gutter:if(style(--page-has-scroll: 1): var(--page-scroll-gutter,unset); else: unset)}:root:root{background:var(--page-scroll-bg,var(--root-bg,var(--color-base-100)))}@keyframes set-page-has-scroll{0%,to{--page-has-scroll:1}}:root,[data-theme]{background-color:var(--root-bg,var(--color-base-100));color:var(--color-base-content)}:where(:root,[data-theme]){--root-bg:var(--color-base-100)}}@layer components;@layer utilities{@layer daisyui.component{:where(.btn){width:unset}.btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;webkit-user-select:none;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));touch-action:manipulation;box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:var(--btn-bg);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}@supports (color:color-mix(in lab, red, red)){.btn{--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%))}}.btn{--btn-shadow:0 3px 2px -2px var(--btn-bg),0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn{--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000)}}.btn{--btn-noise:var(--fx-noise)}@media (hover:hover){.btn:hover{--btn-bg:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}}.btn:focus-visible,.btn:has(:focus-visible){isolation:isolate;outline-width:2px;outline-style:solid}.btn:active:not(.btn-active){--btn-bg:var(--btn-color,var(--color-base-200));translate:0 .5px}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%)}}.btn:active:not(.btn-active){--btn-border:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.btn:active:not(.btn-active){--btn-shadow:0 0 0 0 oklch(0% 0 0/0),0 0 0 0 oklch(0% 0 0/0)}.btn:is(input[type=checkbox],input[type=radio]){appearance:none}.btn:is(input[type=checkbox],input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem)*6);background-color:currentColor;display:inline-block;-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");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.validator-hint{visibility:hidden;margin-top:.5rem;font-size:.75rem}.validator:user-valid{--input-color:var(--color-success)}.validator:user-valid:focus{--input-color:var(--color-success)}.validator:user-valid:checked{--input-color:var(--color-success)}.validator:user-valid[aria-checked=true]{--input-color:var(--color-success)}.validator:user-valid:focus-within{--input-color:var(--color-success)}.validator:has(:user-valid){--input-color:var(--color-success)}.validator:has(:user-valid):focus{--input-color:var(--color-success)}.validator:has(:user-valid):checked{--input-color:var(--color-success)}.validator:has(:user-valid)[aria-checked=true]{--input-color:var(--color-success)}.validator:has(:user-valid):focus-within{--input-color:var(--color-success)}.validator:user-invalid{--input-color:var(--color-error)}.validator:user-invalid:focus{--input-color:var(--color-error)}.validator:user-invalid:checked{--input-color:var(--color-error)}.validator:user-invalid[aria-checked=true]{--input-color:var(--color-error)}.validator:user-invalid:focus-within{--input-color:var(--color-error)}.validator:user-invalid~.validator-hint{visibility:visible;color:var(--color-error)}.validator:has(:user-invalid){--input-color:var(--color-error)}.validator:has(:user-invalid):focus{--input-color:var(--color-error)}.validator:has(:user-invalid):checked{--input-color:var(--color-error)}.validator:has(:user-invalid)[aria-checked=true]{--input-color:var(--color-error)}.validator:has(:user-invalid):focus-within{--input-color:var(--color-error)}.validator:has(:user-invalid)~.validator-hint{visibility:visible;color:var(--color-error)}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))),:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):focus,:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):checked,:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))[aria-checked=true],:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):focus-within{--input-color:var(--color-error)}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))~.validator-hint{visibility:visible;color:var(--color-error)}.input{cursor:text;border:var(--border)solid #0000;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);font-size:max(var(--font-size,.875rem),.875rem);touch-action:manipulation;border-color:var(--input-color);box-shadow:0 1px var(--input-color)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab, red, red)){.input{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset}}.input{--size:calc(var(--size-field,.25rem)*10);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.input{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.input:where(input){display:inline-flex}.input :where(input){appearance:none;background-color:#0000;border:none;width:100%;height:100%;display:inline-flex}.input :where(input):focus,.input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus,.input :where(input):focus-within{outline-offset:2px;outline:2px solid #0000}}.input :where(input[type=url]),.input :where(input[type=email]){direction:ltr}.input :where(input[type=date]){display:inline-flex}.input:focus,.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab, red, red)){.input:focus,.input:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.input:focus,.input:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}@media (pointer:coarse){@supports (-webkit-touch-callout:none){.input:focus,.input:focus-within{--font-size:1rem}}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input)::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input)::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{box-shadow:none}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.input:has(>input[type=date]) :where(input[type=date]){webkit-appearance:none;appearance:none;display:inline-flex}.input:has(>input[type=date]) input[type=date]::-webkit-calendar-picker-indicator{cursor:pointer;width:1em;height:1em;position:absolute;inset-inline-end:.75em}.navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid #0000;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.card:focus{outline-offset:2px;outline:2px solid #0000}}.card:focus-visible{outline-color:currentColor}.card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.card figure{justify-content:center;align-items:center;display:flex}.card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.card:has(>:checked){outline:2px solid}.progress{appearance:none;border-radius:var(--radius-box);background-color:currentColor;width:100%;height:.5rem;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.progress{background-color:color-mix(in oklab,currentcolor 20%,transparent)}}.progress{color:var(--color-base-content)}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%}@media (prefers-reduced-motion:no-preference){.progress:indeterminate{animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:#0000}@media (prefers-reduced-motion:no-preference){.progress:indeterminate::-moz-progress-bar{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:#0000}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}.hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.hero>*{grid-row-start:1;grid-column-start:1}.breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li{align-items:center;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:hover{text-decoration-line:underline}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{outline-offset:2px;outline:2px solid #0000}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus-visible{outline-offset:2px;outline:2px solid}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li+:before{content:"";opacity:.4;background-color:#0000;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li)+:before{rotate:-135deg}.fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:var(--color-base-content);width:.5rem;height:.5rem;display:inline-block}@supports (color:color-mix(in lab, red, red)){.status{background-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.status{vertical-align:middle;color:#0000004d;background-position:50%;background-repeat:no-repeat}@supports (color:color-mix(in lab, red, red)){.status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.status{background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),#0000);box-shadow:0 2px 3px -1px}@supports (color:color-mix(in lab, red, red)){.status{box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),#0000)}}.badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}.navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.card-body :where(p){flex-grow:1}.alert{--alert-border-color:var(--color-base-200);border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px #000,0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));border-style:solid;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}@supports (color:color-mix(in lab, red, red)){.alert{box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),#0000),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08))}}.alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}}@layer daisyui.modifier{.btn:disabled:not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:disabled:not(.btn-link,.btn-ghost){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}}.btn:disabled:not(.btn-link,.btn-ghost){box-shadow:none}.btn:disabled{pointer-events:none;--btn-border:#0000;--btn-noise:none;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:disabled{--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}.btn[disabled]:not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn[disabled]:not(.btn-link,.btn-ghost){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}}.btn[disabled]:not(.btn-link,.btn-ghost){box-shadow:none}.btn[disabled]{pointer-events:none;--btn-border:#0000;--btn-noise:none;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn[disabled]{--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}:where(.navbar){position:relative}.input-md{--size:calc(var(--size-field,.25rem)*10);font-size:max(var(--font-size,.875rem),.875rem)}.input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.alert-error{color:var(--color-error-content);--alert-border-color:var(--color-error);--alert-color:var(--color-error)}.alert-info{color:var(--color-info-content);--alert-border-color:var(--color-info);--alert-color:var(--color-info)}.alert-success{color:var(--color-success-content);--alert-border-color:var(--color-success);--alert-color:var(--color-success)}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible,input:checked:not(.filter .btn)){--btn-shadow:"";--btn-bg:#0000;--btn-border:#0000;--btn-noise:none}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible,input:checked:not(.filter .btn)):not(:disabled,[disabled],.btn-disabled){--btn-fg:var(--btn-color,currentColor);outline-color:currentColor}@media (hover:none){.btn-ghost:not(.btn-active,:active,:focus-visible,input:checked:not(.filter .btn)):hover{--btn-shadow:"";--btn-bg:#0000;--btn-fg:var(--btn-color,currentColor);--btn-border:#0000;--btn-noise:none;outline-color:currentColor}}.btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}}.validator:user-invalid~.validator-hint{display:revert-layer}.validator:has(:user-invalid)~.validator-hint{display:revert-layer}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))~.validator-hint{display:revert-layer}.static{position:static}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.join-item:where(:not(:first-child,:disabled,[disabled],.btn-disabled)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.join-item:where(:is(:disabled,[disabled],.btn-disabled)){border-width:var(--border,1px)0 var(--border,1px)var(--border,1px)}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"โ""โ""โ""โ";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-lg{font-size:1.125rem;line-height:1.77778}.prose-lg :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em}.prose-lg :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.09091em;margin-bottom:1.09091em;font-size:1.22222em;line-height:1.45455}.prose-lg :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.66667em;margin-bottom:1.66667em;padding-inline-start:1em}.prose-lg :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:.833333em;font-size:2.66667em;line-height:1}.prose-lg :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.86667em;margin-bottom:1.06667em;font-size:1.66667em;line-height:1.33333}.prose-lg :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.66667em;margin-bottom:.666667em;font-size:1.33333em;line-height:1.5}.prose-lg :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:.444444em;line-height:1.55556}.prose-lg :where(img):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-lg :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.222222em;padding-inline-end:.444444em;padding-bottom:.222222em;border-radius:.3125rem;padding-inline-start:.444444em;font-size:.888889em}.prose-lg :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em}.prose-lg :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.866667em}.prose-lg :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em}.prose-lg :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:1em;padding-inline-end:1.5em;padding-bottom:1em;border-radius:.375rem;margin-top:2em;margin-bottom:2em;padding-inline-start:1.5em;font-size:.888889em;line-height:1.75}.prose-lg :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em;padding-inline-start:1.55556em}.prose-lg :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;margin-bottom:.666667em}.prose-lg :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.444444em}.prose-lg :where(.prose-lg>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em}.prose-lg :where(.prose-lg>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(.prose-lg>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.33333em}.prose-lg :where(.prose-lg>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(.prose-lg>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.33333em}.prose-lg :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em}.prose-lg :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em}.prose-lg :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;padding-inline-start:1.55556em}.prose-lg :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:3.11111em;margin-bottom:3.11111em}.prose-lg :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-lg :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em;line-height:1.5}.prose-lg :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:.75em;padding-bottom:.75em;padding-inline-start:.75em}.prose-lg :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-lg :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-lg :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.75em;padding-inline-end:.75em;padding-bottom:.75em;padding-inline-start:.75em}.prose-lg :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-lg :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-lg :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-lg :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1em;font-size:.888889em;line-height:1.5}.prose-lg :where(.prose-lg>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-lg :where(.prose-lg>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.alert{border-width:var(--border);border-color:var(--alert-border-color,var(--color-base-200))}.join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join>.join-item:where(:first-child),.join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join>.join-item:where(:last-child),.join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join>.join-item:where(:only-child),.join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}:root .prose{--tw-prose-body:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-body:color-mix(in oklab,var(--color-base-content)80%,#0000)}}:root .prose{--tw-prose-headings:var(--color-base-content);--tw-prose-lead:var(--color-base-content);--tw-prose-links:var(--color-base-content);--tw-prose-bold:var(--color-base-content);--tw-prose-counters:var(--color-base-content);--tw-prose-bullets:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-bullets:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-hr:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-hr:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-quotes:var(--color-base-content);--tw-prose-quote-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-quote-borders:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-captions:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-captions:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-code:var(--color-base-content);--tw-prose-pre-code:var(--color-neutral-content);--tw-prose-pre-bg:var(--color-neutral);--tw-prose-th-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-th-borders:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-td-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-td-borders:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-kbd:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-kbd:color-mix(in oklab,var(--color-base-content)80%,#0000)}}:root .prose :where(code):not(pre>code){background-color:var(--color-base-200);border-radius:var(--radius-selector);border:var(--border)solid var(--color-base-300);font-weight:inherit;padding-block:.2em;padding-inline:.5em}:root .prose :where(code):not(pre>code):before,:root .prose :where(code):not(pre>code):after{display:none}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-24{height:calc(var(--spacing)*24)}.min-h-\[60vh\]{min-height:60vh}.min-h-screen{min-height:100vh}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.shrink-0{flex-shrink:0}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.justify-end{justify-content:flex-end}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.bg-base-100{background-color:var(--color-base-100)}.stroke-current{stroke:currentColor}.px-4{padding-inline:calc(var(--spacing)*4)}.py-6{padding-block:calc(var(--spacing)*6)}.py-8{padding-block:calc(var(--spacing)*8)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-9xl{font-size:var(--text-9xl);line-height:var(--tw-leading,var(--text-9xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-base-content{color:var(--color-base-content)}.text-white{color:var(--color-white)}.prose :where(.btn-link):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-line:none}.opacity-70{opacity:.7}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@layer daisyui.modifier.color{.btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}}@media (min-width:40rem){.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:48rem){.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:64rem){.lg\:ml-8{margin-left:calc(var(--spacing)*8)}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:flex-row-reverse{flex-direction:row-reverse}.lg\:text-left{text-align:left}}}.advent-header{box-shadow:0 4px 6px -1px #0000001a}.advent-title{-webkit-text-fill-color:transparent;letter-spacing:-.025em;background:linear-gradient(90deg,#b91c1c 0%,#ef4444 22%,#f59e0b 50%,#22c55e 78%,#065f46 100%);-webkit-background-clip:text;background-clip:text;font-weight:800}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@keyframes dropdown{0%{opacity:0}}@keyframes radio{0%{padding:5px}50%{padding:3px}}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@keyframes rotator{89.9999%,to{--first-item-position:0 0%}90%,99.9999%{--first-item-position:0 calc(var(--items)*100%)}to{translate:0 -100%}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}@keyframes progress{50%{background-position-x:-115%}}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
+49
web/build.rs
+49
web/build.rs
···
1
+
use std::process::Command;
2
+
3
+
fn main() {
4
+
std::fs::create_dir_all("build").expect("failed to create build directory");
5
+
6
+
Command::new("npx")
7
+
.args([
8
+
"@tailwindcss/cli",
9
+
"-m",
10
+
"-i",
11
+
"assets/css/base.css",
12
+
"-o",
13
+
"public/css/style.css",
14
+
])
15
+
.status()
16
+
.expect("failed to run tailwindcss");
17
+
18
+
// Command::new("bun")
19
+
// .args([
20
+
// "build",
21
+
// "--minify",
22
+
// "--outdir=build",
23
+
// "--entry-naming",
24
+
// "[name].[hash].[ext]",
25
+
// "--asset-naming",
26
+
// "[name].[hash].[ext]",
27
+
// "./assets/scripts/index.ts",
28
+
// ])
29
+
// .status()
30
+
// .expect("failed to run bun");
31
+
32
+
copy_files("public");
33
+
}
34
+
35
+
fn copy_files(dir: &str) {
36
+
for entry in std::fs::read_dir(dir).expect("failed to read dir `public`") {
37
+
let entry = entry.expect("failed to read entry");
38
+
39
+
if entry.file_type().unwrap().is_dir() {
40
+
copy_files(entry.path().to_str().unwrap());
41
+
} else {
42
+
let path = entry.path();
43
+
let filename = path.file_name().unwrap().to_str().unwrap();
44
+
let dest = format!("build/{}", filename);
45
+
46
+
std::fs::copy(path, dest).expect("failed to copy file");
47
+
}
48
+
}
49
+
}
+21
web/package.json
+21
web/package.json
···
1
+
{
2
+
"name": "web",
3
+
"version": "1.0.0",
4
+
"description": "",
5
+
"main": "index.js",
6
+
"scripts": {
7
+
"test": "echo \"Error: no test specified\" && exit 1"
8
+
},
9
+
"keywords": [],
10
+
"author": "",
11
+
"license": "ISC",
12
+
"packageManager": "pnpm@10.16.1",
13
+
"dependencies": {
14
+
"@tailwindcss/cli": "^4.1.17",
15
+
"tailwindcss": "^4.1.17"
16
+
},
17
+
"devDependencies": {
18
+
"@tailwindcss/typography": "^0.5.19",
19
+
"daisyui": "^5.5.0"
20
+
}
21
+
}
+651
web/pnpm-lock.yaml
+651
web/pnpm-lock.yaml
···
1
+
lockfileVersion: '9.0'
2
+
3
+
settings:
4
+
autoInstallPeers: true
5
+
excludeLinksFromLockfile: false
6
+
7
+
importers:
8
+
9
+
.:
10
+
dependencies:
11
+
'@tailwindcss/cli':
12
+
specifier: ^4.1.17
13
+
version: 4.1.17
14
+
tailwindcss:
15
+
specifier: ^4.1.17
16
+
version: 4.1.17
17
+
devDependencies:
18
+
'@tailwindcss/typography':
19
+
specifier: ^0.5.19
20
+
version: 0.5.19(tailwindcss@4.1.17)
21
+
daisyui:
22
+
specifier: ^5.5.0
23
+
version: 5.5.0
24
+
25
+
packages:
26
+
27
+
'@jridgewell/gen-mapping@0.3.13':
28
+
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
29
+
30
+
'@jridgewell/remapping@2.3.5':
31
+
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
32
+
33
+
'@jridgewell/resolve-uri@3.1.2':
34
+
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
35
+
engines: {node: '>=6.0.0'}
36
+
37
+
'@jridgewell/sourcemap-codec@1.5.5':
38
+
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
39
+
40
+
'@jridgewell/trace-mapping@0.3.31':
41
+
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
42
+
43
+
'@parcel/watcher-android-arm64@2.5.1':
44
+
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
45
+
engines: {node: '>= 10.0.0'}
46
+
cpu: [arm64]
47
+
os: [android]
48
+
49
+
'@parcel/watcher-darwin-arm64@2.5.1':
50
+
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
51
+
engines: {node: '>= 10.0.0'}
52
+
cpu: [arm64]
53
+
os: [darwin]
54
+
55
+
'@parcel/watcher-darwin-x64@2.5.1':
56
+
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
57
+
engines: {node: '>= 10.0.0'}
58
+
cpu: [x64]
59
+
os: [darwin]
60
+
61
+
'@parcel/watcher-freebsd-x64@2.5.1':
62
+
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
63
+
engines: {node: '>= 10.0.0'}
64
+
cpu: [x64]
65
+
os: [freebsd]
66
+
67
+
'@parcel/watcher-linux-arm-glibc@2.5.1':
68
+
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
69
+
engines: {node: '>= 10.0.0'}
70
+
cpu: [arm]
71
+
os: [linux]
72
+
73
+
'@parcel/watcher-linux-arm-musl@2.5.1':
74
+
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
75
+
engines: {node: '>= 10.0.0'}
76
+
cpu: [arm]
77
+
os: [linux]
78
+
79
+
'@parcel/watcher-linux-arm64-glibc@2.5.1':
80
+
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
81
+
engines: {node: '>= 10.0.0'}
82
+
cpu: [arm64]
83
+
os: [linux]
84
+
85
+
'@parcel/watcher-linux-arm64-musl@2.5.1':
86
+
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
87
+
engines: {node: '>= 10.0.0'}
88
+
cpu: [arm64]
89
+
os: [linux]
90
+
91
+
'@parcel/watcher-linux-x64-glibc@2.5.1':
92
+
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
93
+
engines: {node: '>= 10.0.0'}
94
+
cpu: [x64]
95
+
os: [linux]
96
+
97
+
'@parcel/watcher-linux-x64-musl@2.5.1':
98
+
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
99
+
engines: {node: '>= 10.0.0'}
100
+
cpu: [x64]
101
+
os: [linux]
102
+
103
+
'@parcel/watcher-win32-arm64@2.5.1':
104
+
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
105
+
engines: {node: '>= 10.0.0'}
106
+
cpu: [arm64]
107
+
os: [win32]
108
+
109
+
'@parcel/watcher-win32-ia32@2.5.1':
110
+
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
111
+
engines: {node: '>= 10.0.0'}
112
+
cpu: [ia32]
113
+
os: [win32]
114
+
115
+
'@parcel/watcher-win32-x64@2.5.1':
116
+
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
117
+
engines: {node: '>= 10.0.0'}
118
+
cpu: [x64]
119
+
os: [win32]
120
+
121
+
'@parcel/watcher@2.5.1':
122
+
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
123
+
engines: {node: '>= 10.0.0'}
124
+
125
+
'@tailwindcss/cli@4.1.17':
126
+
resolution: {integrity: sha512-jUIxcyUNlCC2aNPnyPEWU/L2/ik3pB4fF3auKGXr8AvN3T3OFESVctFKOBoPZQaZJIeUpPn1uCLp0MRxuek8gg==}
127
+
hasBin: true
128
+
129
+
'@tailwindcss/node@4.1.17':
130
+
resolution: {integrity: sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==}
131
+
132
+
'@tailwindcss/oxide-android-arm64@4.1.17':
133
+
resolution: {integrity: sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==}
134
+
engines: {node: '>= 10'}
135
+
cpu: [arm64]
136
+
os: [android]
137
+
138
+
'@tailwindcss/oxide-darwin-arm64@4.1.17':
139
+
resolution: {integrity: sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==}
140
+
engines: {node: '>= 10'}
141
+
cpu: [arm64]
142
+
os: [darwin]
143
+
144
+
'@tailwindcss/oxide-darwin-x64@4.1.17':
145
+
resolution: {integrity: sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==}
146
+
engines: {node: '>= 10'}
147
+
cpu: [x64]
148
+
os: [darwin]
149
+
150
+
'@tailwindcss/oxide-freebsd-x64@4.1.17':
151
+
resolution: {integrity: sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==}
152
+
engines: {node: '>= 10'}
153
+
cpu: [x64]
154
+
os: [freebsd]
155
+
156
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17':
157
+
resolution: {integrity: sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==}
158
+
engines: {node: '>= 10'}
159
+
cpu: [arm]
160
+
os: [linux]
161
+
162
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.17':
163
+
resolution: {integrity: sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==}
164
+
engines: {node: '>= 10'}
165
+
cpu: [arm64]
166
+
os: [linux]
167
+
168
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.17':
169
+
resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==}
170
+
engines: {node: '>= 10'}
171
+
cpu: [arm64]
172
+
os: [linux]
173
+
174
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.17':
175
+
resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==}
176
+
engines: {node: '>= 10'}
177
+
cpu: [x64]
178
+
os: [linux]
179
+
180
+
'@tailwindcss/oxide-linux-x64-musl@4.1.17':
181
+
resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==}
182
+
engines: {node: '>= 10'}
183
+
cpu: [x64]
184
+
os: [linux]
185
+
186
+
'@tailwindcss/oxide-wasm32-wasi@4.1.17':
187
+
resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==}
188
+
engines: {node: '>=14.0.0'}
189
+
cpu: [wasm32]
190
+
bundledDependencies:
191
+
- '@napi-rs/wasm-runtime'
192
+
- '@emnapi/core'
193
+
- '@emnapi/runtime'
194
+
- '@tybys/wasm-util'
195
+
- '@emnapi/wasi-threads'
196
+
- tslib
197
+
198
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.17':
199
+
resolution: {integrity: sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==}
200
+
engines: {node: '>= 10'}
201
+
cpu: [arm64]
202
+
os: [win32]
203
+
204
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.17':
205
+
resolution: {integrity: sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==}
206
+
engines: {node: '>= 10'}
207
+
cpu: [x64]
208
+
os: [win32]
209
+
210
+
'@tailwindcss/oxide@4.1.17':
211
+
resolution: {integrity: sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==}
212
+
engines: {node: '>= 10'}
213
+
214
+
'@tailwindcss/typography@0.5.19':
215
+
resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
216
+
peerDependencies:
217
+
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
218
+
219
+
braces@3.0.3:
220
+
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
221
+
engines: {node: '>=8'}
222
+
223
+
cssesc@3.0.0:
224
+
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
225
+
engines: {node: '>=4'}
226
+
hasBin: true
227
+
228
+
daisyui@5.5.0:
229
+
resolution: {integrity: sha512-lfeimNM3U1FzjfBotV3iTrxNfBEncHs7kMP62lTLghmO99v7HVZ/lbcOLr/y0Q3JB6Lx7XEi2yC5RQ8BBxdKPA==}
230
+
231
+
detect-libc@1.0.3:
232
+
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
233
+
engines: {node: '>=0.10'}
234
+
hasBin: true
235
+
236
+
detect-libc@2.1.2:
237
+
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
238
+
engines: {node: '>=8'}
239
+
240
+
enhanced-resolve@5.18.3:
241
+
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
242
+
engines: {node: '>=10.13.0'}
243
+
244
+
fill-range@7.1.1:
245
+
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
246
+
engines: {node: '>=8'}
247
+
248
+
graceful-fs@4.2.11:
249
+
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
250
+
251
+
is-extglob@2.1.1:
252
+
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
253
+
engines: {node: '>=0.10.0'}
254
+
255
+
is-glob@4.0.3:
256
+
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
257
+
engines: {node: '>=0.10.0'}
258
+
259
+
is-number@7.0.0:
260
+
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
261
+
engines: {node: '>=0.12.0'}
262
+
263
+
jiti@2.6.1:
264
+
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
265
+
hasBin: true
266
+
267
+
lightningcss-android-arm64@1.30.2:
268
+
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
269
+
engines: {node: '>= 12.0.0'}
270
+
cpu: [arm64]
271
+
os: [android]
272
+
273
+
lightningcss-darwin-arm64@1.30.2:
274
+
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
275
+
engines: {node: '>= 12.0.0'}
276
+
cpu: [arm64]
277
+
os: [darwin]
278
+
279
+
lightningcss-darwin-x64@1.30.2:
280
+
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
281
+
engines: {node: '>= 12.0.0'}
282
+
cpu: [x64]
283
+
os: [darwin]
284
+
285
+
lightningcss-freebsd-x64@1.30.2:
286
+
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
287
+
engines: {node: '>= 12.0.0'}
288
+
cpu: [x64]
289
+
os: [freebsd]
290
+
291
+
lightningcss-linux-arm-gnueabihf@1.30.2:
292
+
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
293
+
engines: {node: '>= 12.0.0'}
294
+
cpu: [arm]
295
+
os: [linux]
296
+
297
+
lightningcss-linux-arm64-gnu@1.30.2:
298
+
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
299
+
engines: {node: '>= 12.0.0'}
300
+
cpu: [arm64]
301
+
os: [linux]
302
+
303
+
lightningcss-linux-arm64-musl@1.30.2:
304
+
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
305
+
engines: {node: '>= 12.0.0'}
306
+
cpu: [arm64]
307
+
os: [linux]
308
+
309
+
lightningcss-linux-x64-gnu@1.30.2:
310
+
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
311
+
engines: {node: '>= 12.0.0'}
312
+
cpu: [x64]
313
+
os: [linux]
314
+
315
+
lightningcss-linux-x64-musl@1.30.2:
316
+
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
317
+
engines: {node: '>= 12.0.0'}
318
+
cpu: [x64]
319
+
os: [linux]
320
+
321
+
lightningcss-win32-arm64-msvc@1.30.2:
322
+
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
323
+
engines: {node: '>= 12.0.0'}
324
+
cpu: [arm64]
325
+
os: [win32]
326
+
327
+
lightningcss-win32-x64-msvc@1.30.2:
328
+
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
329
+
engines: {node: '>= 12.0.0'}
330
+
cpu: [x64]
331
+
os: [win32]
332
+
333
+
lightningcss@1.30.2:
334
+
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
335
+
engines: {node: '>= 12.0.0'}
336
+
337
+
magic-string@0.30.21:
338
+
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
339
+
340
+
micromatch@4.0.8:
341
+
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
342
+
engines: {node: '>=8.6'}
343
+
344
+
mri@1.2.0:
345
+
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
346
+
engines: {node: '>=4'}
347
+
348
+
node-addon-api@7.1.1:
349
+
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
350
+
351
+
picocolors@1.1.1:
352
+
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
353
+
354
+
picomatch@2.3.1:
355
+
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
356
+
engines: {node: '>=8.6'}
357
+
358
+
postcss-selector-parser@6.0.10:
359
+
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
360
+
engines: {node: '>=4'}
361
+
362
+
source-map-js@1.2.1:
363
+
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
364
+
engines: {node: '>=0.10.0'}
365
+
366
+
tailwindcss@4.1.17:
367
+
resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==}
368
+
369
+
tapable@2.3.0:
370
+
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
371
+
engines: {node: '>=6'}
372
+
373
+
to-regex-range@5.0.1:
374
+
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
375
+
engines: {node: '>=8.0'}
376
+
377
+
util-deprecate@1.0.2:
378
+
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
379
+
380
+
snapshots:
381
+
382
+
'@jridgewell/gen-mapping@0.3.13':
383
+
dependencies:
384
+
'@jridgewell/sourcemap-codec': 1.5.5
385
+
'@jridgewell/trace-mapping': 0.3.31
386
+
387
+
'@jridgewell/remapping@2.3.5':
388
+
dependencies:
389
+
'@jridgewell/gen-mapping': 0.3.13
390
+
'@jridgewell/trace-mapping': 0.3.31
391
+
392
+
'@jridgewell/resolve-uri@3.1.2': {}
393
+
394
+
'@jridgewell/sourcemap-codec@1.5.5': {}
395
+
396
+
'@jridgewell/trace-mapping@0.3.31':
397
+
dependencies:
398
+
'@jridgewell/resolve-uri': 3.1.2
399
+
'@jridgewell/sourcemap-codec': 1.5.5
400
+
401
+
'@parcel/watcher-android-arm64@2.5.1':
402
+
optional: true
403
+
404
+
'@parcel/watcher-darwin-arm64@2.5.1':
405
+
optional: true
406
+
407
+
'@parcel/watcher-darwin-x64@2.5.1':
408
+
optional: true
409
+
410
+
'@parcel/watcher-freebsd-x64@2.5.1':
411
+
optional: true
412
+
413
+
'@parcel/watcher-linux-arm-glibc@2.5.1':
414
+
optional: true
415
+
416
+
'@parcel/watcher-linux-arm-musl@2.5.1':
417
+
optional: true
418
+
419
+
'@parcel/watcher-linux-arm64-glibc@2.5.1':
420
+
optional: true
421
+
422
+
'@parcel/watcher-linux-arm64-musl@2.5.1':
423
+
optional: true
424
+
425
+
'@parcel/watcher-linux-x64-glibc@2.5.1':
426
+
optional: true
427
+
428
+
'@parcel/watcher-linux-x64-musl@2.5.1':
429
+
optional: true
430
+
431
+
'@parcel/watcher-win32-arm64@2.5.1':
432
+
optional: true
433
+
434
+
'@parcel/watcher-win32-ia32@2.5.1':
435
+
optional: true
436
+
437
+
'@parcel/watcher-win32-x64@2.5.1':
438
+
optional: true
439
+
440
+
'@parcel/watcher@2.5.1':
441
+
dependencies:
442
+
detect-libc: 1.0.3
443
+
is-glob: 4.0.3
444
+
micromatch: 4.0.8
445
+
node-addon-api: 7.1.1
446
+
optionalDependencies:
447
+
'@parcel/watcher-android-arm64': 2.5.1
448
+
'@parcel/watcher-darwin-arm64': 2.5.1
449
+
'@parcel/watcher-darwin-x64': 2.5.1
450
+
'@parcel/watcher-freebsd-x64': 2.5.1
451
+
'@parcel/watcher-linux-arm-glibc': 2.5.1
452
+
'@parcel/watcher-linux-arm-musl': 2.5.1
453
+
'@parcel/watcher-linux-arm64-glibc': 2.5.1
454
+
'@parcel/watcher-linux-arm64-musl': 2.5.1
455
+
'@parcel/watcher-linux-x64-glibc': 2.5.1
456
+
'@parcel/watcher-linux-x64-musl': 2.5.1
457
+
'@parcel/watcher-win32-arm64': 2.5.1
458
+
'@parcel/watcher-win32-ia32': 2.5.1
459
+
'@parcel/watcher-win32-x64': 2.5.1
460
+
461
+
'@tailwindcss/cli@4.1.17':
462
+
dependencies:
463
+
'@parcel/watcher': 2.5.1
464
+
'@tailwindcss/node': 4.1.17
465
+
'@tailwindcss/oxide': 4.1.17
466
+
enhanced-resolve: 5.18.3
467
+
mri: 1.2.0
468
+
picocolors: 1.1.1
469
+
tailwindcss: 4.1.17
470
+
471
+
'@tailwindcss/node@4.1.17':
472
+
dependencies:
473
+
'@jridgewell/remapping': 2.3.5
474
+
enhanced-resolve: 5.18.3
475
+
jiti: 2.6.1
476
+
lightningcss: 1.30.2
477
+
magic-string: 0.30.21
478
+
source-map-js: 1.2.1
479
+
tailwindcss: 4.1.17
480
+
481
+
'@tailwindcss/oxide-android-arm64@4.1.17':
482
+
optional: true
483
+
484
+
'@tailwindcss/oxide-darwin-arm64@4.1.17':
485
+
optional: true
486
+
487
+
'@tailwindcss/oxide-darwin-x64@4.1.17':
488
+
optional: true
489
+
490
+
'@tailwindcss/oxide-freebsd-x64@4.1.17':
491
+
optional: true
492
+
493
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17':
494
+
optional: true
495
+
496
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.17':
497
+
optional: true
498
+
499
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.17':
500
+
optional: true
501
+
502
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.17':
503
+
optional: true
504
+
505
+
'@tailwindcss/oxide-linux-x64-musl@4.1.17':
506
+
optional: true
507
+
508
+
'@tailwindcss/oxide-wasm32-wasi@4.1.17':
509
+
optional: true
510
+
511
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.17':
512
+
optional: true
513
+
514
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.17':
515
+
optional: true
516
+
517
+
'@tailwindcss/oxide@4.1.17':
518
+
optionalDependencies:
519
+
'@tailwindcss/oxide-android-arm64': 4.1.17
520
+
'@tailwindcss/oxide-darwin-arm64': 4.1.17
521
+
'@tailwindcss/oxide-darwin-x64': 4.1.17
522
+
'@tailwindcss/oxide-freebsd-x64': 4.1.17
523
+
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.17
524
+
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.17
525
+
'@tailwindcss/oxide-linux-arm64-musl': 4.1.17
526
+
'@tailwindcss/oxide-linux-x64-gnu': 4.1.17
527
+
'@tailwindcss/oxide-linux-x64-musl': 4.1.17
528
+
'@tailwindcss/oxide-wasm32-wasi': 4.1.17
529
+
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.17
530
+
'@tailwindcss/oxide-win32-x64-msvc': 4.1.17
531
+
532
+
'@tailwindcss/typography@0.5.19(tailwindcss@4.1.17)':
533
+
dependencies:
534
+
postcss-selector-parser: 6.0.10
535
+
tailwindcss: 4.1.17
536
+
537
+
braces@3.0.3:
538
+
dependencies:
539
+
fill-range: 7.1.1
540
+
541
+
cssesc@3.0.0: {}
542
+
543
+
daisyui@5.5.0: {}
544
+
545
+
detect-libc@1.0.3: {}
546
+
547
+
detect-libc@2.1.2: {}
548
+
549
+
enhanced-resolve@5.18.3:
550
+
dependencies:
551
+
graceful-fs: 4.2.11
552
+
tapable: 2.3.0
553
+
554
+
fill-range@7.1.1:
555
+
dependencies:
556
+
to-regex-range: 5.0.1
557
+
558
+
graceful-fs@4.2.11: {}
559
+
560
+
is-extglob@2.1.1: {}
561
+
562
+
is-glob@4.0.3:
563
+
dependencies:
564
+
is-extglob: 2.1.1
565
+
566
+
is-number@7.0.0: {}
567
+
568
+
jiti@2.6.1: {}
569
+
570
+
lightningcss-android-arm64@1.30.2:
571
+
optional: true
572
+
573
+
lightningcss-darwin-arm64@1.30.2:
574
+
optional: true
575
+
576
+
lightningcss-darwin-x64@1.30.2:
577
+
optional: true
578
+
579
+
lightningcss-freebsd-x64@1.30.2:
580
+
optional: true
581
+
582
+
lightningcss-linux-arm-gnueabihf@1.30.2:
583
+
optional: true
584
+
585
+
lightningcss-linux-arm64-gnu@1.30.2:
586
+
optional: true
587
+
588
+
lightningcss-linux-arm64-musl@1.30.2:
589
+
optional: true
590
+
591
+
lightningcss-linux-x64-gnu@1.30.2:
592
+
optional: true
593
+
594
+
lightningcss-linux-x64-musl@1.30.2:
595
+
optional: true
596
+
597
+
lightningcss-win32-arm64-msvc@1.30.2:
598
+
optional: true
599
+
600
+
lightningcss-win32-x64-msvc@1.30.2:
601
+
optional: true
602
+
603
+
lightningcss@1.30.2:
604
+
dependencies:
605
+
detect-libc: 2.1.2
606
+
optionalDependencies:
607
+
lightningcss-android-arm64: 1.30.2
608
+
lightningcss-darwin-arm64: 1.30.2
609
+
lightningcss-darwin-x64: 1.30.2
610
+
lightningcss-freebsd-x64: 1.30.2
611
+
lightningcss-linux-arm-gnueabihf: 1.30.2
612
+
lightningcss-linux-arm64-gnu: 1.30.2
613
+
lightningcss-linux-arm64-musl: 1.30.2
614
+
lightningcss-linux-x64-gnu: 1.30.2
615
+
lightningcss-linux-x64-musl: 1.30.2
616
+
lightningcss-win32-arm64-msvc: 1.30.2
617
+
lightningcss-win32-x64-msvc: 1.30.2
618
+
619
+
magic-string@0.30.21:
620
+
dependencies:
621
+
'@jridgewell/sourcemap-codec': 1.5.5
622
+
623
+
micromatch@4.0.8:
624
+
dependencies:
625
+
braces: 3.0.3
626
+
picomatch: 2.3.1
627
+
628
+
mri@1.2.0: {}
629
+
630
+
node-addon-api@7.1.1: {}
631
+
632
+
picocolors@1.1.1: {}
633
+
634
+
picomatch@2.3.1: {}
635
+
636
+
postcss-selector-parser@6.0.10:
637
+
dependencies:
638
+
cssesc: 3.0.0
639
+
util-deprecate: 1.0.2
640
+
641
+
source-map-js@1.2.1: {}
642
+
643
+
tailwindcss@4.1.17: {}
644
+
645
+
tapable@2.3.0: {}
646
+
647
+
to-regex-range@5.0.1:
648
+
dependencies:
649
+
is-number: 7.0.0
650
+
651
+
util-deprecate@1.0.2: {}
+2
web/public/css/style.css
+2
web/public/css/style.css
···
1
+
/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */
2
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-9xl:8rem;--text-9xl--line-height:1;--font-weight-semibold:600;--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}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;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,Helvetica,Arial,Apple Color Emoji,Segoe UI Emoji}:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@media (prefers-color-scheme:dark){:root:not([data-theme]){color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}}:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=forest]:checked),[data-theme=forest]{color-scheme:dark;--color-base-100:oklch(20.84% .008 17.911);--color-base-200:oklch(18.522% .007 17.911);--color-base-300:oklch(16.203% .007 17.911);--color-base-content:oklch(83.768% .001 17.911);--color-primary:oklch(68.628% .185 148.958);--color-primary-content:oklch(0% 0 0);--color-secondary:oklch(69.776% .135 168.327);--color-secondary-content:oklch(13.955% .027 168.327);--color-accent:oklch(70.628% .119 185.713);--color-accent-content:oklch(14.125% .023 185.713);--color-neutral:oklch(30.698% .039 171.364);--color-neutral-content:oklch(86.139% .007 171.364);--color-info:oklch(72.06% .191 231.6);--color-info-content:oklch(0% 0 0);--color-success:oklch(64.8% .15 160);--color-success-content:oklch(0% 0 0);--color-warning:oklch(84.71% .199 83.87);--color-warning-content:oklch(0% 0 0);--color-error:oklch(71.76% .221 22.18);--color-error-content:oklch(0% 0 0);--radius-selector:1rem;--radius-field:2rem;--radius-box:1rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:0;--noise:0}:root{--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");scrollbar-color:currentColor #0000}@supports (color:color-mix(in lab, red, red)){:root{scrollbar-color:color-mix(in oklch,currentColor 35%,#0000)#0000}}@property --radialprogress{syntax: "<percentage>"; inherits: true; initial-value: 0%;}:root:not(span){overflow:var(--page-overflow)}:root{--page-scroll-bg-on:linear-gradient(var(--root-bg),var(--root-bg))var(--root-bg)}@supports (color:color-mix(in lab, red, red)){:root{--page-scroll-bg-on:linear-gradient(var(--root-bg),var(--root-bg))color-mix(in srgb,var(--root-bg),oklch(0% 0 0) calc(var(--page-has-backdrop,0)*40%))}}:root{--page-scroll-transition-on:background-color .3s ease-out;transition:var(--page-scroll-transition);scrollbar-gutter:var(--page-scroll-gutter,unset);scrollbar-gutter:if(style(--page-has-scroll: 1): var(--page-scroll-gutter,unset); else: unset)}:root:root{background:var(--page-scroll-bg,var(--root-bg,var(--color-base-100)))}@keyframes set-page-has-scroll{0%,to{--page-has-scroll:1}}:root,[data-theme]{background-color:var(--root-bg,var(--color-base-100));color:var(--color-base-content)}:where(:root,[data-theme]){--root-bg:var(--color-base-100)}}@layer components;@layer utilities{@layer daisyui.component{:where(.btn){width:unset}.btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;webkit-user-select:none;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));touch-action:manipulation;box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%))inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:var(--btn-bg);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}@supports (color:color-mix(in lab, red, red)){.btn{--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%))}}.btn{--btn-shadow:0 3px 2px -2px var(--btn-bg),0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn{--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000)}}.btn{--btn-noise:var(--fx-noise)}@media (hover:hover){.btn:hover{--btn-bg:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}}.btn:focus-visible,.btn:has(:focus-visible){isolation:isolate;outline-width:2px;outline-style:solid}.btn:active:not(.btn-active){--btn-bg:var(--btn-color,var(--color-base-200));translate:0 .5px}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%)}}.btn:active:not(.btn-active){--btn-border:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.btn:active:not(.btn-active){--btn-shadow:0 0 0 0 oklch(0% 0 0/0),0 0 0 0 oklch(0% 0 0/0)}.btn:is(input[type=checkbox],input[type=radio]){appearance:none}.btn:is(input[type=checkbox],input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem)*6);background-color:currentColor;display:inline-block;-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");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.validator-hint{visibility:hidden;margin-top:.5rem;font-size:.75rem}.validator:user-valid{--input-color:var(--color-success)}.validator:user-valid:focus{--input-color:var(--color-success)}.validator:user-valid:checked{--input-color:var(--color-success)}.validator:user-valid[aria-checked=true]{--input-color:var(--color-success)}.validator:user-valid:focus-within{--input-color:var(--color-success)}.validator:has(:user-valid){--input-color:var(--color-success)}.validator:has(:user-valid):focus{--input-color:var(--color-success)}.validator:has(:user-valid):checked{--input-color:var(--color-success)}.validator:has(:user-valid)[aria-checked=true]{--input-color:var(--color-success)}.validator:has(:user-valid):focus-within{--input-color:var(--color-success)}.validator:user-invalid{--input-color:var(--color-error)}.validator:user-invalid:focus{--input-color:var(--color-error)}.validator:user-invalid:checked{--input-color:var(--color-error)}.validator:user-invalid[aria-checked=true]{--input-color:var(--color-error)}.validator:user-invalid:focus-within{--input-color:var(--color-error)}.validator:user-invalid~.validator-hint{visibility:visible;color:var(--color-error)}.validator:has(:user-invalid){--input-color:var(--color-error)}.validator:has(:user-invalid):focus{--input-color:var(--color-error)}.validator:has(:user-invalid):checked{--input-color:var(--color-error)}.validator:has(:user-invalid)[aria-checked=true]{--input-color:var(--color-error)}.validator:has(:user-invalid):focus-within{--input-color:var(--color-error)}.validator:has(:user-invalid)~.validator-hint{visibility:visible;color:var(--color-error)}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))),:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):focus,:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):checked,:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))[aria-checked=true],:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false]))):focus-within{--input-color:var(--color-error)}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))~.validator-hint{visibility:visible;color:var(--color-error)}.input{cursor:text;border:var(--border)solid #0000;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);font-size:max(var(--font-size,.875rem),.875rem);touch-action:manipulation;border-color:var(--input-color);box-shadow:0 1px var(--input-color)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab, red, red)){.input{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1))inset}}.input{--size:calc(var(--size-field,.25rem)*10);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.input{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.input:where(input){display:inline-flex}.input :where(input){appearance:none;background-color:#0000;border:none;width:100%;height:100%;display:inline-flex}.input :where(input):focus,.input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus,.input :where(input):focus-within{outline-offset:2px;outline:2px solid #0000}}.input :where(input[type=url]),.input :where(input[type=email]){direction:ltr}.input :where(input[type=date]){display:inline-flex}.input:focus,.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab, red, red)){.input:focus,.input:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.input:focus,.input:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}@media (pointer:coarse){@supports (-webkit-touch-callout:none){.input:focus,.input:focus-within{--font-size:1rem}}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input)::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input)::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{box-shadow:none}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.input:has(>input[type=date]) :where(input[type=date]){webkit-appearance:none;appearance:none;display:inline-flex}.input:has(>input[type=date]) input[type=date]::-webkit-calendar-picker-indicator{cursor:pointer;width:1em;height:1em;position:absolute;inset-inline-end:.75em}.navbar{align-items:center;width:100%;min-height:4rem;padding:.5rem;display:flex}.card{border-radius:var(--radius-box);outline-offset:2px;outline:0 solid #0000;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.card:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.card:focus{outline-offset:2px;outline:2px solid #0000}}.card:focus-visible{outline-color:currentColor}.card :where(figure:first-child){border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.card :where(figure:last-child){border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.card figure{justify-content:center;align-items:center;display:flex}.card:has(>input:is(input[type=checkbox],input[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.card:has(>:checked){outline:2px solid}.progress{appearance:none;border-radius:var(--radius-box);background-color:currentColor;width:100%;height:.5rem;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.progress{background-color:color-mix(in oklab,currentcolor 20%,transparent)}}.progress{color:var(--color-base-content)}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%}@media (prefers-reduced-motion:no-preference){.progress:indeterminate{animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:#0000}@media (prefers-reduced-motion:no-preference){.progress:indeterminate::-moz-progress-bar{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:#0000}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.hero-content{isolation:isolate;justify-content:center;align-items:center;gap:1rem;max-width:80rem;padding:1rem;display:flex}.hero{background-position:50%;background-size:cover;place-items:center;width:100%;display:grid}.hero>*{grid-row-start:1;grid-column-start:1}.breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li{align-items:center;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:hover{text-decoration-line:underline}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{outline-offset:2px;outline:2px solid #0000}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus-visible{outline-offset:2px;outline:2px solid}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li+:before{content:"";opacity:.4;background-color:#0000;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-left:.5rem;margin-right:.75rem;display:block;rotate:45deg}[dir=rtl] :is(:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li)+:before{rotate:-135deg}.fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:var(--color-base-content);width:.5rem;height:.5rem;display:inline-block}@supports (color:color-mix(in lab, red, red)){.status{background-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.status{vertical-align:middle;color:#0000004d;background-position:50%;background-repeat:no-repeat}@supports (color:color-mix(in lab, red, red)){.status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.status{background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),#0000);box-shadow:0 2px 3px -1px}@supports (color:color-mix(in lab, red, red)){.status{box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),#0000)}}.badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border)solid var(--badge-color,var(--color-base-200));width:fit-content;padding-inline:calc(.25rem*3 - var(--border));background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem)*6);height:var(--size);justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.navbar-end{justify-content:flex-end;align-items:center;width:50%;display:inline-flex}.navbar-start{justify-content:flex-start;align-items:center;width:50%;display:inline-flex}.card-body{padding:var(--card-p,1.5rem);font-size:var(--card-fs,.875rem);flex-direction:column;flex:auto;gap:.5rem;display:flex}.card-body :where(p){flex-grow:1}.alert{--alert-border-color:var(--color-base-200);border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px #000,0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08));border-style:solid;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}@supports (color:color-mix(in lab, red, red)){.alert{box-shadow:0 3px 0 -2px oklch(100% 0 0/calc(var(--depth)*.08))inset,0 1px color-mix(in oklab,color-mix(in oklab,#000 20%,var(--alert-color,var(--color-base-200)))calc(var(--depth)*20%),#0000),0 4px 3px -2px oklch(0% 0 0/calc(var(--depth)*.08))}}.alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.card-actions{flex-wrap:wrap;align-items:flex-start;gap:.5rem;display:flex}.card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}}@layer daisyui.modifier{.btn:disabled:not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:disabled:not(.btn-link,.btn-ghost){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}}.btn:disabled:not(.btn-link,.btn-ghost){box-shadow:none}.btn:disabled{pointer-events:none;--btn-border:#0000;--btn-noise:none;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:disabled{--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}.btn[disabled]:not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn[disabled]:not(.btn-link,.btn-ghost){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}}.btn[disabled]:not(.btn-link,.btn-ghost){box-shadow:none}.btn[disabled]{pointer-events:none;--btn-border:#0000;--btn-noise:none;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn[disabled]{--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}:where(.navbar){position:relative}.input-md{--size:calc(var(--size-field,.25rem)*10);font-size:max(var(--font-size,.875rem),.875rem)}.input-md[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.badge-lg{--size:calc(var(--size-selector,.25rem)*7);padding-inline:calc(.25rem*3.5 - var(--border));font-size:1rem}.alert-error{color:var(--color-error-content);--alert-border-color:var(--color-error);--alert-color:var(--color-error)}.alert-info{color:var(--color-info-content);--alert-border-color:var(--color-info);--alert-color:var(--color-info)}.alert-success{color:var(--color-success-content);--alert-border-color:var(--color-success);--alert-color:var(--color-success)}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible,input:checked:not(.filter .btn)){--btn-shadow:"";--btn-bg:#0000;--btn-border:#0000;--btn-noise:none}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible,input:checked:not(.filter .btn)):not(:disabled,[disabled],.btn-disabled){--btn-fg:var(--btn-color,currentColor);outline-color:currentColor}@media (hover:none){.btn-ghost:not(.btn-active,:active,:focus-visible,input:checked:not(.filter .btn)):hover{--btn-shadow:"";--btn-bg:#0000;--btn-fg:var(--btn-color,currentColor);--btn-border:#0000;--btn-noise:none;outline-color:currentColor}}.btn-lg{--fontsize:1.125rem;--btn-p:1.25rem;--size:calc(var(--size-field,.25rem)*12)}.btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem)*8)}.badge-primary{--badge-color:var(--color-primary);--badge-fg:var(--color-primary-content)}.badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}}.validator:user-invalid~.validator-hint{display:revert-layer}.validator:has(:user-invalid)~.validator-hint{display:revert-layer}:is(.validator[aria-invalid]:not([aria-invalid=false]),.validator:has([aria-invalid]:not([aria-invalid=false])))~.validator-hint{display:revert-layer}.static{position:static}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.join-item:where(:not(:first-child,:disabled,[disabled],.btn-disabled)){margin-block-start:0;margin-inline-start:calc(var(--border,1px)*-1)}.join-item:where(:is(:disabled,[disabled],.btn-disabled)){border-width:var(--border,1px)0 var(--border,1px)var(--border,1px)}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"โ""โ""โ""โ";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-lg{font-size:1.125rem;line-height:1.77778}.prose-lg :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em}.prose-lg :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.09091em;margin-bottom:1.09091em;font-size:1.22222em;line-height:1.45455}.prose-lg :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.66667em;margin-bottom:1.66667em;padding-inline-start:1em}.prose-lg :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:.833333em;font-size:2.66667em;line-height:1}.prose-lg :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.86667em;margin-bottom:1.06667em;font-size:1.66667em;line-height:1.33333}.prose-lg :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.66667em;margin-bottom:.666667em;font-size:1.33333em;line-height:1.5}.prose-lg :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:.444444em;line-height:1.55556}.prose-lg :where(img):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-lg :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.222222em;padding-inline-end:.444444em;padding-bottom:.222222em;border-radius:.3125rem;padding-inline-start:.444444em;font-size:.888889em}.prose-lg :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em}.prose-lg :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.866667em}.prose-lg :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.875em}.prose-lg :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:1em;padding-inline-end:1.5em;padding-bottom:1em;border-radius:.375rem;margin-top:2em;margin-bottom:2em;padding-inline-start:1.5em;font-size:.888889em;line-height:1.75}.prose-lg :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em;padding-inline-start:1.55556em}.prose-lg :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;margin-bottom:.666667em}.prose-lg :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.444444em}.prose-lg :where(.prose-lg>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em}.prose-lg :where(.prose-lg>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(.prose-lg>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.33333em}.prose-lg :where(.prose-lg>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(.prose-lg>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.33333em}.prose-lg :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.888889em;margin-bottom:.888889em}.prose-lg :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em;margin-bottom:1.33333em}.prose-lg :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.33333em}.prose-lg :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.666667em;padding-inline-start:1.55556em}.prose-lg :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:3.11111em;margin-bottom:3.11111em}.prose-lg :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose-lg :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-lg :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){font-size:.888889em;line-height:1.5}.prose-lg :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:.75em;padding-bottom:.75em;padding-inline-start:.75em}.prose-lg :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-lg :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-lg :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.75em;padding-inline-end:.75em;padding-bottom:.75em;padding-inline-start:.75em}.prose-lg :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose-lg :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose-lg :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.77778em;margin-bottom:1.77778em}.prose-lg :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose-lg :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1em;font-size:.888889em;line-height:1.5}.prose-lg :where(.prose-lg>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose-lg :where(.prose-lg>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.alert{border-width:var(--border);border-color:var(--alert-border-color,var(--color-base-200))}.join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join>.join-item:where(:first-child),.join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join>.join-item:where(:last-child),.join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join>.join-item:where(:only-child),.join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}:root .prose{--tw-prose-body:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-body:color-mix(in oklab,var(--color-base-content)80%,#0000)}}:root .prose{--tw-prose-headings:var(--color-base-content);--tw-prose-lead:var(--color-base-content);--tw-prose-links:var(--color-base-content);--tw-prose-bold:var(--color-base-content);--tw-prose-counters:var(--color-base-content);--tw-prose-bullets:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-bullets:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-hr:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-hr:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-quotes:var(--color-base-content);--tw-prose-quote-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-quote-borders:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-captions:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-captions:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-code:var(--color-base-content);--tw-prose-pre-code:var(--color-neutral-content);--tw-prose-pre-bg:var(--color-neutral);--tw-prose-th-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-th-borders:color-mix(in oklab,var(--color-base-content)50%,#0000)}}:root .prose{--tw-prose-td-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-td-borders:color-mix(in oklab,var(--color-base-content)20%,#0000)}}:root .prose{--tw-prose-kbd:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-kbd:color-mix(in oklab,var(--color-base-content)80%,#0000)}}:root .prose :where(code):not(pre>code){background-color:var(--color-base-200);border-radius:var(--radius-selector);border:var(--border)solid var(--color-base-300);font-weight:inherit;padding-block:.2em;padding-inline:.5em}:root .prose :where(code):not(pre>code):before,:root .prose :where(code):not(pre>code):after{display:none}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-24{height:calc(var(--spacing)*24)}.min-h-\[60vh\]{min-height:60vh}.min-h-screen{min-height:100vh}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-full{width:100%}.max-w-5xl{max-width:var(--container-5xl)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.shrink-0{flex-shrink:0}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.justify-end{justify-content:flex-end}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.bg-base-100{background-color:var(--color-base-100)}.stroke-current{stroke:currentColor}.px-4{padding-inline:calc(var(--spacing)*4)}.py-6{padding-block:calc(var(--spacing)*6)}.py-8{padding-block:calc(var(--spacing)*8)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-9xl{font-size:var(--text-9xl);line-height:var(--tw-leading,var(--text-9xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-base-content{color:var(--color-base-content)}.text-white{color:var(--color-white)}.prose :where(.btn-link):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-line:none}.opacity-70{opacity:.7}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@layer daisyui.modifier.color{.btn-error{--btn-color:var(--color-error);--btn-fg:var(--color-error-content)}.btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}.btn-success{--btn-color:var(--color-success);--btn-fg:var(--color-success-content)}}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}}@media (min-width:40rem){.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:48rem){.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:64rem){.lg\:ml-8{margin-left:calc(var(--spacing)*8)}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:flex-row-reverse{flex-direction:row-reverse}.lg\:text-left{text-align:left}}}.advent-header{box-shadow:0 4px 6px -1px #0000001a}.advent-title{-webkit-text-fill-color:transparent;letter-spacing:-.025em;background:linear-gradient(90deg,#b91c1c 0%,#ef4444 22%,#f59e0b 50%,#22c55e 78%,#065f46 100%);-webkit-background-clip:text;background-clip:text;font-weight:800}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@keyframes dropdown{0%{opacity:0}}@keyframes radio{0%{padding:5px}50%{padding:3px}}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@keyframes rotator{89.9999%,to{--first-item-position:0 0%}90%,99.9999%{--first-item-position:0 calc(var(--items)*100%)}to{translate:0 -100%}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}@keyframes progress{50%{background-position-x:-115%}}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
+36
-7
web/src/handlers/auth.rs
+36
-7
web/src/handlers/auth.rs
···
4
4
use atrium_api::agent::Agent;
5
5
use atrium_oauth::{AuthorizeOptions, CallbackParams};
6
6
use axum::{
7
-
extract::{Path, Query, State},
7
+
extract::{Query, State},
8
8
http::StatusCode,
9
9
response::{IntoResponse, Redirect, Response},
10
10
};
···
17
17
Some(FlashMessage::Error(msg)) => Some(msg),
18
18
_ => None,
19
19
};
20
+
let is_logged_in = session.logged_in();
20
21
21
22
Ok(HtmlTemplate(LoginTemplate {
22
23
title: "at://advent - Login",
23
24
error: possible_error,
25
+
is_logged_in,
24
26
}))
25
27
}
26
28
29
+
#[derive(serde::Deserialize)]
30
+
pub struct LoginParams {
31
+
pub handle: String,
32
+
}
33
+
27
34
pub async fn login_handle(
28
-
Path(handle): Path<String>,
35
+
Query(params): Query<LoginParams>,
29
36
State(oauth_client): State<OAuthClientType>,
30
37
mut session: AxumSessionStore,
31
38
) -> Result<impl IntoResponse, Response> {
32
-
match atrium_api::types::string::Handle::new(handle) {
39
+
match atrium_api::types::string::Handle::new(params.handle.to_ascii_lowercase()) {
33
40
Ok(handle) => {
34
41
match oauth_client
35
42
.authorize(
···
71
78
}
72
79
}
73
80
74
-
pub async fn handle_root_handler() -> impl IntoResponse {
75
-
Redirect::to("/login")
76
-
}
77
-
78
81
///End point that takes back the OAuth call back and creates a session
79
82
pub async fn oauth_callback_handler(
80
83
params: Query<CallbackParams>,
···
110
113
}
111
114
}
112
115
}
116
+
117
+
/// Logout handler - clears session and redirects to home
118
+
pub async fn logout_handler(
119
+
mut session: AxumSessionStore,
120
+
State(oauth_client): State<OAuthClientType>,
121
+
) -> Result<impl IntoResponse, Response> {
122
+
//TODO test this and move the shared variables to a shared struct for templates like is logged in and title
123
+
124
+
match session.get_did() {
125
+
None => {}
126
+
Some(did) => {
127
+
//TODO lots of unwraps
128
+
let did = atrium_api::types::string::Did::new(did.clone()).unwrap();
129
+
let client = oauth_client.restore(&did).await.unwrap();
130
+
let agent = Agent::new(client);
131
+
let _ = agent.api.com.atproto.server.delete_session().await;
132
+
}
133
+
}
134
+
135
+
session.clear_session().await.map_err(|err| {
136
+
log::error!("Failed to clear session: {err}");
137
+
error_response(StatusCode::INTERNAL_SERVER_ERROR, "Failed to log out")
138
+
})?;
139
+
140
+
Ok(Redirect::to("/"))
141
+
}
+15
-2
web/src/handlers/day.rs
+15
-2
web/src/handlers/day.rs
···
83
83
.markdown_text_part_one(None)
84
84
.map(|s| s.to_string())
85
85
.unwrap_or_else(|_| "Error loading part one".to_string()),
86
-
Some(ref users_did) => match challenge.get_days_challenge(users_did.clone()).await {
86
+
Some(ref users_did) => match challenge.get_days_challenge(&users_did).await {
87
87
Ok(current_challenge) => match current_challenge {
88
88
None => {
89
89
let new_code = challenge
···
132
132
let part_one_flash = get_flash_message(&mut session, "part_one_result").await?;
133
133
let part_two_flash = get_flash_message(&mut session, "part_two_result").await?;
134
134
135
+
let requires_code_input_part_one = challenge.requires_manual_verification_part_one();
136
+
let requires_code_input_part_two = challenge.requires_manual_verification_part_two();
137
+
let is_logged_in = session.logged_in();
138
+
135
139
let template = match status {
136
140
CompletionStatus::None => DayTemplate {
137
141
title,
···
142
146
challenge_two_completed: false,
143
147
part_one_submit_message: part_one_flash,
144
148
part_two_submit_message: part_two_flash,
149
+
requires_code_input_part_one,
150
+
requires_code_input_part_two,
151
+
is_logged_in,
145
152
},
146
153
CompletionStatus::PartOne => {
147
154
let part_two_text = get_part_two_text(did_clone, &challenge).await;
···
155
162
challenge_two_completed: completed,
156
163
part_one_submit_message: part_one_flash,
157
164
part_two_submit_message: part_two_flash,
165
+
requires_code_input_part_one,
166
+
requires_code_input_part_two,
167
+
is_logged_in,
158
168
}
159
169
}
160
170
CompletionStatus::Both => {
···
168
178
challenge_two_completed: true,
169
179
part_one_submit_message: part_one_flash,
170
180
part_two_submit_message: part_two_flash,
181
+
requires_code_input_part_one,
182
+
requires_code_input_part_two,
183
+
is_logged_in,
171
184
}
172
185
}
173
186
};
···
186
199
.markdown_text_part_two(None)
187
200
.map(|opt| opt.map(|s| s.to_string()))
188
201
.unwrap_or(None),
189
-
Some(users_did) => match challenge.get_days_challenge(users_did.clone()).await {
202
+
Some(users_did) => match challenge.get_days_challenge(&users_did).await {
190
203
Ok(current_challenge) => match current_challenge {
191
204
None => {
192
205
if challenge.has_part_two() {
+41
-9
web/src/main.rs
+41
-9
web/src/main.rs
···
1
1
use crate::{
2
-
templates::HtmlTemplate, templates::error::ErrorTemplate, templates::home::HomeTemplate,
2
+
session::AxumSessionStore,
3
+
templates::HtmlTemplate,
4
+
templates::error::ErrorTemplate,
5
+
templates::home::{DayStatus, HomeTemplate},
3
6
};
4
7
use atrium_identity::{
5
8
did::{CommonDidResolver, CommonDidResolverConfig, DEFAULT_PLC_DIRECTORY_URL},
···
11
14
};
12
15
use axum::{
13
16
Router,
17
+
extract::State,
14
18
http::StatusCode,
15
19
middleware,
16
20
response::IntoResponse,
···
21
25
use chrono::Datelike;
22
26
use dotenv::dotenv;
23
27
use redis::AsyncCommands;
28
+
use rust_embed::RustEmbed;
24
29
use shared::{
25
-
HandleResolver, OAuthClientType, atrium::dns_resolver::HickoryDnsTxtResolver,
26
-
atrium::stores::AtriumSessionStore, atrium::stores::AtriumStateStore,
30
+
HandleResolver, OAuthClientType,
31
+
advent::{CompletionStatus, get_all_days_completion_status},
32
+
atrium::dns_resolver::HickoryDnsTxtResolver,
33
+
atrium::stores::AtriumSessionStore,
34
+
atrium::stores::AtriumStateStore,
27
35
};
28
36
use sqlx::{PgPool, postgres::PgPoolOptions};
29
37
use std::{
···
40
48
mod handlers;
41
49
42
50
extern crate dotenv;
43
-
51
+
//
44
52
mod extractors;
45
53
mod redis_session_store;
46
54
mod session;
47
55
mod templates;
48
56
mod unlock;
49
57
58
+
#[derive(RustEmbed, Clone)]
59
+
#[folder = "./public"]
60
+
struct Assets;
61
+
50
62
#[derive(Clone)]
51
63
struct AppState {
52
64
postgres_pool: PgPool,
···
59
71
fn oauth_scopes() -> Vec<Scope> {
60
72
vec![
61
73
Scope::Known(KnownScope::Atproto),
74
+
// Scope::Known(KnownScope::TransitionGeneric),
75
+
//This looks like it HAS to have the full collection name, before i want to say it worked with wildcard
62
76
//Gives full CRUD to the codes.advent.* collection
63
-
Scope::Unknown("repo:codes.advent.*".to_string()),
77
+
Scope::Unknown("repo:codes.advent.test".to_string()),
64
78
]
65
79
}
66
80
···
70
84
HtmlTemplate(ErrorTemplate {
71
85
title: "at://advent - Error",
72
86
message,
87
+
is_logged_in: false,
73
88
}),
74
89
))
75
90
}
···
174
189
.map(|val| val == "true")
175
190
.unwrap_or_else(|_| true);
176
191
log::info!("listening on http://{}", addr);
192
+
177
193
let app = Router::new()
178
194
.route("/", get(home_handler))
179
195
.route(
···
193
209
},
194
210
)
195
211
.route("/login", get(handlers::auth::login_page_handler))
196
-
.route("/handle", get(handlers::auth::handle_root_handler))
197
-
.route("/login/{handle}", get(handlers::auth::login_handle))
212
+
.route("/logout", get(handlers::auth::logout_handler))
213
+
.route("/redirect/login", get(handlers::auth::login_handle))
198
214
.route(
199
215
"/oauth/callback",
200
216
get(handlers::auth::oauth_callback_handler),
201
217
)
218
+
.nest_service("/public", axum_embed::ServeEmbed::<Assets>::new())
202
219
.layer(session_layer)
203
220
.with_state(app_state)
204
221
.layer(TraceLayer::new_for_http());
···
207
224
}
208
225
209
226
/// Landing page showing currently unlocked days and a login button
210
-
async fn home_handler() -> impl IntoResponse {
227
+
async fn home_handler(State(pool): State<PgPool>, session: AxumSessionStore) -> impl IntoResponse {
211
228
//TODO make a helper function for this since it is similar to the middleware
212
229
let now = chrono::Utc::now();
213
230
let mut unlocked: Vec<u8> = Vec::new();
···
229
246
}
230
247
}
231
248
249
+
// Get completion status for all days at once
250
+
let did = session.get_did();
251
+
let is_logged_in = session.logged_in();
252
+
let all_statuses = get_all_days_completion_status(&pool, did.as_ref())
253
+
.await
254
+
.unwrap_or_else(|_| (1..=25).map(|day| (day, CompletionStatus::None)).collect());
255
+
256
+
// Filter to only include unlocked days
257
+
let unlocked_with_status: Vec<DayStatus> = all_statuses
258
+
.into_iter()
259
+
.filter(|(day, _)| unlocked.contains(day))
260
+
.map(|(day, status)| DayStatus { day, status })
261
+
.collect();
262
+
232
263
HtmlTemplate(HomeTemplate {
233
264
title: "at://advent",
234
-
unlocked_days: unlocked,
265
+
unlocked_days: unlocked_with_status,
266
+
is_logged_in,
235
267
})
236
268
}
+7
-1
web/src/session.rs
+7
-1
web/src/session.rs
···
41
41
impl AxumSessionStore {
42
42
const SESSION_DATA_KEY: &'static str = "session.data";
43
43
44
-
pub fn _logged_in(&self) -> bool {
44
+
pub fn logged_in(&self) -> bool {
45
45
self.data.did.is_some()
46
46
}
47
47
···
52
52
53
53
pub fn get_did(&self) -> Option<String> {
54
54
self.data.did.clone()
55
+
}
56
+
57
+
/// Clears the session data (logs out the user)
58
+
pub async fn clear_session(&mut self) -> Result<(), tower_sessions::session::Error> {
59
+
self.data = SessionData::default();
60
+
Self::update_session(&self.session, &self.data).await
55
61
}
56
62
57
63
///Gets the message as well as removes it from the session
+6
web/src/templates/day.rs
+6
web/src/templates/day.rs
···
14
14
//If these are set than it was a redirect from checking the challenge.
15
15
pub part_one_submit_message: Option<FlashMessage>,
16
16
pub part_two_submit_message: Option<FlashMessage>,
17
+
18
+
// Flags to indicate if manual code input is required
19
+
pub requires_code_input_part_one: bool,
20
+
pub requires_code_input_part_two: bool,
21
+
22
+
pub is_logged_in: bool,
17
23
}
+1
web/src/templates/error.rs
+1
web/src/templates/error.rs
+9
-1
web/src/templates/home.rs
+9
-1
web/src/templates/home.rs
···
1
1
use askama::Template;
2
+
use shared::advent::CompletionStatus;
3
+
4
+
#[derive(Clone)]
5
+
pub struct DayStatus {
6
+
pub day: u8,
7
+
pub status: CompletionStatus,
8
+
}
2
9
3
10
#[derive(Template)]
4
11
#[template(path = "index.askama.html")]
5
12
pub struct HomeTemplate {
6
13
pub title: &'static str,
7
-
pub unlocked_days: Vec<u8>,
14
+
pub unlocked_days: Vec<DayStatus>,
15
+
pub is_logged_in: bool,
8
16
}
+1
web/src/templates/login.rs
+1
web/src/templates/login.rs
+1
-1
web/src/templates/mod.rs
+1
-1
web/src/templates/mod.rs
+124
-41
web/templates/day.askama.html
+124
-41
web/templates/day.askama.html
···
1
1
{% extends "layout.askama.html" %}
2
2
3
3
{% block content %}
4
-
<h2 class="text-xl">Day {{ day }}</h2>
5
-
<p>Part 1:</p>
6
-
<article class="prose">{{ challenge_one_text | safe }}</article>
7
-
<br/>
8
-
{% if let Some(msg) = part_one_submit_message %}
9
-
{% match msg %}
10
-
{% when FlashMessage::Success with (success) %}
11
-
<span class="text-success">{{success}}</span>
12
-
{% when FlashMessage::Error with (error) %}
13
-
<div class="alert alert-error mb-2">{{error}}</div>
14
-
{% endmatch %}
15
-
{% endif %}
4
+
<div class="mb-6">
5
+
<div class="breadcrumbs text-sm">
6
+
<ul>
7
+
<li><a href="/">Home</a></li>
8
+
<li>Day {{ day }}</li>
9
+
</ul>
10
+
</div>
11
+
<h2 class="text-4xl font-bold">Day {{ day }}</h2>
12
+
</div>
16
13
17
-
{% if !challenge_one_completed %}
18
-
<form method="post" action="/day/{{ day }}">
19
-
<!-- TODO will be optional prob load from a markdown variable? -->
20
-
<!-- <input type="text" name="verification_code_one" placeholder="Enter Part 1 code" class="input input-bordered mr-2"/>-->
21
-
<button class="btn" type="submit">Check answer</button>
22
-
</form>
23
-
{% else %}
24
-
<span class="text-success">Great work, you've completed Part 1</span>
25
-
{% endif %}
14
+
<!-- Part 1 -->
15
+
<div class="card bg-base-100 shadow-xl mb-6">
16
+
<div class="card-body">
17
+
<h3 class="card-title text-2xl">
18
+
Part 1
19
+
{% if challenge_one_completed %}
20
+
<div class="badge badge-success gap-2">
21
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-4 h-4 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
22
+
Completed
23
+
</div>
24
+
{% endif %}
25
+
</h3>
26
+
27
+
<article class="prose prose-lg max-w-none">{{ challenge_one_text | safe }}</article>
28
+
29
+
{% if let Some(msg) = part_one_submit_message %}
30
+
<div class="mt-4">
31
+
{% match msg %}
32
+
{% when FlashMessage::Success with (success) %}
33
+
<div class="alert alert-success shadow-lg">
34
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
35
+
<span>{{success}}</span>
36
+
</div>
37
+
{% when FlashMessage::Error with (error) %}
38
+
<div class="alert alert-error shadow-lg">
39
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
40
+
<span>{{error}}</span>
41
+
</div>
42
+
{% endmatch %}
43
+
</div>
44
+
{% endif %}
26
45
46
+
<div class="card-actions justify-end mt-4">
47
+
{% if !challenge_one_completed %}
48
+
<form method="post" action="/day/{{ day }}">
49
+
{% if requires_code_input_part_one %}
50
+
<div class="join">
51
+
<div>
52
+
<label class="input validator join-item">
53
+
<input type="text" name="verification_code_one" placeholder="Enter Part 1 code" required />
54
+
</label>
55
+
<div class="validator-hint hidden">Enter valid email address</div>
56
+
</div>
57
+
<button type="submit" class="btn btn-primary join-item">Check answer</button>
58
+
</div>
59
+
{% else %}
60
+
<button class="btn btn-primary" type="submit">Check answer</button>
61
+
<!-- <input type="text" name="verification_code_one" placeholder="" class="input input-bordered mr-2" required/> -->
62
+
{% endif %}
27
63
64
+
</form>
65
+
{% else %}
66
+
<div class="badge badge-success badge-lg gap-2">
67
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-4 h-4 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
68
+
Great work, you've completed Part 1!
69
+
</div>
70
+
{% endif %}
71
+
</div>
72
+
</div>
73
+
</div>
74
+
75
+
<!-- Part 2 -->
28
76
{% if let Some(challenge_two_text) = challenge_two_text %}
29
-
<hr class="my-4"/>
30
-
<p>Part 2:</p>
31
-
<article class="prose">{{ challenge_two_text | safe }}</article>
32
-
{% if let Some(msg) = part_two_submit_message %}
33
-
{% match msg %}
34
-
{% when FlashMessage::Success with (success) %}
35
-
<span class="text-success">{{success}}</span>
36
-
{% when FlashMessage::Error with (error) %}
37
-
<div class="alert alert-error mb-2">{{error}}</div>
38
-
{% endmatch %}
39
-
{% endif %}
40
-
{% if !challenge_two_completed %}
41
-
<form method="post" action="/day/{{ day }}">
42
-
<!-- TODO will be optional prob load from a markdown variable? -->
43
-
<!-- <input type="text" name="verification_code_two" placeholder="Enter Part 2 code" class="input input-bordered mr-2"/>-->
44
-
<button class="btn" type="submit">Check answer</button>
45
-
</form>
46
-
{% endif %}
77
+
<div class="card bg-base-100 shadow-xl mb-6">
78
+
<div class="card-body">
79
+
<h3 class="card-title text-2xl">
80
+
Part 2
81
+
{% if challenge_two_completed %}
82
+
<div class="badge badge-success gap-2">
83
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-4 h-4 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
84
+
Completed
85
+
</div>
86
+
{% endif %}
87
+
</h3>
88
+
89
+
<article class="prose prose-lg max-w-none">{{ challenge_two_text | safe }}</article>
47
90
91
+
{% if let Some(msg) = part_two_submit_message %}
92
+
<div class="mt-4">
93
+
{% match msg %}
94
+
{% when FlashMessage::Success with (success) %}
95
+
<div class="alert alert-success shadow-lg">
96
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
97
+
<span>{{success}}</span>
98
+
</div>
99
+
{% when FlashMessage::Error with (error) %}
100
+
<div class="alert alert-error shadow-lg">
101
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
102
+
<span>{{error}}</span>
103
+
</div>
104
+
{% endmatch %}
105
+
</div>
106
+
{% endif %}
107
+
108
+
<div class="card-actions justify-end mt-4">
109
+
{% if !challenge_two_completed %}
110
+
<form method="post" action="/day/{{ day }}">
111
+
{% if requires_code_input_part_two %}
112
+
<input type="text" name="verification_code_two" placeholder="Enter Part 2 code" class="input input-bordered mr-2" required/>
113
+
{% endif %}
114
+
<button class="btn btn-primary" type="submit">Check answer</button>
115
+
</form>
116
+
{% else %}
117
+
<div class="badge badge-success badge-lg gap-2">
118
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-4 h-4 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
119
+
Great work, you've completed Part 2!
120
+
</div>
121
+
{% endif %}
122
+
</div>
123
+
</div>
124
+
</div>
48
125
{% endif %}
49
126
127
+
<!-- All Complete Message -->
50
128
{% if challenge_one_completed && challenge_two_completed %}
51
-
<br>
52
-
<span class="text-success">Great work, you've completed all the challenges for today! Come back tomorrow for more at 00:00 UTC</span>
129
+
<div class="alert alert-success shadow-lg">
130
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
131
+
<div>
132
+
<h3 class="font-bold">Amazing work! ๐</h3>
133
+
<div class="text-sm">You've completed all the challenges for today! Come back tomorrow at 00:00 UTC for more.</div>
134
+
</div>
135
+
</div>
53
136
{% endif %}
54
137
55
138
{% endblock %}
+15
-3
web/templates/error.askama.html
+15
-3
web/templates/error.askama.html
···
1
1
{% extends "layout.askama.html" %}
2
2
3
3
{% block content %}
4
-
<h2 class="text-xl">An error occurred</h2>
5
-
<p class="mt-2">{{ message }}</p>
6
-
<p class="mt-4"><a class="link" href="?">Return</a></p>
4
+
<div class="hero min-h-[60vh]">
5
+
<div class="hero-content text-center">
6
+
<div class="max-w-md">
7
+
<div class="text-9xl mb-4">โ ๏ธ</div>
8
+
<h1 class="text-5xl font-bold mb-4">Oops!</h1>
9
+
<div class="alert alert-error mb-6">
10
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
11
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
12
+
</svg>
13
+
<span>{{ message }}</span>
14
+
</div>
15
+
<a href="/" class="btn btn-primary">Return Home</a>
16
+
</div>
17
+
</div>
18
+
</div>
7
19
{% endblock %}
+47
-8
web/templates/index.askama.html
+47
-8
web/templates/index.askama.html
···
1
1
{% extends "layout.askama.html" %}
2
2
3
3
{% block content %}
4
-
<div class="flex items-center justify-between mb-6">
5
-
<h2 class="text-xl font-semibold">Welcome</h2>
6
-
<a class="btn" href="/login">Login</a>
4
+
<div class="card bg-base-100 shadow-xl mb-8">
5
+
<div class="card-body">
6
+
<h2 class="card-title text-3xl font-bold">Welcome to AT Protocol Advent! ๐</h2>
7
+
<p class="text-base-content">Complete daily challenges throughout December to learn about the AT Protocol.</p>
8
+
</div>
7
9
</div>
8
10
9
-
<p class="mb-3">Unlocked days:</p>
10
11
{% if unlocked_days.len() == 0 %}
11
-
<div class="alert">No days are unlocked yet. Please check back in December!</div>
12
+
<div class="alert alert-info shadow-lg">
13
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
14
+
<div>
15
+
<h3 class="font-bold">No days unlocked yet</h3>
16
+
<div class="text-sm">Please check back in December when the challenges begin!</div>
17
+
</div>
18
+
</div>
12
19
{% else %}
13
-
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-2">
14
-
{% for d in unlocked_days %}
15
-
<a class="btn" href="/day/{{ d }}">Day {{ d }}</a>
20
+
<div class="mb-4">
21
+
<h3 class="text-2xl font-semibold mb-4">Available Challenges</h3>
22
+
<div class="badge badge-primary badge-lg">{{ unlocked_days.len() }} day{% if unlocked_days.len() != 1 %}s{% endif %} unlocked</div>
23
+
</div>
24
+
25
+
<style>
26
+
.day-btn-partial {
27
+
background: linear-gradient(135deg, #22c55e 0%, #22c55e 50%, #ef4444 50%, #ef4444 100%) !important;
28
+
color: white;
29
+
}
30
+
31
+
.day-btn-partial:hover {
32
+
opacity: 0.9;
33
+
}
34
+
</style>
35
+
36
+
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
37
+
{% for day_status in unlocked_days %}
38
+
{% match day_status.status %}
39
+
{% when shared::advent::CompletionStatus::None %}
40
+
<a href="/day/{{ day_status.day }}" class="btn btn-lg btn-error h-24 flex flex-col hover:scale-105 transition-transform">
41
+
<span class="text-xs opacity-70">Day</span>
42
+
<span class="text-3xl font-bold">{{ day_status.day }}</span>
43
+
</a>
44
+
{% when shared::advent::CompletionStatus::PartOne %}
45
+
<a href="/day/{{ day_status.day }}" class="btn btn-lg day-btn-partial h-24 flex flex-col hover:scale-105 transition-transform">
46
+
<span class="text-xs opacity-70">Day</span>
47
+
<span class="text-3xl font-bold">{{ day_status.day }}</span>
48
+
</a>
49
+
{% when shared::advent::CompletionStatus::Both %}
50
+
<a href="/day/{{ day_status.day }}" class="btn btn-lg btn-success h-24 flex flex-col hover:scale-105 transition-transform">
51
+
<span class="text-xs opacity-70">Day</span>
52
+
<span class="text-3xl font-bold">{{ day_status.day }}</span>
53
+
</a>
54
+
{% endmatch %}
16
55
{% endfor %}
17
56
</div>
18
57
{% endif %}
+20
-16
web/templates/layout.askama.html
+20
-16
web/templates/layout.askama.html
···
1
1
<!DOCTYPE html>
2
-
<html lang="en">
2
+
<html lang="en" data-theme="forest">
3
3
<head>
4
4
<meta charset="utf-8">
5
5
<meta name="viewport" content="width=device-width, initial-scale=1">
6
6
<title>{{ title }}</title>
7
-
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
8
-
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
9
-
10
-
<style>
11
-
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"; margin: 0; color: #111; }
12
-
header { background: #0d47a1; color: #fff; padding: 1rem; }
13
-
main { padding: 1rem; max-width: 900px; margin: 0 auto; }
7
+
<link rel="stylesheet" href="/public/css/style.css"/>
14
8
15
-
</style>
16
9
</head>
17
-
<body>
18
-
<header>
19
-
<h1>at://advent</h1>
20
-
</header>
21
-
<main>
22
-
{% block content %}{% endblock %}
23
-
</main>
10
+
<body class="min-h-screen">
11
+
<div class="navbar advent-header text-white shadow-lg">
12
+
<div class="navbar-start">
13
+
<a href="/" class="text-3xl font-bold advent-title">at://advent</a>
14
+
</div>
15
+
<div class="navbar-end">
16
+
{% if is_logged_in %}
17
+
<a href="/logout" class="btn btn-ghost btn-sm">Logout</a>
18
+
{% else %}
19
+
<a href="/login" class="btn btn-ghost btn-sm">Login</a>
20
+
{% endif %}
21
+
</div>
22
+
</div>
23
+
24
+
<main class="container mx-auto px-4 py-8 max-w-5xl">
25
+
{% block content %}{% endblock %}
26
+
</main>
27
+
24
28
</body>
25
29
</html>
+31
-22
web/templates/login.askama.html
+31
-22
web/templates/login.askama.html
···
1
1
{% extends "layout.askama.html" %}
2
2
3
3
{% block content %}
4
-
<h2 class="text-xl mb-4">Login</h2>
5
-
<p class="mb-4">Enter your Bluesky handle to continue.</p>
6
-
{% if let Some(err) = error %}
7
-
<div class="alert alert-error mb-4">{{ err }}</div>
8
-
{% endif %}
9
-
<form id="handle-form" class="flex gap-2" onsubmit="return goToHandle(event)">
10
-
<input id="handle-input" type="text" name="handle" placeholder="you.bsky.social" class="input input-bordered"
11
-
required/>
12
-
<button class="btn" type="submit">Continue</button>
13
-
</form>
14
-
<script>
4
+
<div class="hero min-h-[60vh]">
5
+
<div class="hero-content flex-col lg:flex-row-reverse">
6
+
<div class="text-center lg:text-left lg:ml-8">
7
+
<h1 class="text-5xl font-bold">Login to continue</h1>
8
+
<p class="py-6">Enter your AT Protocol handle to track your progress and complete daily challenges.</p>
9
+
</div>
10
+
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
11
+
<div class="card-body">
12
+
{% if let Some(err) = error %}
13
+
<div class="alert alert-error mb-4">
14
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
15
+
<span>{{ err }}</span>
16
+
</div>
17
+
{% endif %}
18
+
19
+
<form id="handle-form" action="/redirect/login" method="GET" >
20
+
<div class="">
21
+
<fieldset class="fieldset">
22
+
<legend class="fieldset-legend">AT Protocol Handle</legend>
23
+
<input id="handle-input" name="handle" type="text" class="input input-md" placeholder="alice.bsky.social" required/>
24
+
</fieldset>
25
+
26
+
</div>
27
+
<div class="form-control mt-6">
28
+
<button class="btn btn-primary" type="submit">Continue</button>
29
+
</div>
30
+
</form>
31
+
</div>
32
+
</div>
33
+
</div>
34
+
</div>
15
35
16
-
function goToHandle(e) {
17
-
e.preventDefault();
18
-
const input = document.getElementById('handle-input');
19
-
const handle = (input.value || '').trim();
20
-
if (!handle) return false;
21
-
const encoded = encodeURIComponent(handle);
22
-
// Redirect to /handle/{handle}
23
-
window.location.href = `/login/${encoded}`;
24
-
return false;
25
-
}
26
-
</script>
27
36
{% endblock %}