diff --git a/Gemfile b/Gemfile index 614a2e95..ce746208 100644 --- a/Gemfile +++ b/Gemfile @@ -52,6 +52,7 @@ gem 'jwt' group :development, :test do gem 'brakeman', require: false + gem 'bullet' gem 'bundler-audit', require: false gem 'debug', platforms: %i[mri mingw x64_mingw] gem 'dotenv-rails' @@ -78,3 +79,9 @@ group :development do gem 'foreman' gem 'rubocop-rails', require: false end + +# group :production do +# gem 'uglifier' +# end + +# gem 'sassc-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 4b955b5a..c5a1fd55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,9 @@ GEM brakeman (7.0.2) racc builder (3.3.0) + bullet (8.0.8) + activesupport (>= 3.0.0) + uniform_notifier (~> 1.11) bundler-audit (0.9.2) bundler (>= 1.2.0, < 3) thor (~> 1.0) @@ -486,6 +489,7 @@ GEM unicode-display_width (3.1.4) unicode-emoji (~> 4.0, >= 4.0.4) unicode-emoji (4.0.4) + uniform_notifier (1.17.0) uri (1.0.3) useragent (0.16.11) warden (1.2.9) @@ -519,6 +523,7 @@ DEPENDENCIES aws-sdk-s3 (~> 1.177.0) bootsnap brakeman + bullet bundler-audit capybara chartkick diff --git a/app/assets/builds/tailwind.css b/app/assets/builds/tailwind.css index 5efebdd7..e3cabadd 100644 --- a/app/assets/builds/tailwind.css +++ b/app/assets/builds/tailwind.css @@ -1,6 +1,6415 @@ -*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:Inter var,ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]:where(:not([hidden=until-found])){display:none}:root,[data-theme]{background-color:var(--fallback-b1,oklch(var(--b1)/1));color:var(--fallback-bc,oklch(var(--bc)/1))}@supports not (color:oklch(0 0 0)){:root{color-scheme:light;--fallback-p:#491eff;--fallback-pc:#d4dbff;--fallback-s:#ff41c7;--fallback-sc:#fff9fc;--fallback-a:#00cfbd;--fallback-ac:#00100d;--fallback-n:#2b3440;--fallback-nc:#d7dde4;--fallback-b1:#fff;--fallback-b2:#e5e6e6;--fallback-b3:#e5e6e6;--fallback-bc:#1f2937;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--fallback-p:#7582ff;--fallback-pc:#050617;--fallback-s:#ff71cf;--fallback-sc:#190211;--fallback-a:#00c7b5;--fallback-ac:#000e0c;--fallback-n:#2a323c;--fallback-nc:#a6adbb;--fallback-b1:#1d232a;--fallback-b2:#191e24;--fallback-b3:#15191e;--fallback-bc:#a6adbb;--fallback-in:#00b3f0;--fallback-inc:#000;--fallback-su:#00ca92;--fallback-suc:#000;--fallback-wa:#ffc22d;--fallback-wac:#000;--fallback-er:#ff6f70;--fallback-erc:#000}}}html{-webkit-tap-highlight-color:transparent}:root{color-scheme:light;--in:0.7206 0.191 231.6;--su:64.8% 0.150 160;--wa:0.8471 0.199 83.87;--er:0.7176 0.221 22.18;--pc:0.89824 0.06192 275.75;--ac:0.15352 0.0368 183.61;--inc:0 0 0;--suc:0 0 0;--wac:0 0 0;--erc:0 0 0;--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--p:0.4912 0.3096 275.75;--s:0.6971 0.329 342.55;--sc:0.9871 0.0106 342.55;--a:0.7676 0.184 183.61;--n:0.321785 0.02476 255.701624;--nc:0.894994 0.011585 252.096176;--b1:1 0 0;--b2:0.961151 0 0;--b3:0.924169 0.00108 197.137559;--bc:0.278078 0.029596 256.847952}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--in:0.7206 0.191 231.6;--su:64.8% 0.150 160;--wa:0.8471 0.199 83.87;--er:0.7176 0.221 22.18;--pc:0.13138 0.0392 275.75;--sc:0.1496 0.052 342.55;--ac:0.14902 0.0334 183.61;--inc:0 0 0;--suc:0 0 0;--wac:0 0 0;--erc:0 0 0;--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--p:0.6569 0.196 275.75;--s:0.748 0.26 342.55;--a:0.7451 0.167 183.61;--n:0.313815 0.021108 254.139175;--nc:0.746477 0.0216 264.435964;--b1:0.253267 0.015896 252.417568;--b2:0.232607 0.013807 253.100675;--b3:0.211484 0.01165 254.087939;--bc:0.746477 0.0216 264.435964}}[data-theme=light]{color-scheme:light;--in:0.7206 0.191 231.6;--su:64.8% 0.150 160;--wa:0.8471 0.199 83.87;--er:0.7176 0.221 22.18;--pc:0.89824 0.06192 275.75;--ac:0.15352 0.0368 183.61;--inc:0 0 0;--suc:0 0 0;--wac:0 0 0;--erc:0 0 0;--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--p:0.4912 0.3096 275.75;--s:0.6971 0.329 342.55;--sc:0.9871 0.0106 342.55;--a:0.7676 0.184 183.61;--n:0.321785 0.02476 255.701624;--nc:0.894994 0.011585 252.096176;--b1:1 0 0;--b2:0.961151 0 0;--b3:0.924169 0.00108 197.137559;--bc:0.278078 0.029596 256.847952}[data-theme=dark]{color-scheme:dark;--in:0.7206 0.191 231.6;--su:64.8% 0.150 160;--wa:0.8471 0.199 83.87;--er:0.7176 0.221 22.18;--pc:0.13138 0.0392 275.75;--sc:0.1496 0.052 342.55;--ac:0.14902 0.0334 183.61;--inc:0 0 0;--suc:0 0 0;--wac:0 0 0;--erc:0 0 0;--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-focus-scale:0.95;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;--p:0.6569 0.196 275.75;--s:0.748 0.26 342.55;--a:0.7451 0.167 183.61;--n:0.313815 0.021108 254.139175;--nc:0.746477 0.0216 264.435964;--b1:0.253267 0.015896 252.417568;--b2:0.232607 0.013807 253.100675;--b3:0.211484 0.01165 254.087939;--bc:0.746477 0.0216 264.435964}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],input:where(:not([type])),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,input:where(:not([type])):focus,select:focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-bottom:0;padding-top:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-origin:border-box;border-color:#6b7280;border-width:1px;color:#2563eb;display:inline-block;flex-shrink:0;height:1rem;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:1rem;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{background-color:currentColor;background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{background-color:currentColor;border-color:transparent}[type=checkbox]:indeterminate{background-color:currentColor;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}@media (forced-colors:active) {[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{background-color:currentColor;border-color:transparent}[type=file]{background:unset;border-color:inherit;border-radius:0;border-width:0;font-size:unset;line-height:inherit;padding:0}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.alert{align-content:flex-start;align-items:center;border-radius:var(--rounded-box,1rem);border-width:1px;display:grid;gap:1rem;grid-auto-flow:row;justify-items:center;text-align:center;width:100%;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));padding:1rem;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-b2,oklch(var(--b2)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1));background-color:var(--alert-bg)}@media (min-width:640px){.alert{grid-auto-flow:column;grid-template-columns:auto minmax(auto,1fr);justify-items:start;text-align:start}}.avatar.placeholder>div{align-items:center;display:flex;justify-content:center}.badge{align-items:center;border-radius:var(--rounded-badge,1.9rem);border-width:1px;display:inline-flex;font-size:.875rem;height:1.25rem;justify-content:center;line-height:1.25rem;padding-left:.563rem;padding-right:.563rem;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);width:-moz-fit-content;width:fit-content;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}@media (hover:hover){.label a:hover{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.menu li>:not(ul,.menu-title,details,.btn).active,.menu li>:not(ul,.menu-title,details,.btn):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.radio-primary:hover{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.tab:hover{--tw-text-opacity:1}.tabs-boxed .tab-active:not(.tab-disabled):not([disabled]):hover,.tabs-boxed :is(input:checked):hover{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.table tr.hover:hover,.table tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.table-zebra tr.hover:hover,.table-zebra tr.hover:nth-child(2n):hover{--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}}.btn{align-items:center;animation:button-pop var(--animation-btn,.25s) ease-out;border-color:transparent;border-color:oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity));border-radius:var(--rounded-btn,.5rem);border-width:var(--border-btn,1px);cursor:pointer;display:inline-flex;flex-shrink:0;flex-wrap:wrap;font-size:.875rem;font-weight:600;gap:.5rem;height:3rem;justify-content:center;line-height:1em;min-height:3rem;padding-left:1rem;padding-right:1rem;text-align:center;text-decoration-line:none;transition-duration:.2s;transition-property:color,background-color,border-color,opacity,box-shadow,transform;transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);background-color:oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity));box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:var(--fallback-bc,oklch(var(--bc)/1));--tw-bg-opacity:1;--tw-border-opacity:1}.btn-disabled,.btn:disabled,.btn[disabled]{pointer-events:none}:where(.btn:is(input[type=checkbox])),:where(.btn:is(input[type=radio])){-webkit-appearance:none;-moz-appearance:none;appearance:none;width:auto}.btn:is(input[type=checkbox]):after,.btn:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.card{border-radius:var(--rounded-box,1rem);display:flex;flex-direction:column;position:relative}.card:focus{outline:2px solid transparent;outline-offset:2px}.card-body{display:flex;flex:1 1 auto;flex-direction:column;gap:.5rem;padding:var(--padding-card,2rem)}.card-body :where(p){flex-grow:1}.card-actions{align-items:flex-start;display:flex;flex-wrap:wrap;gap:.5rem}.card figure{align-items:center;display:flex;justify-content:center}.card.image-full{display:grid}.card.image-full:before{border-radius:var(--rounded-box,1rem);content:"";position:relative;z-index:10;--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));opacity:.75}.card.image-full:before,.card.image-full>*{grid-column-start:1;grid-row-start:1}.card.image-full>figure img{height:100%;-o-object-fit:cover;object-fit:cover}.card.image-full>.card-body{position:relative;z-index:20;--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.checkbox{flex-shrink:0;--chkbg:var(--fallback-bc,oklch(var(--bc)/1));--chkfg:var(--fallback-b1,oklch(var(--b1)/1));-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;height:1.5rem;width:1.5rem;--tw-border-opacity:0.2}.divider{align-items:center;align-self:stretch;display:flex;flex-direction:row;height:1rem;margin-bottom:1rem;margin-top:1rem;white-space:nowrap}.divider:after,.divider:before{flex-grow:1;height:.125rem;width:100%;--tw-content:"";background-color:var(--fallback-bc,oklch(var(--bc)/.1));content:var(--tw-content)}.\!drawer{display:grid!important;grid-auto-columns:max-content auto!important;position:relative!important;width:100%!important}.drawer{display:grid;grid-auto-columns:max-content auto;position:relative;width:100%}.dropdown{display:inline-block;position:relative}.dropdown>:not(summary):focus{outline:2px solid transparent;outline-offset:2px}.dropdown .dropdown-content{position:absolute}.dropdown:is(:not(details)) .dropdown-content{opacity:0;transform-origin:top;visibility:hidden;--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.dropdown-end .dropdown-content{inset-inline-end:0}.dropdown-left .dropdown-content{bottom:auto;inset-inline-end:100%;top:0;transform-origin:right}.dropdown-right .dropdown-content{bottom:auto;inset-inline-start:100%;top:0;transform-origin:left}.dropdown-bottom .dropdown-content{bottom:auto;top:100%;transform-origin:top}.dropdown-top .dropdown-content{bottom:100%;top:auto;transform-origin:bottom}.dropdown-end.dropdown-left .dropdown-content,.dropdown-end.dropdown-right .dropdown-content{bottom:0;top:auto}.dropdown.dropdown-open .dropdown-content,.dropdown:focus-within .dropdown-content,.dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1;visibility:visible}@media (hover:hover){.dropdown.dropdown-hover:hover .dropdown-content{opacity:1;visibility:visible}.btm-nav>.disabled:hover,.btm-nav>[disabled]:hover{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:hover{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn:hover{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b2))/var(--tw-border-opacity,1)) 90%,#000)}}@supports not (color:oklch(0 0 0)){.btn:hover{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}}.btn.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost:hover{border-color:transparent}@supports (color:oklch(0 0 0)){.btn-ghost:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.btn-outline:hover{--tw-border-opacity:1;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)))}.btn-outline.btn-primary:hover{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-primary:hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.btn-outline.btn-secondary:hover{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-secondary:hover{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}}.btn-outline.btn-accent:hover{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-accent:hover{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}}.btn-outline.btn-success:hover{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-success:hover{background-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000)}}.btn-outline.btn-info:hover{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-info:hover{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}}.btn-outline.btn-warning:hover{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-warning:hover{background-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000)}}.btn-outline.btn-error:hover{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.btn-outline.btn-error:hover{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn-disabled:hover,.btn:disabled:hover,.btn[disabled]:hover{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}@supports (color:color-mix(in oklab,black,black)){.btn:is(input[type=checkbox]:checked):hover,.btn:is(input[type=radio]:checked):hover{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}}.dropdown.dropdown-hover:hover .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(.active,.btn):hover,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.active,.btn):hover{cursor:pointer;outline:2px solid transparent;outline-offset:2px}@supports (color:oklch(0 0 0)){:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(.active,.btn):hover,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.active,.btn):hover{background-color:var(--fallback-bc,oklch(var(--bc)/.1))}}.tab[disabled],.tab[disabled]:hover{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));cursor:not-allowed;--tw-text-opacity:0.2}}.dropdown:is(details) summary::-webkit-details-marker{display:none}.file-input{border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:1rem;height:3rem;line-height:2;line-height:1.5rem;overflow:hidden;padding-inline-end:1rem;--tw-border-opacity:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.file-input::file-selector-button{align-items:center;border-style:solid;cursor:pointer;display:inline-flex;flex-shrink:0;flex-wrap:wrap;font-size:.875rem;height:100%;justify-content:center;line-height:1.25rem;line-height:1em;margin-inline-end:1rem;padding-left:1rem;padding-right:1rem;text-align:center;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-border-opacity:1;border-color:var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));font-weight:600;text-transform:uppercase;--tw-text-opacity:1;animation:button-pop var(--animation-btn,.25s) ease-out;border-width:var(--border-btn,1px);color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));text-decoration-line:none}.footer{-moz-column-gap:1rem;column-gap:1rem;font-size:.875rem;grid-auto-flow:row;line-height:1.25rem;row-gap:2.5rem;width:100%}.footer,.footer>*{display:grid;place-items:start}.footer>*{gap:.5rem}@media (min-width:48rem){.footer{grid-auto-flow:column}.footer-center{grid-auto-flow:row dense}}.form-control{flex-direction:column}.form-control,.label{display:flex}.label{align-items:center;justify-content:space-between;padding:.5rem .25rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.hero{background-position:50%;background-size:cover;display:grid;place-items:center;width:100%}.hero>*{grid-column-start:1;grid-row-start:1}.hero-content{align-items:center;display:flex;gap:1rem;justify-content:center;max-width:80rem;padding:1rem;z-index:0}.indicator{display:inline-flex;position:relative;width:-moz-max-content;width:max-content}.indicator :where(.indicator-item){position:absolute;white-space:nowrap;z-index:1}.input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:transparent;border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:1rem;height:3rem;line-height:2;line-height:1.5rem;padding-left:1rem;padding-right:1rem;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.input-md[type=number]::-webkit-inner-spin-button,.input[type=number]::-webkit-inner-spin-button{margin-bottom:-1rem;margin-top:-1rem;margin-inline-end:-1rem}.input-xs[type=number]::-webkit-inner-spin-button{margin-bottom:-.25rem;margin-top:-.25rem;margin-inline-end:0}.input-sm[type=number]::-webkit-inner-spin-button{margin-bottom:0;margin-top:0;margin-inline-end:0}.join{align-items:stretch;border-radius:var(--rounded-btn,.5rem);display:inline-flex}.join :where(.join-item){border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:0;border-start-start-radius:0}.join .join-item:not(:first-child):not(:last-child),.join :not(:first-child):not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:0;border-start-start-radius:0}.join .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-start-end-radius:0}.join .dropdown .join-item:first-child:not(:last-child),.join :first-child:not(:last-child) .dropdown .join-item{border-end-end-radius:inherit;border-start-end-radius:inherit}.join :where(.join-item:first-child:not(:last-child)),.join :where(:first-child:not(:last-child) .join-item){border-end-start-radius:inherit;border-start-start-radius:inherit}.join .join-item:last-child:not(:first-child),.join :last-child:not(:first-child) .join-item{border-end-start-radius:0;border-start-start-radius:0}.join :where(.join-item:last-child:not(:first-child)),.join :where(:last-child:not(:first-child) .join-item){border-end-end-radius:inherit;border-start-end-radius:inherit}@supports not selector(:has(*)){:where(.join *){border-radius:inherit}}@supports selector(:has(*)){:where(.join :has(.join-item)){border-radius:inherit}}.link{cursor:pointer;text-decoration-line:underline}.menu{display:flex;flex-direction:column;flex-wrap:wrap;font-size:.875rem;line-height:1.25rem;padding:.5rem}.menu :where(li ul){margin-inline-start:1rem;padding-inline-start:.5rem;position:relative;white-space:nowrap}.menu :where(li:not(.menu-title)>:not(ul,details,.menu-title,.btn)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){align-content:flex-start;align-items:center;display:grid;gap:.5rem;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;-webkit-user-select:none;-moz-user-select:none;user-select:none}.menu li.disabled{color:var(--fallback-bc,oklch(var(--bc)/.3));cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;user-select:none}.menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}:where(.menu li){align-items:stretch;display:flex;flex-direction:column;flex-shrink:0;flex-wrap:wrap;position:relative}:where(.menu li) .badge{justify-self:end}.modal{background-color:transparent;color:inherit;display:grid;height:100%;inset:0;justify-items:center;margin:0;max-height:none;max-width:none;opacity:0;overflow-y:hidden;overscroll-behavior:contain;padding:0;pointer-events:none;position:fixed;transition-duration:.2s;transition-property:transform,opacity,visibility;transition-timing-function:cubic-bezier(0,0,.2,1);width:100%;z-index:999}:where(.modal){align-items:center}.modal-box{grid-column-start:1;grid-row-start:1;max-height:calc(100vh - 5em);max-width:32rem;width:91.666667%;--tw-scale-x:.9;--tw-scale-y:.9;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));box-shadow:0 25px 50px -12px rgba(0,0,0,.25);overflow-y:auto;overscroll-behavior:contain;padding:1.5rem;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}.modal-open,.modal-toggle:checked+.modal,.modal:target,.modal[open]{opacity:1;pointer-events:auto;visibility:visible}.modal-action{display:flex;justify-content:flex-end;margin-top:1.5rem}.modal-toggle{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:0;opacity:0;position:fixed;width:0}:root:has(:is(.modal-open,.modal:target,.modal-toggle:checked+.modal,.modal[open])){overflow:hidden}.navbar{align-items:center;display:flex;min-height:4rem;padding:var(--navbar-padding,.5rem);width:100%}:where(.navbar>:not(script,style)){align-items:center;display:inline-flex}.navbar-start{justify-content:flex-start;width:50%}.navbar-center{flex-shrink:0}.navbar-end{justify-content:flex-end;width:50%}.progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--fallback-bc,oklch(var(--bc)/.2));border-radius:var(--rounded-box,1rem);height:.5rem;overflow:hidden;position:relative;width:100%}.radio{flex-shrink:0;--chkbg:var(--bc);-webkit-appearance:none;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));border-radius:9999px;border-width:1px;width:1.5rem;--tw-border-opacity:0.2}.radio,.range{-moz-appearance:none;appearance:none;cursor:pointer;height:1.5rem}.range{-webkit-appearance:none;width:100%;--range-shdw:var(--fallback-bc,oklch(var(--bc)/1));background-color:transparent;border-radius:var(--rounded-box,1rem);overflow:hidden}.range:focus{outline:none}.select{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:transparent;border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;display:inline-flex;font-size:.875rem;height:3rem;line-height:1.25rem;line-height:2;min-height:3rem;padding-left:1rem;padding-right:2.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));background-image:linear-gradient(45deg,transparent 50%,currentColor 0),linear-gradient(135deg,currentColor 50%,transparent 0);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px}.select[multiple]{height:auto}.stack{display:inline-grid;place-items:center;align-items:flex-end}.stack>*{grid-column-start:1;grid-row-start:1;opacity:.6;transform:translateY(10%) scale(.9);width:100%;z-index:1}.stack>:nth-child(2){opacity:.8;transform:translateY(5%) scale(.95);z-index:2}.stack>:first-child{opacity:1;transform:translateY(0) scale(1);z-index:3}.stats{border-radius:var(--rounded-box,1rem);display:inline-grid;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}:where(.stats){grid-auto-flow:column;overflow-x:auto}.stat{border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));-moz-column-gap:1rem;column-gap:1rem;display:inline-grid;grid-template-columns:repeat(1,1fr);width:100%;--tw-border-opacity:0.1;padding:1rem 1.5rem}.stat-title{color:var(--fallback-bc,oklch(var(--bc)/.6))}.stat-title,.stat-value{grid-column-start:1;white-space:nowrap}.stat-value{font-size:2.25rem;font-weight:800;line-height:2.5rem}.stat-desc{color:var(--fallback-bc,oklch(var(--bc)/.6));font-size:.75rem;grid-column-start:1;line-height:1rem;white-space:nowrap}.steps .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-columns:auto;grid-template-rows:repeat(2,minmax(0,1fr));grid-template-rows:40px 1fr;min-width:4rem;place-items:center;text-align:center}.tabs{align-items:flex-end;display:grid}.tabs-lifted:has(.tab-content[class*=" rounded-"]) .tab:first-child:not(.tab-active),.tabs-lifted:has(.tab-content[class^=rounded-]) .tab:first-child:not(.tab-active){border-bottom-color:transparent}.tab{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;display:inline-flex;flex-wrap:wrap;font-size:.875rem;grid-row-start:1;height:2rem;justify-content:center;line-height:1.25rem;line-height:2;position:relative;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;--tab-padding:1rem;--tw-text-opacity:0.5;--tab-color:var(--fallback-bc,oklch(var(--bc)/1));--tab-bg:var(--fallback-b1,oklch(var(--b1)/1));--tab-border-color:var(--fallback-b3,oklch(var(--b3)/1));color:var(--tab-color);padding-inline-end:var(--tab-padding,1rem);padding-inline-start:var(--tab-padding,1rem)}.tab:is(input[type=radio]){border-bottom-left-radius:0;border-bottom-right-radius:0;width:auto}.tab:is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.tab:not(input):empty{cursor:default;grid-column-start:span 9999}.tab-active+.tab-content:nth-child(2),:checked+.tab-content:nth-child(2){border-start-start-radius:0}.tab-active+.tab-content,input.tab:checked+.tab-content{display:block}.table{border-radius:var(--rounded-box,1rem);font-size:.875rem;line-height:1.25rem;position:relative;text-align:left;width:100%}.table :where(.table-pin-rows thead tr){position:sticky;top:0;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-rows tfoot tr){bottom:0;position:sticky;z-index:1;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.table :where(.table-pin-cols tr th){left:0;position:sticky;right:0;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.timeline{display:flex;position:relative}:where(.timeline>li){align-items:center;display:grid;flex-shrink:0;grid-template-columns:var(--timeline-col-start,minmax(0,1fr)) auto var( - --timeline-col-end,minmax(0,1fr) - );grid-template-rows:var(--timeline-row-start,minmax(0,1fr)) auto var( - --timeline-row-end,minmax(0,1fr) - );position:relative}.timeline>li>hr{border-width:0;width:100%}:where(.timeline>li>hr):first-child{grid-column-start:1;grid-row-start:2}:where(.timeline>li>hr):last-child{grid-column-end:none;grid-column-start:3;grid-row-end:auto;grid-row-start:2}.timeline-start{align-self:flex-end;grid-column-end:4;grid-column-start:1;grid-row-end:2;grid-row-start:1;justify-self:center;margin:.25rem}.timeline-middle{grid-column-start:2;grid-row-start:2}.timeline-end{align-self:flex-start;grid-column-end:4;grid-column-start:1;grid-row-end:4;grid-row-start:3;justify-self:center;margin:.25rem}.toggle{flex-shrink:0;--tglbg:var(--fallback-b1,oklch(var(--b1)/1));--handleoffset:1.5rem;--handleoffsetcalculator:calc(var(--handleoffset)*-1);--togglehandleborder:0 0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:currentColor;border-color:currentColor;border-radius:var(--rounded-badge,1.9rem);border-width:1px;box-shadow:var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset,var(--togglehandleborder);color:var(--fallback-bc,oklch(var(--bc)/.5));cursor:pointer;height:1.5rem;transition:background,box-shadow var(--animation-input,.2s) ease-out;width:3rem}.alert-info{border-color:var(--fallback-in,oklch(var(--in)/.2));--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));--alert-bg:var(--fallback-in,oklch(var(--in)/1));--alert-bg-mix:var(--fallback-b1,oklch(var(--b1)/1))}.badge-primary{background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.badge-primary,.badge-secondary{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1}.badge-secondary{background-color:var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity)));border-color:var(--fallback-s,oklch(var(--s)/var(--tw-border-opacity)));color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.badge-success{background-color:var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity)));color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.badge-success,.badge-warning{border-color:transparent;--tw-bg-opacity:1;--tw-text-opacity:1}.badge-warning{background-color:var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity)));color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.badge-outline{border-color:currentColor;--tw-border-opacity:0.5;background-color:transparent;color:currentColor}.badge-outline.badge-neutral{--tw-text-opacity:1;color:var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity)))}.badge-outline.badge-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.badge-outline.badge-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.badge-outline.badge-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.badge-outline.badge-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.badge-outline.badge-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.badge-outline.badge-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)))}.badge-outline.badge-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.btm-nav>:where(.active){border-top-width:2px;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)))}.btm-nav>.disabled,.btm-nav>[disabled]{pointer-events:none;--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btm-nav>* .label{font-size:1rem;line-height:1.5rem}.btn:active:focus,.btn:active:hover{animation:button-pop 0s ease-out;transform:scale(var(--btn-focus-scale,.97))}@supports not (color:oklch(0 0 0)){.btn{background-color:var(--btn-color,var(--fallback-b2));border-color:var(--btn-color,var(--fallback-b2))}.btn-primary{--btn-color:var(--fallback-p)}.btn-neutral{--btn-color:var(--fallback-n)}.btn-info{--btn-color:var(--fallback-in)}.btn-success{--btn-color:var(--fallback-su)}.btn-warning{--btn-color:var(--fallback-wa)}.btn-error{--btn-color:var(--fallback-er)}}@supports (color:color-mix(in oklab,black,black)){.btn-active{background-color:color-mix(in oklab,oklch(var(--btn-color,var(--b3))/var(--tw-bg-opacity,1)) 90%,#000);border-color:color-mix(in oklab,oklch(var(--btn-color,var(--b3))/var(--tw-border-opacity,1)) 90%,#000)}.btn-outline.btn-primary.btn-active{background-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 90%,#000)}.btn-outline.btn-secondary.btn-active{background-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-s,oklch(var(--s)/1)) 90%,#000)}.btn-outline.btn-accent.btn-active{background-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-a,oklch(var(--a)/1)) 90%,#000)}.btn-outline.btn-success.btn-active{background-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-su,oklch(var(--su)/1)) 90%,#000)}.btn-outline.btn-info.btn-active{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}.btn-outline.btn-warning.btn-active{background-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-wa,oklch(var(--wa)/1)) 90%,#000)}.btn-outline.btn-error.btn-active{background-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-er,oklch(var(--er)/1)) 90%,#000)}}.btn:focus-visible{outline-offset:2px;outline-style:solid;outline-width:2px}.btn-primary{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));outline-color:var(--fallback-p,oklch(var(--p)/1))}@supports (color:oklch(0 0 0)){.btn-primary{--btn-color:var(--p)}.btn-neutral{--btn-color:var(--n)}.btn-info{--btn-color:var(--in)}.btn-success{--btn-color:var(--su)}.btn-warning{--btn-color:var(--wa)}.btn-error{--btn-color:var(--er)}}.btn-neutral{--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)));outline-color:var(--fallback-n,oklch(var(--n)/1))}.btn-info{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));outline-color:var(--fallback-in,oklch(var(--in)/1))}.btn-success{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)));outline-color:var(--fallback-su,oklch(var(--su)/1))}.btn-warning{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)));outline-color:var(--fallback-wa,oklch(var(--wa)/1))}.btn-error{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));outline-color:var(--fallback-er,oklch(var(--er)/1))}.btn.glass{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn.glass.btn-active{--glass-opacity:25%;--glass-border-opacity:15%}.btn-ghost{background-color:transparent;border-color:transparent;border-width:1px;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.btn-ghost.btn-active{background-color:var(--fallback-bc,oklch(var(--bc)/.2));border-color:transparent}.btn-link.btn-active{background-color:transparent;border-color:transparent;text-decoration-line:underline}.btn-outline{background-color:transparent;border-color:currentColor;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.btn-outline.btn-active{--tw-border-opacity:1;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)))}.btn-outline.btn-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}.btn-outline.btn-primary.btn-active{--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn-outline.btn-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)))}.btn-outline.btn-secondary.btn-active{--tw-text-opacity:1;color:var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)))}.btn-outline.btn-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)))}.btn-outline.btn-accent.btn-active{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)))}.btn-outline.btn-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)))}.btn-outline.btn-success.btn-active{--tw-text-opacity:1;color:var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)))}.btn-outline.btn-info{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.btn-outline.btn-info.btn-active{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.btn-outline.btn-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)))}.btn-outline.btn-warning.btn-active{--tw-text-opacity:1;color:var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)))}.btn-outline.btn-error{--tw-text-opacity:1;color:var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)))}.btn-outline.btn-error.btn-active{--tw-text-opacity:1;color:var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)))}.btn.btn-disabled,.btn:disabled,.btn[disabled]{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.btn:is(input[type=checkbox]:checked),.btn:is(input[type=radio]:checked){--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.btn:is(input[type=checkbox]:checked):focus-visible,.btn:is(input[type=radio]:checked):focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}@keyframes button-pop{0%{transform:scale(var(--btn-focus-scale,.98))}40%{transform:scale(1.02)}to{transform:scale(1)}}.card :where(figure:first-child){border-end-end-radius:unset;border-end-start-radius:unset;border-start-end-radius:inherit;border-start-start-radius:inherit;overflow:hidden}.card :where(figure:last-child){border-end-end-radius:inherit;border-end-start-radius:inherit;border-start-end-radius:unset;border-start-start-radius:unset;overflow:hidden}.card:focus-visible{outline:2px solid currentColor;outline-offset:2px}.card.bordered{border-width:1px;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.card.compact .card-body{font-size:.875rem;line-height:1.25rem;padding:1rem}.card-title{align-items:center;display:flex;font-size:1.25rem;font-weight:600;gap:.5rem;line-height:1.75rem}.card.image-full :where(figure){border-radius:inherit;overflow:hidden}.checkbox:focus{box-shadow:none}.checkbox:focus-visible{outline-color:var(--fallback-bc,oklch(var(--bc)/1));outline-offset:2px;outline-style:solid;outline-width:2px}.checkbox:checked,.checkbox[aria-checked=true],.checkbox[checked=true]{animation:checkmark var(--animation-input,.2s) ease-out;background-color:var(--chkbg);background-image:linear-gradient(-45deg,transparent 65%,var(--chkbg) 65.99%),linear-gradient(45deg,transparent 75%,var(--chkbg) 75.99%),linear-gradient(-45deg,var(--chkbg) 40%,transparent 40.99%),linear-gradient(45deg,var(--chkbg) 30%,var(--chkfg) 30.99%,var(--chkfg) 40%,transparent 40.99%),linear-gradient(-45deg,var(--chkfg) 50%,var(--chkbg) 50.99%);background-repeat:no-repeat}.checkbox:indeterminate{--tw-bg-opacity:1;animation:checkmark var(--animation-input,.2s) ease-out;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));background-image:linear-gradient(90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(-90deg,transparent 80%,var(--chkbg) 80%),linear-gradient(0deg,var(--chkbg) 43%,var(--chkfg) 43%,var(--chkfg) 57%,var(--chkbg) 57%);background-repeat:no-repeat}.checkbox:disabled{border-color:transparent;cursor:not-allowed;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));opacity:.2}@keyframes checkmark{0%{background-position-y:5px}50%{background-position-y:-2px}to{background-position-y:0}}.divider:not(:empty){gap:1rem}.drawer-toggle:focus-visible~.drawer-content label.drawer-button{outline-offset:2px;outline-style:solid;outline-width:2px}.dropdown.dropdown-open .dropdown-content,.dropdown:focus .dropdown-content,.dropdown:focus-within .dropdown-content{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.file-input-bordered{--tw-border-opacity:0.2}.file-input:focus{outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.file-input-disabled,.file-input[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));--tw-text-opacity:0.2}.file-input-disabled::-moz-placeholder,.file-input[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.file-input-disabled::placeholder,.file-input[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.file-input-disabled::file-selector-button,.file-input[disabled]::file-selector-button{--tw-border-opacity:0;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-bg-opacity:0.2;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.footer-title{font-weight:700;margin-bottom:.5rem;opacity:.6;text-transform:uppercase}.label-text{font-size:.875rem;line-height:1.25rem}.label-text,.label-text-alt{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.label-text-alt{font-size:.75rem;line-height:1rem}.input input{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));background-color:transparent}.input input:focus{outline:2px solid transparent;outline-offset:2px}.input[list]::-webkit-calendar-picker-indicator{line-height:1em}.input-bordered{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.input:focus,.input:focus-within{border-color:var(--fallback-bc,oklch(var(--bc)/.2));box-shadow:none;outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.input-ghost{--tw-bg-opacity:0.05}.input-ghost:focus,.input-ghost:focus-within{--tw-bg-opacity:1;--tw-text-opacity:1;box-shadow:none;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}.input-primary{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.input-primary:focus,.input-primary:focus-within{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));outline-color:var(--fallback-p,oklch(var(--p)/1))}.input-error{--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)))}.input-error:focus,.input-error:focus-within{--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)));outline-color:var(--fallback-er,oklch(var(--er)/1))}.input-disabled,.input:disabled,.input[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));color:var(--fallback-bc,oklch(var(--bc)/.4))}.input-disabled::-moz-placeholder,.input:disabled::-moz-placeholder,.input[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input-disabled::placeholder,.input:disabled::placeholder,.input[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.input::-webkit-date-and-time-value{text-align:inherit}.join>:where(:not(:first-child)){margin-bottom:0;margin-top:0;margin-inline-start:-1px}.join-item:focus{isolation:isolate}.link-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){@media (hover:hover){.link-primary:hover{color:color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 80%,#000)}}}.link:focus{outline:2px solid transparent;outline-offset:2px}.link:focus-visible{outline:2px solid currentColor;outline-offset:2px}.loading{aspect-ratio:1/1;background-color:currentColor;display:inline-block;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100%;mask-size:100%;pointer-events:none;width:1.5rem}.loading,.loading-spinner{-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Cstyle%3E@keyframes spinner_zKoa{to{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%25{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%25{stroke-dasharray:42 150;stroke-dashoffset:-16}95%25,to{stroke-dasharray:42 150;stroke-dashoffset:-59}}%3C/style%3E%3Cg style='transform-origin:center;animation:spinner_zKoa 2s linear infinite'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' class='spinner_V8m1' style='stroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite'/%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' stroke='%23000'%3E%3Cstyle%3E@keyframes spinner_zKoa{to{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%25{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%25{stroke-dasharray:42 150;stroke-dashoffset:-16}95%25,to{stroke-dasharray:42 150;stroke-dashoffset:-59}}%3C/style%3E%3Cg style='transform-origin:center;animation:spinner_zKoa 2s linear infinite'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' class='spinner_V8m1' style='stroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite'/%3E%3C/g%3E%3C/svg%3E")}.loading-dots{-webkit-mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cstyle%3E@keyframes spinner_8HQG{0%25,57.14%25{animation-timing-function:cubic-bezier(.33,.66,.66,1);transform:translate(0)}28.57%25{animation-timing-function:cubic-bezier(.33,0,.66,.33);transform:translateY(-6px)}to{transform:translate(0)}}.spinner_qM83{animation:spinner_8HQG 1.05s infinite}%3C/style%3E%3Ccircle cx='4' cy='12' r='3' class='spinner_qM83'/%3E%3Ccircle cx='12' cy='12' r='3' class='spinner_qM83' style='animation-delay:.1s'/%3E%3Ccircle cx='20' cy='12' r='3' class='spinner_qM83' style='animation-delay:.2s'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cstyle%3E@keyframes spinner_8HQG{0%25,57.14%25{animation-timing-function:cubic-bezier(.33,.66,.66,1);transform:translate(0)}28.57%25{animation-timing-function:cubic-bezier(.33,0,.66,.33);transform:translateY(-6px)}to{transform:translate(0)}}.spinner_qM83{animation:spinner_8HQG 1.05s infinite}%3C/style%3E%3Ccircle cx='4' cy='12' r='3' class='spinner_qM83'/%3E%3Ccircle cx='12' cy='12' r='3' class='spinner_qM83' style='animation-delay:.1s'/%3E%3Ccircle cx='20' cy='12' r='3' class='spinner_qM83' style='animation-delay:.2s'/%3E%3C/svg%3E")}.loading-sm{width:1.25rem}.loading-md{width:1.5rem}.loading-lg{width:2.5rem}:where(.menu li:empty){--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));height:1px;margin:.5rem 1rem;opacity:.1}.menu :where(li ul):before{bottom:.75rem;inset-inline-start:0;position:absolute;top:.75rem;width:1px;--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));content:"";opacity:.1}.menu :where(li:not(.menu-title)>:not(ul,details,.menu-title,.btn)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--rounded-btn,.5rem);padding:.5rem 1rem;text-align:start;text-wrap:balance;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1)}:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):is(summary):not(.active,.btn):focus-visible,:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(summary,.active,.btn).focus,:where(.menu li:not(.menu-title,.disabled)>:not(ul,details,.menu-title)):not(summary,.active,.btn):focus,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):is(summary):not(.active,.btn):focus-visible,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(summary,.active,.btn).focus,:where(.menu li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(summary,.active,.btn):focus{background-color:var(--fallback-bc,oklch(var(--bc)/.1));cursor:pointer;--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));outline:2px solid transparent;outline-offset:2px}.menu li>:not(ul,.menu-title,details,.btn).active,.menu li>:not(ul,.menu-title,details,.btn):active,.menu li>details>summary:active{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity)))}.menu :where(li>details>summary)::-webkit-details-marker{display:none}.menu :where(li>.menu-dropdown-toggle):after,.menu :where(li>details>summary):after{box-shadow:2px 2px;content:"";display:block;height:.5rem;justify-self:end;margin-top:-.5rem;pointer-events:none;transform:rotate(45deg);transform-origin:75% 75%;transition-duration:.3s;transition-property:transform,margin-top;transition-timing-function:cubic-bezier(.4,0,.2,1);width:.5rem}.menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after,.menu :where(li>details[open]>summary):after{margin-top:0;transform:rotate(225deg)}.mockup-phone .display{border-radius:40px;margin-top:-25px;overflow:hidden}.mockup-browser .mockup-browser-toolbar .input{display:block;height:1.75rem;margin-left:auto;margin-right:auto;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:24rem;--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));direction:ltr;padding-left:2rem}.mockup-browser .mockup-browser-toolbar .input:before{aspect-ratio:1/1;height:.75rem;left:.5rem;--tw-translate-y:-50%;border-color:currentColor;border-radius:9999px;border-width:2px}.mockup-browser .mockup-browser-toolbar .input:after,.mockup-browser .mockup-browser-toolbar .input:before{content:"";opacity:.6;position:absolute;top:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.mockup-browser .mockup-browser-toolbar .input:after{height:.5rem;left:1.25rem;--tw-translate-y:25%;--tw-rotate:-45deg;border-color:currentColor;border-radius:9999px;border-width:1px}.modal::backdrop,.modal:not(dialog:not(.modal-open)){animation:modal-pop .2s ease-out;background-color:#0006}.modal-backdrop{align-self:stretch;color:transparent;display:grid;grid-column-start:1;grid-row-start:1;justify-self:stretch;z-index:-1}.modal-open .modal-box,.modal-toggle:checked+.modal .modal-box,.modal:target .modal-box,.modal[open] .modal-box{--tw-translate-y:0px;--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-action>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}@keyframes modal-pop{0%{opacity:0}}.progress::-moz-progress-bar{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)))}.progress-primary::-moz-progress-bar{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)))}.progress:indeterminate{--progress-color:var(--fallback-bc,oklch(var(--bc)/1));animation:progress-loading 5s ease-in-out infinite;background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-position-x:15%;background-size:200%}.progress-primary:indeterminate{--progress-color:var(--fallback-p,oklch(var(--p)/1))}.progress::-webkit-progress-bar{background-color:transparent;border-radius:var(--rounded-box,1rem)}.progress::-webkit-progress-value{border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)))}.progress-primary::-webkit-progress-value{--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)))}.progress:indeterminate::-moz-progress-bar{animation:progress-loading 5s ease-in-out infinite;background-color:transparent;background-image:repeating-linear-gradient(90deg,var(--progress-color) -1%,var(--progress-color) 10%,transparent 10%,transparent 90%);background-position-x:15%;background-size:200%}@keyframes progress-loading{50%{background-position-x:-115%}}.radio:focus{box-shadow:none}.radio:focus-visible{outline-color:var(--fallback-bc,oklch(var(--bc)/1));outline-offset:2px;outline-style:solid;outline-width:2px}.radio:checked,.radio[aria-checked=true]{--tw-bg-opacity:1;animation:radiomark var(--animation-input,.2s) ease-out;background-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));background-image:none;box-shadow:0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset}.radio-primary{--chkbg:var(--p);--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.radio-primary:focus-visible{outline-color:var(--fallback-p,oklch(var(--p)/1))}.radio-primary:checked,.radio-primary[aria-checked=true]{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}.radio:disabled{cursor:not-allowed;opacity:.2}@keyframes radiomark{0%{box-shadow:0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset}50%{box-shadow:0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset}to{box-shadow:0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset}}.range:focus-visible::-webkit-slider-thumb{--focus-shadow:0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 2rem var(--range-shdw) inset}.range:focus-visible::-moz-range-thumb{--focus-shadow:0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset,0 0 0 2rem var(--range-shdw) inset}.range::-webkit-slider-runnable-track{background-color:var(--fallback-bc,oklch(var(--bc)/.1));border-radius:var(--rounded-box,1rem);height:.5rem;width:100%}.range::-moz-range-track{background-color:var(--fallback-bc,oklch(var(--bc)/.1));border-radius:var(--rounded-box,1rem);height:.5rem;width:100%}.range::-webkit-slider-thumb{border-radius:var(--rounded-box,1rem);border-style:none;height:1.5rem;position:relative;width:1.5rem;--tw-bg-opacity:1;appearance:none;-webkit-appearance:none;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));color:var(--range-shdw);top:50%;transform:translateY(-50%);--filler-size:100rem;--filler-offset:0.6rem;box-shadow:0 0 0 3px var(--range-shdw) inset,var(--focus-shadow,0 0),calc(var(--filler-size)*-1 - var(--filler-offset)) 0 0 var(--filler-size)}.range::-moz-range-thumb{border-radius:var(--rounded-box,1rem);border-style:none;height:1.5rem;position:relative;width:1.5rem;--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));color:var(--range-shdw);top:50%;--filler-size:100rem;--filler-offset:0.5rem;box-shadow:0 0 0 3px var(--range-shdw) inset,var(--focus-shadow,0 0),calc(var(--filler-size)*-1 - var(--filler-offset)) 0 0 var(--filler-size)}@keyframes rating-pop{0%{transform:translateY(-.125em)}40%{transform:translateY(-.125em)}to{transform:translateY(0)}}.select-bordered,.select:focus{border-color:var(--fallback-bc,oklch(var(--bc)/.2))}.select:focus{box-shadow:none;outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.select-disabled,.select:disabled,.select[disabled]{cursor:not-allowed;--tw-border-opacity:1;border-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));--tw-text-opacity:0.2}.select-disabled::-moz-placeholder,.select:disabled::-moz-placeholder,.select[disabled]::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-disabled::placeholder,.select:disabled::placeholder,.select[disabled]::placeholder{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));--tw-placeholder-opacity:0.2}.select-multiple,.select[multiple],.select[size].select:not([size="1"]){background-image:none;padding-right:1rem}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}:where(.stats)>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0;--tw-divide-y-reverse:0;border-width:calc(0px*(1 - var(--tw-divide-y-reverse))) calc(1px*var(--tw-divide-x-reverse)) calc(0px*var(--tw-divide-y-reverse)) calc(1px*(1 - var(--tw-divide-x-reverse)))}:is([dir=rtl] .stats>:not([hidden])~:not([hidden])){--tw-divide-x-reverse:1}.steps .step:before{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));content:"";height:.5rem;margin-inline-start:-100%;top:0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));width:100%}.steps .step:after,.steps .step:before{grid-column-start:1;grid-row-start:1;--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));--tw-text-opacity:1}.steps .step:after{border-radius:9999px;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));content:counter(step);counter-increment:step;display:grid;height:2rem;place-items:center;place-self:center;position:relative;width:2rem;z-index:1}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.tabs-lifted>.tab:focus-visible{border-end-end-radius:0;border-end-start-radius:0}.tab.tab-active:not(.tab-disabled):not([disabled]),.tab:is(input:checked){border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:1;--tw-text-opacity:1}.tab:focus{outline:2px solid transparent;outline-offset:2px}.tab:focus-visible{outline:2px solid currentColor;outline-offset:-5px}.tab-disabled,.tab[disabled]{color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));cursor:not-allowed;--tw-text-opacity:0.2}.tabs-bordered>.tab{border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));--tw-border-opacity:0.2;border-bottom-width:calc(var(--tab-border, 1px) + 1px);border-style:solid}.tabs-lifted>.tab{border:var(--tab-border,1px) solid transparent;border-bottom-color:var(--tab-border-color);border-start-end-radius:var(--tab-radius,.5rem);border-start-start-radius:var(--tab-radius,.5rem);border-width:0 0 var(--tab-border,1px) 0;padding-inline-end:var(--tab-padding,1rem);padding-inline-start:var(--tab-padding,1rem);padding-top:var(--tab-border,1px)}.tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]),.tabs-lifted>.tab:is(input:checked){background-color:var(--tab-bg);border-inline-end-color:var(--tab-border-color);border-inline-start-color:var(--tab-border-color);border-top-color:var(--tab-border-color);border-width:var(--tab-border,1px) var(--tab-border,1px) 0 var(--tab-border,1px);padding-inline-end:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-bottom:var(--tab-border,1px);padding-inline-start:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-top:0}.tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]):before,.tabs-lifted>.tab:is(input:checked):before{background-position:0 0,100% 0;background-repeat:no-repeat;background-size:var(--tab-radius,.5rem);bottom:0;content:"";display:block;height:var(--tab-radius,.5rem);position:absolute;width:calc(100% + var(--tab-radius, .5rem)*2);z-index:1;--tab-grad:calc(69% - var(--tab-border, 1px));--radius-start:radial-gradient(circle at top left,transparent var(--tab-grad),var(--tab-border-color) calc(var(--tab-grad) + 0.25px),var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)),var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px));--radius-end:radial-gradient(circle at top right,transparent var(--tab-grad),var(--tab-border-color) calc(var(--tab-grad) + 0.25px),var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)),var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px));background-image:var(--radius-start),var(--radius-end)}.tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]):first-child:before,.tabs-lifted>.tab:is(input:checked):first-child:before{background-image:var(--radius-end);background-position:100% 0}[dir=rtl] .tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]):first-child:before,[dir=rtl] .tabs-lifted>.tab:is(input:checked):first-child:before{background-image:var(--radius-start);background-position:0 0}.tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]):last-child:before,.tabs-lifted>.tab:is(input:checked):last-child:before{background-image:var(--radius-start);background-position:0 0}[dir=rtl] .tabs-lifted>.tab.tab-active:not(.tab-disabled):not([disabled]):last-child:before,[dir=rtl] .tabs-lifted>.tab:is(input:checked):last-child:before{background-image:var(--radius-end);background-position:100% 0}.tabs-lifted>.tab-active:not(.tab-disabled):not([disabled])+.tabs-lifted .tab-active:not(.tab-disabled):not([disabled]):before,.tabs-lifted>.tab:is(input:checked)+.tabs-lifted .tab:is(input:checked):before{background-image:var(--radius-end);background-position:100% 0}.tabs-boxed{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));padding:.25rem}.tabs-boxed,.tabs-boxed .tab{border-radius:var(--rounded-btn,.5rem)}.tabs-boxed .tab-active:not(.tab-disabled):not([disabled]),.tabs-boxed :is(input:checked){--tw-bg-opacity:1;background-color:var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));--tw-text-opacity:1;color:var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)))}:is([dir=rtl] .table){text-align:right}.table :where(th,td){padding:.75rem 1rem;vertical-align:middle}.table tr.active,.table tr.active:nth-child(2n),.table-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)))}.table-zebra tr.active,.table-zebra tr.active:nth-child(2n),.table-zebra-zebra tbody tr:nth-child(2n){--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}.table :where(thead,tbody) :where(tr:first-child:last-child),.table :where(thead,tbody) :where(tr:not(:last-child)){border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)))}.table :where(thead,tfoot){color:var(--fallback-bc,oklch(var(--bc)/.6));font-size:.75rem;font-weight:700;line-height:1rem;white-space:nowrap}.timeline hr{height:.25rem}:where(.timeline hr){--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)))}:where(.timeline:has(.timeline-middle) hr):first-child{border-end-end-radius:var(--rounded-badge,1.9rem);border-end-start-radius:0;border-start-end-radius:var(--rounded-badge,1.9rem);border-start-start-radius:0}:where(.timeline:has(.timeline-middle) hr):last-child{border-end-end-radius:0;border-end-start-radius:var(--rounded-badge,1.9rem);border-start-end-radius:0;border-start-start-radius:var(--rounded-badge,1.9rem)}:where(.timeline:not(:has(.timeline-middle)) :first-child hr:last-child){border-end-end-radius:0;border-end-start-radius:var(--rounded-badge,1.9rem);border-start-end-radius:0;border-start-start-radius:var(--rounded-badge,1.9rem)}:where(.timeline:not(:has(.timeline-middle)) :last-child hr:first-child){border-end-end-radius:var(--rounded-badge,1.9rem);border-end-start-radius:0;border-start-end-radius:var(--rounded-badge,1.9rem);border-start-start-radius:0}.timeline-box{border-radius:var(--rounded-box,1rem);border-width:1px;--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));padding:.5rem 1rem;--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}@keyframes toast-pop{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}[dir=rtl] .toggle{--handleoffsetcalculator:calc(var(--handleoffset)*1)}.toggle:focus-visible{outline-color:var(--fallback-bc,oklch(var(--bc)/.2));outline-offset:2px;outline-style:solid;outline-width:2px}.toggle:hover{background-color:currentColor}.toggle:checked,.toggle[aria-checked=true],.toggle[checked=true]{background-image:none;--handleoffsetcalculator:var(--handleoffset);--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}[dir=rtl] .toggle:checked,[dir=rtl] .toggle[aria-checked=true],[dir=rtl] .toggle[checked=true]{--handleoffsetcalculator:calc(var(--handleoffset)*-1)}.toggle:indeterminate{--tw-text-opacity:1;box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}[dir=rtl] .toggle:indeterminate{box-shadow:calc(var(--handleoffset)/2) 0 0 2px var(--tglbg) inset,calc(var(--handleoffset)/-2) 0 0 2px var(--tglbg) inset,0 0 0 2px var(--tglbg) inset}.toggle:disabled{cursor:not-allowed;--tw-border-opacity:1;background-color:transparent;border-color:var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));opacity:.3;--togglehandleborder:0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset,var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset}.glass,.glass.btn-active{-webkit-backdrop-filter:blur(var(--glass-blur,40px));backdrop-filter:blur(var(--glass-blur,40px));background-color:transparent;background-image:linear-gradient(135deg,rgb(255 255 255/var(--glass-opacity,30%)) 0,transparent 100%),linear-gradient(var(--glass-reflex-degree,100deg),rgb(255 255 255/var(--glass-reflex-opacity,10%)) 25%,transparent 25%);border:none;box-shadow:0 0 0 1px rgb(255 255 255/var(--glass-border-opacity,10%)) inset,0 0 0 2px rgb(0 0 0/5%);text-shadow:0 1px rgb(0 0 0/var(--glass-text-shadow-opacity,5%))}@media (hover:hover){.glass.btn-active{-webkit-backdrop-filter:blur(var(--glass-blur,40px));backdrop-filter:blur(var(--glass-blur,40px));background-color:transparent;background-image:linear-gradient(135deg,rgb(255 255 255/var(--glass-opacity,30%)) 0,transparent 100%),linear-gradient(var(--glass-reflex-degree,100deg),rgb(255 255 255/var(--glass-reflex-opacity,10%)) 25%,transparent 25%);border:none;box-shadow:0 0 0 1px rgb(255 255 255/var(--glass-border-opacity,10%)) inset,0 0 0 2px rgb(0 0 0/5%);text-shadow:0 1px rgb(0 0 0/var(--glass-text-shadow-opacity,5%))}}.badge-xs{font-size:.75rem;height:.75rem;line-height:.75rem;padding-left:.313rem;padding-right:.313rem}.badge-sm{font-size:.75rem;height:1rem;line-height:1rem;padding-left:.438rem;padding-right:.438rem}.btm-nav-xs>:where(.active){border-top-width:1px}.btm-nav-sm>:where(.active){border-top-width:2px}.btm-nav-md>:where(.active){border-top-width:2px}.btm-nav-lg>:where(.active){border-top-width:4px}.btn-xs{font-size:.75rem;height:1.5rem;min-height:1.5rem;padding-left:.5rem;padding-right:.5rem}.btn-sm{font-size:.875rem;height:2rem;min-height:2rem;padding-left:.75rem;padding-right:.75rem}.btn-square:where(.btn-xs){height:1.5rem;padding:0;width:1.5rem}.btn-square:where(.btn-sm){height:2rem;padding:0;width:2rem}.btn-circle:where(.btn-xs){border-radius:9999px;height:1.5rem;padding:0;width:1.5rem}.btn-circle:where(.btn-sm){border-radius:9999px;height:2rem;padding:0;width:2rem}[type=checkbox].checkbox-sm{height:1.25rem;width:1.25rem}.indicator :where(.indicator-item){bottom:auto;inset-inline-end:0;inset-inline-start:auto;top:0;--tw-translate-y:-50%;--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .indicator :where(.indicator-item)){--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-start){inset-inline-end:auto;inset-inline-start:0;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .indicator :where(.indicator-item.indicator-start)){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-center){inset-inline-end:50%;inset-inline-start:50%;--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .indicator :where(.indicator-item.indicator-center)){--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-end){inset-inline-end:0;inset-inline-start:auto;--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .indicator :where(.indicator-item.indicator-end)){--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-bottom){bottom:0;top:auto;--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-middle){bottom:50%;top:50%;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.indicator :where(.indicator-item.indicator-top){bottom:auto;top:0;--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.input-xs{font-size:.75rem;height:1.5rem;line-height:1rem;line-height:1.625;padding-left:.5rem;padding-right:.5rem}.input-sm{font-size:.875rem;height:2rem;line-height:2rem;padding-left:.75rem;padding-right:.75rem}.join.join-vertical{flex-direction:column}.join.join-vertical .join-item:first-child:not(:last-child),.join.join-vertical :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:0;border-start-end-radius:inherit;border-start-start-radius:inherit}.join.join-vertical .join-item:last-child:not(:first-child),.join.join-vertical :last-child:not(:first-child) .join-item{border-end-end-radius:inherit;border-end-start-radius:inherit;border-start-end-radius:0;border-start-start-radius:0}.join.join-horizontal{flex-direction:row}.join.join-horizontal .join-item:first-child:not(:last-child),.join.join-horizontal :first-child:not(:last-child) .join-item{border-end-end-radius:0;border-end-start-radius:inherit;border-start-end-radius:0;border-start-start-radius:inherit}.join.join-horizontal .join-item:last-child:not(:first-child),.join.join-horizontal :last-child:not(:first-child) .join-item{border-end-end-radius:inherit;border-end-start-radius:0;border-start-end-radius:inherit;border-start-start-radius:0}.menu-horizontal{display:inline-flex;flex-direction:row}.menu-horizontal>li:not(.menu-title)>details>ul{position:absolute}.select-sm{font-size:.875rem;height:2rem;line-height:2rem;min-height:2rem;padding-left:.75rem;padding-right:2rem}[dir=rtl] .select-sm{padding-left:2rem;padding-right:.75rem}.stats-vertical{grid-auto-flow:row}.steps-horizontal .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));place-items:center;text-align:center}.steps-vertical .step{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(1,minmax(0,1fr))}.tabs-md :where(.tab){font-size:.875rem;height:2rem;line-height:1.25rem;line-height:2;--tab-padding:1rem}.tabs-lg :where(.tab){font-size:1.125rem;height:3rem;line-height:1.75rem;line-height:2;--tab-padding:1.25rem}.tabs-sm :where(.tab){font-size:.875rem;height:1.5rem;line-height:.75rem;--tab-padding:0.75rem}.tabs-xs :where(.tab){font-size:.75rem;height:1.25rem;line-height:.75rem;--tab-padding:0.5rem}.timeline-vertical{flex-direction:column}.timeline-compact .timeline-start,.timeline-horizontal.timeline-compact .timeline-start{align-self:flex-start;grid-column-end:4;grid-column-start:1;grid-row-end:4;grid-row-start:3;justify-self:center;margin:.25rem}.timeline-compact li:has(.timeline-start) .timeline-end,.timeline-horizontal.timeline-compact li:has(.timeline-start) .timeline-end{grid-column-start:none;grid-row-start:auto}.timeline-vertical.timeline-compact>li{--timeline-col-start:0}.timeline-vertical.timeline-compact .timeline-start{align-self:center;grid-column-end:4;grid-column-start:3;grid-row-end:4;grid-row-start:1;justify-self:start}.timeline-vertical.timeline-compact li:has(.timeline-start) .timeline-end{grid-column-start:auto;grid-row-start:none}:where(.timeline-vertical>li){--timeline-row-start:minmax(0,1fr);--timeline-row-end:minmax(0,1fr);justify-items:center}.timeline-vertical>li>hr{height:100%}:where(.timeline-vertical>li>hr):first-child{grid-column-start:2;grid-row-start:1}:where(.timeline-vertical>li>hr):last-child{grid-column-end:auto;grid-column-start:2;grid-row-end:none;grid-row-start:3}.timeline-vertical .timeline-start{align-self:center;grid-column-end:2;grid-column-start:1;grid-row-end:4;grid-row-start:1;justify-self:end}.timeline-vertical .timeline-end{align-self:center;grid-column-end:4;grid-column-start:3;grid-row-end:4;grid-row-start:1;justify-self:start}.timeline-vertical:where(.timeline-snap-icon)>li{--timeline-col-start:minmax(0,1fr);--timeline-row-start:0.5rem}.timeline-horizontal .timeline-start{align-self:flex-end;grid-column-end:4;grid-column-start:1;grid-row-end:2;grid-row-start:1;justify-self:center}.timeline-horizontal .timeline-end{align-self:flex-start;grid-column-end:4;grid-column-start:1;grid-row-end:4;grid-row-start:3;justify-self:center}.timeline-horizontal:where(.timeline-snap-icon)>li,:where(.timeline-snap-icon)>li{--timeline-col-start:0.5rem;--timeline-row-start:minmax(0,1fr)}.tooltip{--tooltip-offset:calc(100% + 1px + var(--tooltip-tail, 0px))}.tooltip:before{content:var(--tw-content);pointer-events:none;position:absolute;z-index:1;--tw-content:attr(data-tip)}.tooltip-top:before,.tooltip:before{bottom:var(--tooltip-offset);left:50%;right:auto;top:auto;transform:translateX(-50%)}.tooltip-bottom:before{bottom:auto;left:50%;right:auto;top:var(--tooltip-offset);transform:translateX(-50%)}.card-compact .card-body{font-size:.875rem;line-height:1.25rem;padding:1rem}.card-compact .card-title{margin-bottom:.25rem}.card-normal .card-body{font-size:1rem;line-height:1.5rem;padding:var(--padding-card,2rem)}.card-normal .card-title{margin-bottom:.75rem}.join.join-vertical>:where(:not(:first-child)){margin-left:0;margin-right:0;margin-top:-1px}.join.join-horizontal>:where(:not(:first-child)){margin-bottom:0;margin-top:0;margin-inline-start:-1px}.menu-horizontal>li:not(.menu-title)>details>ul{margin-inline-start:0;margin-top:1rem;padding-bottom:.5rem;padding-inline-end:.5rem;padding-top:.5rem}.menu-horizontal>li>details>ul:before{content:none}:where(.menu-horizontal>li:not(.menu-title)>details>ul){border-radius:var(--rounded-box,1rem);--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.menu-sm :where(li:not(.menu-title)>:not(ul,details,.menu-title)),.menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--rounded-btn,.5rem);font-size:.875rem;line-height:1.25rem;padding:.25rem .75rem}.menu-sm .menu-title{padding:.5rem .75rem}.modal-top :where(.modal-box){max-width:none;width:100%;--tw-translate-y:-2.5rem;--tw-scale-x:1;--tw-scale-y:1;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:0;border-top-right-radius:0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-middle :where(.modal-box){max-width:32rem;width:91.666667%;--tw-translate-y:0px;--tw-scale-x:.9;--tw-scale-y:.9;border-bottom-left-radius:var(--rounded-box,1rem);border-bottom-right-radius:var(--rounded-box,1rem);border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-bottom :where(.modal-box){max-width:none;width:100%;--tw-translate-y:2.5rem;--tw-scale-x:1;--tw-scale-y:1;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--rounded-box,1rem);border-top-right-radius:var(--rounded-box,1rem);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.stats-vertical>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0;--tw-divide-y-reverse:0;border-width:calc(1px*(1 - var(--tw-divide-y-reverse))) calc(0px*var(--tw-divide-x-reverse)) calc(1px*var(--tw-divide-y-reverse)) calc(0px*(1 - var(--tw-divide-x-reverse)))}.stats-vertical{overflow-y:auto}.steps-horizontal .step{grid-template-columns:auto;grid-template-rows:40px 1fr;min-width:4rem}.steps-horizontal .step:before{height:.5rem;width:100%;--tw-translate-x:0px;--tw-translate-y:0px;content:"";margin-inline-start:-100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .steps-horizontal .step):before{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.steps-vertical .step{gap:.5rem;grid-template-columns:40px 1fr;grid-template-rows:auto;justify-items:start;min-height:4rem}.steps-vertical .step:before{height:100%;width:.5rem;--tw-translate-x:-50%;--tw-translate-y:-50%;margin-inline-start:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir=rtl] .steps-vertical .step):before{--tw-translate-x:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.timeline-vertical>li>hr{width:.25rem}:where(.timeline-vertical:has(.timeline-middle)>li>hr):first-child{border-bottom-left-radius:var(--rounded-badge,1.9rem);border-bottom-right-radius:var(--rounded-badge,1.9rem);border-top-left-radius:0;border-top-right-radius:0}:where(.timeline-vertical:has(.timeline-middle)>li>hr):last-child{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--rounded-badge,1.9rem);border-top-right-radius:var(--rounded-badge,1.9rem)}:where(.timeline-vertical:not(:has(.timeline-middle)) :first-child>hr:last-child){border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--rounded-badge,1.9rem);border-top-right-radius:var(--rounded-badge,1.9rem)}:where(.timeline-vertical:not(:has(.timeline-middle)) :last-child>hr:first-child){border-bottom-left-radius:var(--rounded-badge,1.9rem);border-bottom-right-radius:var(--rounded-badge,1.9rem);border-top-left-radius:0;border-top-right-radius:0}:where(.timeline-horizontal:has(.timeline-middle)>li>hr):first-child{border-end-end-radius:var(--rounded-badge,1.9rem);border-end-start-radius:0;border-start-end-radius:var(--rounded-badge,1.9rem);border-start-start-radius:0}:where(.timeline-horizontal:has(.timeline-middle)>li>hr):last-child{border-end-end-radius:0;border-end-start-radius:var(--rounded-badge,1.9rem);border-start-end-radius:0;border-start-start-radius:var(--rounded-badge,1.9rem)}.tooltip{display:inline-block;position:relative;text-align:center;--tooltip-tail:0.1875rem;--tooltip-color:var(--fallback-n,oklch(var(--n)/1));--tooltip-text-color:var(--fallback-nc,oklch(var(--nc)/1));--tooltip-tail-offset:calc(100% + 0.0625rem - var(--tooltip-tail))}.tooltip:after,.tooltip:before{opacity:0;transition-delay:.1s;transition-duration:.2s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tooltip:after{border-style:solid;border-width:var(--tooltip-tail,0);content:"";display:block;height:0;position:absolute;width:0}.tooltip:before{background-color:var(--tooltip-color);border-radius:.25rem;color:var(--tooltip-text-color);font-size:.875rem;line-height:1.25rem;max-width:20rem;padding:.25rem .5rem;width:-moz-max-content;width:max-content}.tooltip.tooltip-open:after,.tooltip.tooltip-open:before,.tooltip:hover:after,.tooltip:hover:before{opacity:1;transition-delay:75ms}.tooltip:has(:focus-visible):after,.tooltip:has(:focus-visible):before{opacity:1;transition-delay:75ms}.tooltip:not([data-tip]):hover:after,.tooltip:not([data-tip]):hover:before{opacity:0;visibility:hidden}.tooltip-top:after,.tooltip:after{border-color:var(--tooltip-color) transparent transparent transparent;bottom:var(--tooltip-tail-offset);left:50%;right:auto;top:auto;transform:translateX(-50%)}.tooltip-bottom:after{border-color:transparent transparent var(--tooltip-color) transparent;bottom:auto;left:50%;right:auto;top:var(--tooltip-tail-offset);transform:translateX(-50%)}.fade-out{opacity:0;transition:opacity .15s ease-in-out}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.left-2{left:.5rem}.right-0{right:0}.right-5{right:1.25rem}.top-0{top:0}.top-2{top:.5rem}.top-5{top:1.25rem}.z-0{z-index:0}.z-10{z-index:10}.z-50{z-index:50}.z-\[1\]{z-index:1}.z-\[5000\]{z-index:5000}.z-\[6000\]{z-index:6000}.m-0{margin:0}.m-2{margin:.5rem}.m-5{margin:1.25rem}.m-auto{margin:auto}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-10{margin-bottom:2.5rem;margin-top:2.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-3{margin-bottom:.75rem;margin-top:.75rem}.my-4{margin-bottom:1rem;margin-top:1rem}.my-5{margin-bottom:1.25rem;margin-top:1.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-96{height:24rem}.h-\[250px\]{height:250px}.h-\[25rem\]{height:25rem}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.max-h-96{max-height:24rem}.min-h-80{min-height:20rem}.min-h-screen{min-height:100vh}.w-1\/2{width:50%}.w-10\/12{width:83.333333%}.w-4{width:1rem}.w-4\/12{width:33.333333%}.w-5{width:1.25rem}.w-52{width:13rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-80{width:20rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.min-w-52{min-width:13rem}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-5xl{max-width:64rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.translate-x-full{--tw-translate-x:100%}.transform,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-base-300>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-divide-opacity,1)))}.justify-self-end{justify-self:end}.justify-self-center{justify-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;white-space:nowrap}.text-ellipsis,.truncate{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-box{border-radius:var(--rounded-box,1rem)}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-t-none{border-top-left-radius:0;border-top-right-radius:0}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-dashed{border-style:dashed}.border-base-300{--tw-border-opacity:1;border-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity,1)))}.border-blue-300{--tw-border-opacity:1;border-color:rgb(147 197 253/var(--tw-border-opacity,1))}.border-error{--tw-border-opacity:1;border-color:var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity,1)))}.border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity,1))}.border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.border-sky-500{--tw-border-opacity:1;border-color:rgb(14 165 233/var(--tw-border-opacity,1))}.border-opacity-30{--tw-border-opacity:0.3}.bg-base-100{--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity,1)))}.bg-base-200{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity,1)))}.bg-base-300{--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity,1)))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-blue-900{--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity,1))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-neutral{--tw-bg-opacity:1;background-color:var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity,1)))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-secondary-content{--tw-bg-opacity:1;background-color:var(--fallback-sc,oklch(var(--sc)/var(--tw-bg-opacity,1)))}.stroke-current{stroke:currentColor}.stroke-info{stroke:var(--fallback-in,oklch(var(--in)/1))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-20{padding-bottom:5rem;padding-top:5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.py-5{padding-bottom:1.25rem;padding-top:1.25rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.pl-4{padding-left:1rem}.pl-6{padding-left:1.5rem}.pr-10{padding-right:2.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.normal-case{text-transform:none}.italic{font-style:italic}.text-accent{--tw-text-opacity:1;color:var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity,1)))}.text-accent-content{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity,1)))}.text-base-content{--tw-text-opacity:1;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity,1)))}.text-base-content\/60{color:var(--fallback-bc,oklch(var(--bc)/.6))}.text-base-content\/70{color:var(--fallback-bc,oklch(var(--bc)/.7))}.text-base-content\/80{color:var(--fallback-bc,oklch(var(--bc)/.8))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-neutral-content{--tw-text-opacity:1;color:var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity,1)))}.text-primary{--tw-text-opacity:1;color:var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity,1)))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.text-secondary{--tw-text-opacity:1;color:var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity,1)))}.text-success{--tw-text-opacity:1;color:var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity,1)))}.text-warning{--tw-text-opacity:1;color:var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity,1)))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.decoration-dotted{text-decoration-style:dotted}.placeholder-base-content\/70::-moz-placeholder{color:var(--fallback-bc,oklch(var(--bc)/.7))}.placeholder-base-content\/70::placeholder{color:var(--fallback-bc,oklch(var(--bc)/.7))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-sm,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.grayscale{--tw-grayscale:grayscale(100%)}.filter,.grayscale{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@tailwind daisyui;.leaflet-right-panel{background:#fff;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.3);margin-right:10px;margin-top:80px;transform:none;transition:right .3s ease-in-out;z-index:400}.leaflet-right-panel.controls-shifted{right:310px}.leaflet-control-button{background-color:#fff!important;color:#374151!important}.leaflet-control-button:hover{background-color:#f3f4f6!important}.leaflet-drawer{background:hsla(0,0%,100%,.5);box-shadow:-2px 0 5px rgba(0,0,0,.1);height:100%;position:absolute;right:0;top:0;transform:translateX(100%);transition:transform .3s ease-in-out;width:338px;z-index:450}.leaflet-drawer.open{transform:translateX(0)}.leaflet-control-button,.leaflet-control-layers,.toggle-panel-button{transition:right .3s ease-in-out;z-index:500}.controls-shifted{right:338px!important}.leaflet-control-custom{align-items:center;background-color:#fff;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.3);cursor:pointer;display:flex;height:30px;justify-content:center;width:30px}.leaflet-control-custom:hover{background-color:#f3f4f6}#selection-tool-button.active{background-color:#60a5fa;color:#fff}#cancel-selection-button{margin-bottom:1rem;width:100%}@media (hover:hover){.hover\:btn-ghost:hover:hover{border-color:transparent}@supports (color:oklch(0 0 0)){.hover\:btn-ghost:hover:hover{background-color:var(--fallback-bc,oklch(var(--bc)/.2))}}.hover\:btn-info:hover.btn-outline:hover{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}@supports (color:color-mix(in oklab,black,black)){.hover\:btn-info:hover.btn-outline:hover{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}}}@supports not (color:oklch(0 0 0)){.hover\:btn-info:hover{--btn-color:var(--fallback-in)}}@supports (color:color-mix(in oklab,black,black)){.hover\:btn-info:hover.btn-outline.btn-active{background-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000);border-color:color-mix(in oklab,var(--fallback-in,oklch(var(--in)/1)) 90%,#000)}}@supports (color:oklch(0 0 0)){.hover\:btn-info:hover{--btn-color:var(--in)}}.hover\:btn-info:hover{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));outline-color:var(--fallback-in,oklch(var(--in)/1))}.hover\:btn-ghost:hover{background-color:transparent;border-color:transparent;border-width:1px;color:currentColor;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline-color:currentColor}.hover\:btn-ghost:hover.btn-active{background-color:var(--fallback-bc,oklch(var(--bc)/.2));border-color:transparent}.hover\:btn-info:hover.btn-outline{--tw-text-opacity:1;color:var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)))}.hover\:btn-info:hover.btn-outline.btn-active{--tw-text-opacity:1;color:var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)))}.hover\:input-primary:hover{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)))}.hover\:input-primary:hover:focus,.hover\:input-primary:hover:focus-within{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity)));outline-color:var(--fallback-p,oklch(var(--p)/1))}.focus\:input-ghost:focus{--tw-bg-opacity:0.05}.focus\:input-ghost:focus:focus,.focus\:input-ghost:focus:focus-within{--tw-bg-opacity:1;--tw-text-opacity:1;box-shadow:none;color:var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)))}@media not all and (min-width:768px){.max-md\:timeline-compact,.max-md\:timeline-compact -.timeline-horizontal{--timeline-row-start:0}.max-md\:timeline-compact .timeline-horizontal .timeline-start,.max-md\:timeline-compact .timeline-start{align-self:flex-start;grid-column-end:4;grid-column-start:1;grid-row-end:4;grid-row-start:3;justify-self:center;margin:.25rem}.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact li:has(.timeline-start) .timeline-end{grid-column-start:none;grid-row-start:auto}.max-md\:timeline-compact.timeline-vertical>li{--timeline-col-start:0}.max-md\:timeline-compact.timeline-vertical .timeline-start{align-self:center;grid-column-end:4;grid-column-start:3;grid-row-end:4;grid-row-start:1;justify-self:start}.max-md\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end{grid-column-start:auto;grid-row-start:none}}@media (min-width:1024px){.lg\:stats-horizontal{grid-auto-flow:column}.lg\:stats-horizontal>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0;--tw-divide-y-reverse:0;border-width:calc(0px*(1 - var(--tw-divide-y-reverse))) calc(1px*var(--tw-divide-x-reverse)) calc(0px*var(--tw-divide-y-reverse)) calc(1px*(1 - var(--tw-divide-x-reverse)))}.lg\:stats-horizontal{overflow-x:auto}:is([dir=rtl] .lg\:stats-horizontal){--tw-divide-x-reverse:1}}.last\:border-0:last-child{border-width:0}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:cursor-pointer:hover{cursor:pointer}.hover\:bg-accent:hover{--tw-bg-opacity:1;background-color:var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity,1)))}.hover\:bg-base-200:hover{--tw-bg-opacity:1;background-color:var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity,1)))}.hover\:bg-base-300:hover{--tw-bg-opacity:1;background-color:var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity,1)))}.hover\:text-accent-content:hover{--tw-text-opacity:1;color:var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity,1)))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:shadow-2xl:hover{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.hover\:shadow-2xl:hover,.hover\:shadow-lg:hover{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.hover\:shadow-blue-500\/50:hover{--tw-shadow-color:rgba(59,130,246,.5);--tw-shadow:var(--tw-shadow-colored)}.focus\:border-primary:focus{--tw-border-opacity:1;border-color:var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity,1)))}.focus\:bg-base-100:focus{--tw-bg-opacity:1;background-color:var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity,1)))}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:inline{display:inline}.sm\:w-1\/12{width:8.333333%}.sm\:w-2\/12{width:16.666667%}.sm\:w-6\/12{width:50%}.sm\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-end{align-items:flex-end}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}}@media (min-width:768px){.md\:h-64{height:16rem}.md\:min-h-64{min-height:16rem}.md\:w-1\/12{width:8.333333%}.md\:w-2\/12{width:16.666667%}.md\:w-2\/3{width:66.666667%}.md\:w-3\/12{width:25%}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.md\:text-end{text-align:end}}@media (min-width:1024px){.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-1\/12{width:8.333333%}.lg\:w-1\/2{width:50%}.lg\:w-2\/12{width:16.666667%}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:flex-row-reverse{flex-direction:row-reverse}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.lg\:text-left{text-align:left}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}} \ No newline at end of file +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +/* +! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: Inter var, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden]:where(:not([hidden="until-found"])) { + display: none; +} + +:root, +[data-theme] { + background-color: var(--fallback-b1,oklch(var(--b1)/1)); + color: var(--fallback-bc,oklch(var(--bc)/1)); +} + +@supports not (color: oklch(0 0 0)) { + :root { + color-scheme: light; + --fallback-p: #491eff; + --fallback-pc: #d4dbff; + --fallback-s: #ff41c7; + --fallback-sc: #fff9fc; + --fallback-a: #00cfbd; + --fallback-ac: #00100d; + --fallback-n: #2b3440; + --fallback-nc: #d7dde4; + --fallback-b1: #ffffff; + --fallback-b2: #e5e6e6; + --fallback-b3: #e5e6e6; + --fallback-bc: #1f2937; + --fallback-in: #00b3f0; + --fallback-inc: #000000; + --fallback-su: #00ca92; + --fallback-suc: #000000; + --fallback-wa: #ffc22d; + --fallback-wac: #000000; + --fallback-er: #ff6f70; + --fallback-erc: #000000; + } + + @media (prefers-color-scheme: dark) { + :root { + color-scheme: dark; + --fallback-p: #7582ff; + --fallback-pc: #050617; + --fallback-s: #ff71cf; + --fallback-sc: #190211; + --fallback-a: #00c7b5; + --fallback-ac: #000e0c; + --fallback-n: #2a323c; + --fallback-nc: #a6adbb; + --fallback-b1: #1d232a; + --fallback-b2: #191e24; + --fallback-b3: #15191e; + --fallback-bc: #a6adbb; + --fallback-in: #00b3f0; + --fallback-inc: #000000; + --fallback-su: #00ca92; + --fallback-suc: #000000; + --fallback-wa: #ffc22d; + --fallback-wac: #000000; + --fallback-er: #ff6f70; + --fallback-erc: #000000; + } + } +} + +html { + -webkit-tap-highlight-color: transparent; +} + +:root { + color-scheme: light; + --in: 0.7206 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 0.8471 0.199 83.87; + --er: 0.7176 0.221 22.18; + --pc: 0.89824 0.06192 275.75; + --ac: 0.15352 0.0368 183.61; + --inc: 0 0 0; + --suc: 0 0 0; + --wac: 0 0 0; + --erc: 0 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 0.4912 0.3096 275.75; + --s: 0.6971 0.329 342.55; + --sc: 0.9871 0.0106 342.55; + --a: 0.7676 0.184 183.61; + --n: 0.321785 0.02476 255.701624; + --nc: 0.894994 0.011585 252.096176; + --b1: 1 0 0; + --b2: 0.961151 0 0; + --b3: 0.924169 0.00108 197.137559; + --bc: 0.278078 0.029596 256.847952; +} + +@media (prefers-color-scheme: dark) { + :root { + color-scheme: dark; + --in: 0.7206 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 0.8471 0.199 83.87; + --er: 0.7176 0.221 22.18; + --pc: 0.13138 0.0392 275.75; + --sc: 0.1496 0.052 342.55; + --ac: 0.14902 0.0334 183.61; + --inc: 0 0 0; + --suc: 0 0 0; + --wac: 0 0 0; + --erc: 0 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 0.6569 0.196 275.75; + --s: 0.748 0.26 342.55; + --a: 0.7451 0.167 183.61; + --n: 0.313815 0.021108 254.139175; + --nc: 0.746477 0.0216 264.435964; + --b1: 0.253267 0.015896 252.417568; + --b2: 0.232607 0.013807 253.100675; + --b3: 0.211484 0.01165 254.087939; + --bc: 0.746477 0.0216 264.435964; + } +} + +[data-theme=light] { + color-scheme: light; + --in: 0.7206 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 0.8471 0.199 83.87; + --er: 0.7176 0.221 22.18; + --pc: 0.89824 0.06192 275.75; + --ac: 0.15352 0.0368 183.61; + --inc: 0 0 0; + --suc: 0 0 0; + --wac: 0 0 0; + --erc: 0 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 0.4912 0.3096 275.75; + --s: 0.6971 0.329 342.55; + --sc: 0.9871 0.0106 342.55; + --a: 0.7676 0.184 183.61; + --n: 0.321785 0.02476 255.701624; + --nc: 0.894994 0.011585 252.096176; + --b1: 1 0 0; + --b2: 0.961151 0 0; + --b3: 0.924169 0.00108 197.137559; + --bc: 0.278078 0.029596 256.847952; +} + +[data-theme=dark] { + color-scheme: dark; + --in: 0.7206 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 0.8471 0.199 83.87; + --er: 0.7176 0.221 22.18; + --pc: 0.13138 0.0392 275.75; + --sc: 0.1496 0.052 342.55; + --ac: 0.14902 0.0334 183.61; + --inc: 0 0 0; + --suc: 0 0 0; + --wac: 0 0 0; + --erc: 0 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 0.6569 0.196 275.75; + --s: 0.748 0.26 342.55; + --a: 0.7451 0.167 183.61; + --n: 0.313815 0.021108 254.139175; + --nc: 0.746477 0.0216 264.435964; + --b1: 0.253267 0.015896 252.417568; + --b2: 0.232607 0.013807 253.100675; + --b3: 0.211484 0.01165 254.087939; + --bc: 0.746477 0.0216 264.435964; +} + +[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + border-radius: 0px; + padding-top: 0.5rem; + padding-right: 0.75rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + font-size: 1rem; + line-height: 1.5rem; + --tw-shadow: 0 0 #0000; +} + +[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + border-color: #2563eb; +} + +input::-moz-placeholder, textarea::-moz-placeholder { + color: #6b7280; + opacity: 1; +} + +input::placeholder,textarea::placeholder { + color: #6b7280; + opacity: 1; +} + +::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} + +::-webkit-date-and-time-value { + min-height: 1.5em; + text-align: inherit; +} + +::-webkit-datetime-edit { + display: inline-flex; +} + +::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field { + padding-top: 0; + padding-bottom: 0; +} + +select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; +} + +[multiple],[size]:where(select:not([size="1"])) { + background-image: initial; + background-position: initial; + background-repeat: unset; + background-size: initial; + padding-right: 0.75rem; + -webkit-print-color-adjust: unset; + print-color-adjust: unset; +} + +[type='checkbox'],[type='radio'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + display: inline-block; + vertical-align: middle; + background-origin: border-box; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-shrink: 0; + height: 1rem; + width: 1rem; + color: #2563eb; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + --tw-shadow: 0 0 #0000; +} + +[type='checkbox'] { + border-radius: 0px; +} + +[type='radio'] { + border-radius: 100%; +} + +[type='checkbox']:focus,[type='radio']:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 2px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); +} + +[type='checkbox']:checked,[type='radio']:checked { + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +@media (forced-colors: active) { + [type='checkbox']:checked { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} + +[type='radio']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); +} + +@media (forced-colors: active) { + [type='radio']:checked { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} + +[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +@media (forced-colors: active) { + [type='checkbox']:indeterminate { + -webkit-appearance: auto; + -moz-appearance: auto; + appearance: auto; + } +} + +[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='file'] { + background: unset; + border-color: inherit; + border-width: 0; + border-radius: 0; + padding: 0; + font-size: unset; + line-height: inherit; +} + +[type='file']:focus { + outline: 1px solid ButtonText; + outline: 1px auto -webkit-focus-ring-color; +} + +.\!container { + width: 100% !important; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .\!container { + max-width: 640px !important; + } + + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .\!container { + max-width: 768px !important; + } + + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .\!container { + max-width: 1024px !important; + } + + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .\!container { + max-width: 1280px !important; + } + + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .\!container { + max-width: 1536px !important; + } + + .container { + max-width: 1536px; + } +} + +.alert { + display: grid; + width: 100%; + grid-auto-flow: row; + align-content: flex-start; + align-items: center; + justify-items: center; + gap: 1rem; + text-align: center; + border-radius: var(--rounded-box, 1rem); + border-width: 1px; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + padding: 1rem; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --alert-bg: var(--fallback-b2,oklch(var(--b2)/1)); + --alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1)); + background-color: var(--alert-bg); +} + +@media (min-width: 640px) { + .alert { + grid-auto-flow: column; + grid-template-columns: auto minmax(auto,1fr); + justify-items: start; + text-align: start; + } +} + +.avatar.placeholder > div { + display: flex; + align-items: center; + justify-content: center; +} + +.badge { + display: inline-flex; + align-items: center; + justify-content: center; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; + height: 1.25rem; + font-size: 0.875rem; + line-height: 1.25rem; + width: -moz-fit-content; + width: fit-content; + padding-left: 0.563rem; + padding-right: 0.563rem; + border-radius: var(--rounded-badge, 1.9rem); + border-width: 1px; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +@media (hover:hover) { + .label a:hover { + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + } + + .menu li > *:not(ul, .menu-title, details, .btn):active, +.menu li > *:not(ul, .menu-title, details, .btn).active, +.menu li > details > summary:active { + --tw-bg-opacity: 1; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); + } + + .radio-primary:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + } + + .tab:hover { + --tw-text-opacity: 1; + } + + .tabs-boxed .tab-active:not(.tab-disabled):not([disabled]):hover, + .tabs-boxed :is(input:checked):hover { + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); + } + + .table tr.hover:hover, + .table tr.hover:nth-child(even):hover { + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + } + + .table-zebra tr.hover:hover, + .table-zebra tr.hover:nth-child(even):hover { + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); + } +} + +.btn { + display: inline-flex; + height: 3rem; + min-height: 3rem; + flex-shrink: 0; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + border-radius: var(--rounded-btn, 0.5rem); + border-color: transparent; + border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity)); + padding-left: 1rem; + padding-right: 1rem; + text-align: center; + font-size: 0.875rem; + line-height: 1em; + gap: 0.5rem; + font-weight: 600; + text-decoration-line: none; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + border-width: var(--border-btn, 1px); + animation: button-pop var(--animation-btn, 0.25s) ease-out; + transition-property: color, background-color, border-color, opacity, box-shadow, transform; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); + background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + --tw-border-opacity: 1; +} + +.btn-disabled, + .btn[disabled], + .btn:disabled { + pointer-events: none; +} + +:where(.btn:is(input[type="checkbox"])), +:where(.btn:is(input[type="radio"])) { + width: auto; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.btn:is(input[type="checkbox"]):after, +.btn:is(input[type="radio"]):after { + --tw-content: attr(aria-label); + content: var(--tw-content); +} + +.card { + position: relative; + display: flex; + flex-direction: column; + border-radius: var(--rounded-box, 1rem); +} + +.card:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.card-body { + display: flex; + flex: 1 1 auto; + flex-direction: column; + padding: var(--padding-card, 2rem); + gap: 0.5rem; +} + +.card-body :where(p) { + flex-grow: 1; +} + +.card-actions { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + gap: 0.5rem; +} + +.card figure { + display: flex; + align-items: center; + justify-content: center; +} + +.card.image-full { + display: grid; +} + +.card.image-full:before { + position: relative; + content: ""; + z-index: 10; + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + opacity: 0.75; +} + +.card.image-full:before, + .card.image-full > * { + grid-column-start: 1; + grid-row-start: 1; +} + +.card.image-full > figure img { + height: 100%; + -o-object-fit: cover; + object-fit: cover; +} + +.card.image-full > .card-body { + position: relative; + z-index: 20; + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); +} + +.checkbox { + flex-shrink: 0; + --chkbg: var(--fallback-bc,oklch(var(--bc)/1)); + --chkfg: var(--fallback-b1,oklch(var(--b1)/1)); + height: 1.5rem; + width: 1.5rem; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.2; +} + +.divider { + display: flex; + flex-direction: row; + align-items: center; + align-self: stretch; + margin-top: 1rem; + margin-bottom: 1rem; + height: 1rem; + white-space: nowrap; +} + +.divider:before, + .divider:after { + height: 0.125rem; + width: 100%; + flex-grow: 1; + --tw-content: ''; + content: var(--tw-content); + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); +} + +.\!drawer { + position: relative !important; + display: grid !important; + grid-auto-columns: max-content auto !important; + width: 100% !important; +} + +.drawer { + position: relative; + display: grid; + grid-auto-columns: max-content auto; + width: 100%; +} + +.dropdown { + position: relative; + display: inline-block; +} + +.dropdown > *:not(summary):focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.dropdown .dropdown-content { + position: absolute; +} + +.dropdown:is(:not(details)) .dropdown-content { + visibility: hidden; + opacity: 0; + transform-origin: top; + --tw-scale-x: .95; + --tw-scale-y: .95; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; +} + +.dropdown-end .dropdown-content { + inset-inline-end: 0px; +} + +.dropdown-left .dropdown-content { + bottom: auto; + inset-inline-end: 100%; + top: 0px; + transform-origin: right; +} + +.dropdown-right .dropdown-content { + bottom: auto; + inset-inline-start: 100%; + top: 0px; + transform-origin: left; +} + +.dropdown-bottom .dropdown-content { + bottom: auto; + top: 100%; + transform-origin: top; +} + +.dropdown-top .dropdown-content { + bottom: 100%; + top: auto; + transform-origin: bottom; +} + +.dropdown-end.dropdown-right .dropdown-content { + bottom: 0px; + top: auto; +} + +.dropdown-end.dropdown-left .dropdown-content { + bottom: 0px; + top: auto; +} + +.dropdown.dropdown-open .dropdown-content, +.dropdown:not(.dropdown-hover):focus .dropdown-content, +.dropdown:focus-within .dropdown-content { + visibility: visible; + opacity: 1; +} + +@media (hover: hover) { + .dropdown.dropdown-hover:hover .dropdown-content { + visibility: visible; + opacity: 1; + } + + .btm-nav > *.disabled:hover, + .btm-nav > *[disabled]:hover { + pointer-events: none; + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } + + .btn:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn:hover { + background-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, + black + ); + border-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, + black + ); + } + } + + @supports not (color: oklch(0 0 0)) { + .btn:hover { + background-color: var(--btn-color, var(--fallback-b2)); + border-color: var(--btn-color, var(--fallback-b2)); + } + } + + .btn.glass:hover { + --glass-opacity: 25%; + --glass-border-opacity: 15%; + } + + .btn-ghost:hover { + border-color: transparent; + } + + @supports (color: oklch(0 0 0)) { + .btn-ghost:hover { + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + } + } + + .btn-outline:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity))); + } + + .btn-outline.btn-primary:hover { + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-primary:hover { + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + } + } + + .btn-outline.btn-secondary:hover { + --tw-text-opacity: 1; + color: var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-secondary:hover { + background-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black); + } + } + + .btn-outline.btn-accent:hover { + --tw-text-opacity: 1; + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-accent:hover { + background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); + } + } + + .btn-outline.btn-success:hover { + --tw-text-opacity: 1; + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-success:hover { + background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); + } + } + + .btn-outline.btn-info:hover { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-info:hover { + background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + } + } + + .btn-outline.btn-warning:hover { + --tw-text-opacity: 1; + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-warning:hover { + background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); + } + } + + .btn-outline.btn-error:hover { + --tw-text-opacity: 1; + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn-outline.btn-error:hover { + background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); + } + } + + .btn-disabled:hover, + .btn[disabled]:hover, + .btn:disabled:hover { + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.2; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover { + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + } + } + + .dropdown.dropdown-hover:hover .dropdown-content { + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + + :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover { + cursor: pointer; + outline: 2px solid transparent; + outline-offset: 2px; + } + + @supports (color: oklch(0 0 0)) { + :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover { + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); + } + } + + .tab[disabled], + .tab[disabled]:hover { + cursor: not-allowed; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } +} + +.dropdown:is(details) summary::-webkit-details-marker { + display: none; +} + +.file-input { + height: 3rem; + flex-shrink: 1; + padding-inline-end: 1rem; + font-size: 1rem; + line-height: 2; + line-height: 1.5rem; + overflow: hidden; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.file-input::file-selector-button { + margin-inline-end: 1rem; + display: inline-flex; + height: 100%; + flex-shrink: 0; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + padding-left: 1rem; + padding-right: 1rem; + text-align: center; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 1em; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; + border-style: solid; + --tw-border-opacity: 1; + border-color: var(--fallback-n,oklch(var(--n)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + font-weight: 600; + text-transform: uppercase; + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); + text-decoration-line: none; + border-width: var(--border-btn, 1px); + animation: button-pop var(--animation-btn, 0.25s) ease-out; +} + +.footer { + display: grid; + width: 100%; + grid-auto-flow: row; + place-items: start; + -moz-column-gap: 1rem; + column-gap: 1rem; + row-gap: 2.5rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.footer > * { + display: grid; + place-items: start; + gap: 0.5rem; +} + +@media (min-width: 48rem) { + .footer { + grid-auto-flow: column; + } + + .footer-center { + grid-auto-flow: row dense; + } +} + +.form-control { + display: flex; + flex-direction: column; +} + +.label { + display: flex; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + align-items: center; + justify-content: space-between; + padding-left: 0.25rem; + padding-right: 0.25rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.hero { + display: grid; + width: 100%; + place-items: center; + background-size: cover; + background-position: center; +} + +.hero > * { + grid-column-start: 1; + grid-row-start: 1; +} + +.hero-content { + z-index: 0; + display: flex; + align-items: center; + justify-content: center; + max-width: 80rem; + gap: 1rem; + padding: 1rem; +} + +.indicator { + position: relative; + display: inline-flex; + width: -moz-max-content; + width: max-content; +} + +.indicator :where(.indicator-item) { + z-index: 1; + position: absolute; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + white-space: nowrap; +} + +.input { + flex-shrink: 1; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 3rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 1rem; + line-height: 2; + line-height: 1.5rem; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.input[type="number"]::-webkit-inner-spin-button, +.input-md[type="number"]::-webkit-inner-spin-button { + margin-top: -1rem; + margin-bottom: -1rem; + margin-inline-end: -1rem; +} + +.input-xs[type="number"]::-webkit-inner-spin-button { + margin-top: -0.25rem; + margin-bottom: -0.25rem; + margin-inline-end: -0px; +} + +.input-sm[type="number"]::-webkit-inner-spin-button { + margin-top: 0px; + margin-bottom: 0px; + margin-inline-end: -0px; +} + +.join { + display: inline-flex; + align-items: stretch; + border-radius: var(--rounded-btn, 0.5rem); +} + +.join :where(.join-item) { + border-start-end-radius: 0; + border-end-end-radius: 0; + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join .join-item:not(:first-child):not(:last-child), + .join *:not(:first-child):not(:last-child) .join-item { + border-start-end-radius: 0; + border-end-end-radius: 0; + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join .join-item:first-child:not(:last-child), + .join *:first-child:not(:last-child) .join-item { + border-start-end-radius: 0; + border-end-end-radius: 0; +} + +.join .dropdown .join-item:first-child:not(:last-child), + .join *:first-child:not(:last-child) .dropdown .join-item { + border-start-end-radius: inherit; + border-end-end-radius: inherit; +} + +.join :where(.join-item:first-child:not(:last-child)), + .join :where(*:first-child:not(:last-child) .join-item) { + border-end-start-radius: inherit; + border-start-start-radius: inherit; +} + +.join .join-item:last-child:not(:first-child), + .join *:last-child:not(:first-child) .join-item { + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join :where(.join-item:last-child:not(:first-child)), + .join :where(*:last-child:not(:first-child) .join-item) { + border-start-end-radius: inherit; + border-end-end-radius: inherit; +} + +@supports not selector(:has(*)) { + :where(.join *) { + border-radius: inherit; + } +} + +@supports selector(:has(*)) { + :where(.join *:has(.join-item)) { + border-radius: inherit; + } +} + +.link { + cursor: pointer; + text-decoration-line: underline; +} + +.menu { + display: flex; + flex-direction: column; + flex-wrap: wrap; + font-size: 0.875rem; + line-height: 1.25rem; + padding: 0.5rem; +} + +.menu :where(li ul) { + position: relative; + white-space: nowrap; + margin-inline-start: 1rem; + padding-inline-start: 0.5rem; +} + +.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), .menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) { + display: grid; + grid-auto-flow: column; + align-content: flex-start; + align-items: center; + gap: 0.5rem; + grid-auto-columns: minmax(auto, max-content) auto max-content; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.menu li.disabled { + cursor: not-allowed; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + color: var(--fallback-bc,oklch(var(--bc)/0.3)); +} + +.menu :where(li > .menu-dropdown:not(.menu-dropdown-show)) { + display: none; +} + +:where(.menu li) { + position: relative; + display: flex; + flex-shrink: 0; + flex-direction: column; + flex-wrap: wrap; + align-items: stretch; +} + +:where(.menu li) .badge { + justify-self: end; +} + +.modal { + pointer-events: none; + position: fixed; + inset: 0px; + margin: 0px; + display: grid; + height: 100%; + max-height: none; + width: 100%; + max-width: none; + justify-items: center; + padding: 0px; + opacity: 0; + overscroll-behavior: contain; + z-index: 999; + background-color: transparent; + color: inherit; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-property: transform, opacity, visibility; + overflow-y: hidden; +} + +:where(.modal) { + align-items: center; +} + +.modal-box { + max-height: calc(100vh - 5em); + grid-column-start: 1; + grid-row-start: 1; + width: 91.666667%; + max-width: 32rem; + --tw-scale-x: .9; + --tw-scale-y: .9; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-bottom-right-radius: var(--rounded-box, 1rem); + border-bottom-left-radius: var(--rounded-box, 1rem); + border-top-left-radius: var(--rounded-box, 1rem); + border-top-right-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + padding: 1.5rem; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; + box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -12px; + overflow-y: auto; + overscroll-behavior: contain; +} + +.modal-open, +.modal:target, +.modal-toggle:checked + .modal, +.modal[open] { + pointer-events: auto; + visibility: visible; + opacity: 1; +} + +.modal-action { + display: flex; + margin-top: 1.5rem; + justify-content: flex-end; +} + +.modal-toggle { + position: fixed; + height: 0px; + width: 0px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + opacity: 0; +} + +:root:has(:is(.modal-open, .modal:target, .modal-toggle:checked + .modal, .modal[open])) { + overflow: hidden; +} + +.navbar { + display: flex; + align-items: center; + padding: var(--navbar-padding, 0.5rem); + min-height: 4rem; + width: 100%; +} + +:where(.navbar > *:not(script, style)) { + display: inline-flex; + align-items: center; +} + +.navbar-start { + width: 50%; + justify-content: flex-start; +} + +.navbar-center { + flex-shrink: 0; +} + +.navbar-end { + width: 50%; + justify-content: flex-end; +} + +.progress { + position: relative; + width: 100%; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + overflow: hidden; + height: 0.5rem; + border-radius: var(--rounded-box, 1rem); + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.radio { + flex-shrink: 0; + --chkbg: var(--bc); + height: 1.5rem; + width: 1.5rem; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 9999px; + border-width: 1px; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.2; +} + +.range { + height: 1.5rem; + width: 100%; + cursor: pointer; + -moz-appearance: none; + appearance: none; + -webkit-appearance: none; + --range-shdw: var(--fallback-bc,oklch(var(--bc)/1)); + overflow: hidden; + border-radius: var(--rounded-box, 1rem); + background-color: transparent; +} + +.range:focus { + outline: none; +} + +.select { + display: inline-flex; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 3rem; + min-height: 3rem; + padding-left: 1rem; + padding-right: 2.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), + linear-gradient(135deg, currentColor 50%, transparent 50%); + background-position: calc(100% - 20px) calc(1px + 50%), + calc(100% - 16.1px) calc(1px + 50%); + background-size: 4px 4px, + 4px 4px; + background-repeat: no-repeat; +} + +.select[multiple] { + height: auto; +} + +.stack { + display: inline-grid; + place-items: center; + align-items: flex-end; +} + +.stack > * { + grid-column-start: 1; + grid-row-start: 1; + transform: translateY(10%) scale(0.9); + z-index: 1; + width: 100%; + opacity: 0.6; +} + +.stack > *:nth-child(2) { + transform: translateY(5%) scale(0.95); + z-index: 2; + opacity: 0.8; +} + +.stack > *:nth-child(1) { + transform: translateY(0) scale(1); + z-index: 3; + opacity: 1; +} + +.stats { + display: inline-grid; + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +:where(.stats) { + grid-auto-flow: column; + overflow-x: auto; +} + +.stat { + display: inline-grid; + width: 100%; + grid-template-columns: repeat(1, 1fr); + -moz-column-gap: 1rem; + column-gap: 1rem; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.1; + padding-left: 1.5rem; + padding-right: 1.5rem; + padding-top: 1rem; + padding-bottom: 1rem; +} + +.stat-title { + grid-column-start: 1; + white-space: nowrap; + color: var(--fallback-bc,oklch(var(--bc)/0.6)); +} + +.stat-value { + grid-column-start: 1; + white-space: nowrap; + font-size: 2.25rem; + line-height: 2.5rem; + font-weight: 800; +} + +.stat-desc { + grid-column-start: 1; + white-space: nowrap; + font-size: 0.75rem; + line-height: 1rem; + color: var(--fallback-bc,oklch(var(--bc)/0.6)); +} + +.steps .step { + display: grid; + grid-template-columns: repeat(1, minmax(0, 1fr)); + grid-template-columns: auto; + grid-template-rows: repeat(2, minmax(0, 1fr)); + grid-template-rows: 40px 1fr; + place-items: center; + text-align: center; + min-width: 4rem; +} + +.tabs { + display: grid; + align-items: flex-end; +} + +.tabs-lifted:has(.tab-content[class^="rounded-"]) .tab:first-child:not(.tab-active), + .tabs-lifted:has(.tab-content[class*=" rounded-"]) .tab:first-child:not(.tab-active) { + border-bottom-color: transparent; +} + +.tab { + position: relative; + grid-row-start: 1; + display: inline-flex; + height: 2rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + text-align: center; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + --tab-padding: 1rem; + --tw-text-opacity: 0.5; + --tab-color: var(--fallback-bc,oklch(var(--bc)/1)); + --tab-bg: var(--fallback-b1,oklch(var(--b1)/1)); + --tab-border-color: var(--fallback-b3,oklch(var(--b3)/1)); + color: var(--tab-color); + padding-inline-start: var(--tab-padding, 1rem); + padding-inline-end: var(--tab-padding, 1rem); +} + +.tab:is(input[type="radio"]) { + width: auto; + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +.tab:is(input[type="radio"]):after { + --tw-content: attr(aria-label); + content: var(--tw-content); +} + +.tab:not(input):empty { + cursor: default; + grid-column-start: span 9999; +} + +:checked + .tab-content:nth-child(2), + .tab-active + .tab-content:nth-child(2) { + border-start-start-radius: 0px; +} + +input.tab:checked + .tab-content, +.tab-active + .tab-content { + display: block; +} + +.table { + position: relative; + width: 100%; + border-radius: var(--rounded-box, 1rem); + text-align: left; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.table :where(.table-pin-rows thead tr) { + position: sticky; + top: 0px; + z-index: 1; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.table :where(.table-pin-rows tfoot tr) { + position: sticky; + bottom: 0px; + z-index: 1; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.table :where(.table-pin-cols tr th) { + position: sticky; + left: 0px; + right: 0px; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.timeline { + position: relative; + display: flex; +} + +:where(.timeline > li) { + position: relative; + display: grid; + flex-shrink: 0; + align-items: center; + grid-template-rows: var(--timeline-row-start, minmax(0, 1fr)) auto var( + --timeline-row-end, + minmax(0, 1fr) + ); + grid-template-columns: var(--timeline-col-start, minmax(0, 1fr)) auto var( + --timeline-col-end, + minmax(0, 1fr) + ); +} + +.timeline > li > hr { + width: 100%; + border-width: 0px; +} + +:where(.timeline > li > hr):first-child { + grid-column-start: 1; + grid-row-start: 2; +} + +:where(.timeline > li > hr):last-child { + grid-column-start: 3; + grid-column-end: none; + grid-row-start: 2; + grid-row-end: auto; +} + +.timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 2; + margin: 0.25rem; + align-self: flex-end; + justify-self: center; +} + +.timeline-middle { + grid-column-start: 2; + grid-row-start: 2; +} + +.timeline-end { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; +} + +.toggle { + flex-shrink: 0; + --tglbg: var(--fallback-b1,oklch(var(--b1)/1)); + --handleoffset: 1.5rem; + --handleoffsetcalculator: calc(var(--handleoffset) * -1); + --togglehandleborder: 0 0; + height: 1.5rem; + width: 3rem; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: var(--rounded-badge, 1.9rem); + border-width: 1px; + border-color: currentColor; + background-color: currentColor; + color: var(--fallback-bc,oklch(var(--bc)/0.5)); + transition: background, + box-shadow var(--animation-input, 0.2s) ease-out; + box-shadow: var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset, + var(--togglehandleborder); +} + +.alert-info { + border-color: var(--fallback-in,oklch(var(--in)/0.2)); + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + --alert-bg: var(--fallback-in,oklch(var(--in)/1)); + --alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1)); +} + +.badge-primary { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.badge-secondary { + --tw-border-opacity: 1; + border-color: var(--fallback-s,oklch(var(--s)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-s,oklch(var(--s)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity))); +} + +.badge-success { + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-su,oklch(var(--su)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); +} + +.badge-warning { + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-wa,oklch(var(--wa)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); +} + +.badge-outline { + border-color: currentColor; + --tw-border-opacity: 0.5; + background-color: transparent; + color: currentColor; +} + +.badge-outline.badge-neutral { + --tw-text-opacity: 1; + color: var(--fallback-n,oklch(var(--n)/var(--tw-text-opacity))); +} + +.badge-outline.badge-primary { + --tw-text-opacity: 1; + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); +} + +.badge-outline.badge-secondary { + --tw-text-opacity: 1; + color: var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity))); +} + +.badge-outline.badge-accent { + --tw-text-opacity: 1; + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity))); +} + +.badge-outline.badge-info { + --tw-text-opacity: 1; + color: var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity))); +} + +.badge-outline.badge-success { + --tw-text-opacity: 1; + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity))); +} + +.badge-outline.badge-warning { + --tw-text-opacity: 1; + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity))); +} + +.badge-outline.badge-error { + --tw-text-opacity: 1; + color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); +} + +.btm-nav > *:where(.active) { + border-top-width: 2px; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.btm-nav > *.disabled, + .btm-nav > *[disabled] { + pointer-events: none; + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.btm-nav > * .label { + font-size: 1rem; + line-height: 1.5rem; +} + +.btn:active:hover, + .btn:active:focus { + animation: button-pop 0s ease-out; + transform: scale(var(--btn-focus-scale, 0.97)); +} + +@supports not (color: oklch(0 0 0)) { + .btn { + background-color: var(--btn-color, var(--fallback-b2)); + border-color: var(--btn-color, var(--fallback-b2)); + } + + .btn-primary { + --btn-color: var(--fallback-p); + } + + .btn-neutral { + --btn-color: var(--fallback-n); + } + + .btn-info { + --btn-color: var(--fallback-in); + } + + .btn-success { + --btn-color: var(--fallback-su); + } + + .btn-warning { + --btn-color: var(--fallback-wa); + } + + .btn-error { + --btn-color: var(--fallback-er); + } +} + +@supports (color: color-mix(in oklab, black, black)) { + .btn-active { + background-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b3)) / var(--tw-bg-opacity, 1)) 90%, + black + ); + border-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b3)) / var(--tw-border-opacity, 1)) 90%, + black + ); + } + + .btn-outline.btn-primary.btn-active { + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + } + + .btn-outline.btn-secondary.btn-active { + background-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black); + } + + .btn-outline.btn-accent.btn-active { + background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black); + } + + .btn-outline.btn-success.btn-active { + background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black); + } + + .btn-outline.btn-info.btn-active { + background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + } + + .btn-outline.btn-warning.btn-active { + background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black); + } + + .btn-outline.btn-error.btn-active { + background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black); + } +} + +.btn:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; +} + +.btn-primary { + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +@supports (color: oklch(0 0 0)) { + .btn-primary { + --btn-color: var(--p); + } + + .btn-neutral { + --btn-color: var(--n); + } + + .btn-info { + --btn-color: var(--in); + } + + .btn-success { + --btn-color: var(--su); + } + + .btn-warning { + --btn-color: var(--wa); + } + + .btn-error { + --btn-color: var(--er); + } +} + +.btn-neutral { + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); + outline-color: var(--fallback-n,oklch(var(--n)/1)); +} + +.btn-info { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + outline-color: var(--fallback-in,oklch(var(--in)/1)); +} + +.btn-success { + --tw-text-opacity: 1; + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); + outline-color: var(--fallback-su,oklch(var(--su)/1)); +} + +.btn-warning { + --tw-text-opacity: 1; + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); + outline-color: var(--fallback-wa,oklch(var(--wa)/1)); +} + +.btn-error { + --tw-text-opacity: 1; + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); + outline-color: var(--fallback-er,oklch(var(--er)/1)); +} + +.btn.glass { + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + outline-color: currentColor; +} + +.btn.glass.btn-active { + --glass-opacity: 25%; + --glass-border-opacity: 15%; +} + +.btn-ghost { + border-width: 1px; + border-color: transparent; + background-color: transparent; + color: currentColor; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + outline-color: currentColor; +} + +.btn-ghost.btn-active { + border-color: transparent; + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.btn-link.btn-active { + border-color: transparent; + background-color: transparent; + text-decoration-line: underline; +} + +.btn-outline { + border-color: currentColor; + background-color: transparent; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.btn-outline.btn-active { + --tw-border-opacity: 1; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity))); +} + +.btn-outline.btn-primary { + --tw-text-opacity: 1; + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); +} + +.btn-outline.btn-primary.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.btn-outline.btn-secondary { + --tw-text-opacity: 1; + color: var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity))); +} + +.btn-outline.btn-secondary.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity))); +} + +.btn-outline.btn-accent { + --tw-text-opacity: 1; + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity))); +} + +.btn-outline.btn-accent.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity))); +} + +.btn-outline.btn-success { + --tw-text-opacity: 1; + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity))); +} + +.btn-outline.btn-success.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity))); +} + +.btn-outline.btn-info { + --tw-text-opacity: 1; + color: var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity))); +} + +.btn-outline.btn-info.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); +} + +.btn-outline.btn-warning { + --tw-text-opacity: 1; + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity))); +} + +.btn-outline.btn-warning.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity))); +} + +.btn-outline.btn-error { + --tw-text-opacity: 1; + color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))); +} + +.btn-outline.btn-error.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity))); +} + +.btn.btn-disabled, + .btn[disabled], + .btn:disabled { + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.2; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.btn:is(input[type="checkbox"]:checked), +.btn:is(input[type="radio"]:checked) { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.btn:is(input[type="checkbox"]:checked):focus-visible, .btn:is(input[type="radio"]:checked):focus-visible { + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +@keyframes button-pop { + 0% { + transform: scale(var(--btn-focus-scale, 0.98)); + } + + 40% { + transform: scale(1.02); + } + + 100% { + transform: scale(1); + } +} + +.card :where(figure:first-child) { + overflow: hidden; + border-start-start-radius: inherit; + border-start-end-radius: inherit; + border-end-start-radius: unset; + border-end-end-radius: unset; +} + +.card :where(figure:last-child) { + overflow: hidden; + border-start-start-radius: unset; + border-start-end-radius: unset; + border-end-start-radius: inherit; + border-end-end-radius: inherit; +} + +.card:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; +} + +.card.bordered { + border-width: 1px; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); +} + +.card.compact .card-body { + padding: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.card-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 1.25rem; + line-height: 1.75rem; + font-weight: 600; +} + +.card.image-full :where(figure) { + overflow: hidden; + border-radius: inherit; +} + +.checkbox:focus { + box-shadow: none; +} + +.checkbox:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); +} + +.checkbox:checked, + .checkbox[checked="true"], + .checkbox[aria-checked="true"] { + background-repeat: no-repeat; + animation: checkmark var(--animation-input, 0.2s) ease-out; + background-color: var(--chkbg); + background-image: linear-gradient(-45deg, transparent 65%, var(--chkbg) 65.99%), + linear-gradient(45deg, transparent 75%, var(--chkbg) 75.99%), + linear-gradient(-45deg, var(--chkbg) 40%, transparent 40.99%), + linear-gradient( + 45deg, + var(--chkbg) 30%, + var(--chkfg) 30.99%, + var(--chkfg) 40%, + transparent 40.99% + ), + linear-gradient(-45deg, var(--chkfg) 50%, var(--chkbg) 50.99%); +} + +.checkbox:indeterminate { + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + background-repeat: no-repeat; + animation: checkmark var(--animation-input, 0.2s) ease-out; + background-image: linear-gradient(90deg, transparent 80%, var(--chkbg) 80%), + linear-gradient(-90deg, transparent 80%, var(--chkbg) 80%), + linear-gradient(0deg, var(--chkbg) 43%, var(--chkfg) 43%, var(--chkfg) 57%, var(--chkbg) 57%); +} + +.checkbox:disabled { + cursor: not-allowed; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + opacity: 0.2; +} + +@keyframes checkmark { + 0% { + background-position-y: 5px; + } + + 50% { + background-position-y: -2px; + } + + 100% { + background-position-y: 0; + } +} + +.divider:not(:empty) { + gap: 1rem; +} + +.drawer-toggle:focus-visible ~ .drawer-content label.drawer-button { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; +} + +.dropdown.dropdown-open .dropdown-content, +.dropdown:focus .dropdown-content, +.dropdown:focus-within .dropdown-content { + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.file-input-bordered { + --tw-border-opacity: 0.2; +} + +.file-input:focus { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.file-input-disabled, + .file-input[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + --tw-text-opacity: 0.2; +} + +.file-input-disabled::-moz-placeholder, .file-input[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.file-input-disabled::placeholder, + .file-input[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.file-input-disabled::file-selector-button, .file-input[disabled]::file-selector-button { + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.2; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.footer-title { + margin-bottom: 0.5rem; + font-weight: 700; + text-transform: uppercase; + opacity: 0.6; +} + +.label-text { + font-size: 0.875rem; + line-height: 1.25rem; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +.label-text-alt { + font-size: 0.75rem; + line-height: 1rem; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +.input input { + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + background-color: transparent; +} + +.input input:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.input[list]::-webkit-calendar-picker-indicator { + line-height: 1em; +} + +.input-bordered { + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.input:focus, + .input:focus-within { + box-shadow: none; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.input-ghost { + --tw-bg-opacity: 0.05; +} + +.input-ghost:focus, + .input-ghost:focus-within { + --tw-bg-opacity: 1; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + box-shadow: none; +} + +.input-primary { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); +} + +.input-primary:focus, + .input-primary:focus-within { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +.input-error { + --tw-border-opacity: 1; + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); +} + +.input-error:focus, + .input-error:focus-within { + --tw-border-opacity: 1; + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); + outline-color: var(--fallback-er,oklch(var(--er)/1)); +} + +.input-disabled, + .input:disabled, + .input[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + color: var(--fallback-bc,oklch(var(--bc)/0.4)); +} + +.input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.input-disabled::placeholder, + .input:disabled::placeholder, + .input[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.input::-webkit-date-and-time-value { + text-align: inherit; +} + +.join > :where(*:not(:first-child)) { + margin-top: 0px; + margin-bottom: 0px; + margin-inline-start: -1px; +} + +.join-item:focus { + isolation: isolate; +} + +.link-primary { + --tw-text-opacity: 1; + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); +} + +@supports (color:color-mix(in oklab,black,black)) { + @media (hover:hover) { + .link-primary:hover { + color: color-mix(in oklab,var(--fallback-p,oklch(var(--p)/1)) 80%,black); + } + } +} + +.link:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.link:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; +} + +.loading { + pointer-events: none; + display: inline-block; + aspect-ratio: 1 / 1; + width: 1.5rem; + background-color: currentColor; + -webkit-mask-size: 100%; + mask-size: 100%; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-position: center; + mask-position: center; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E"); +} + +.loading-spinner { + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E"); +} + +.loading-dots { + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_qM83%7Banimation:spinner_8HQG 1.05s infinite%7D.spinner_oXPr%7Banimation-delay:.1s%7D.spinner_ZTLf%7Banimation-delay:.2s%7D@keyframes spinner_8HQG%7B0%25,57.14%25%7Banimation-timing-function:cubic-bezier(0.33,.66,.66,1);transform:translate(0)%7D28.57%25%7Banimation-timing-function:cubic-bezier(0.33,0,.66,.33);transform:translateY(-6px)%7D100%25%7Btransform:translate(0)%7D%7D%3C/style%3E%3Ccircle class='spinner_qM83' cx='4' cy='12' r='3'/%3E%3Ccircle class='spinner_qM83 spinner_oXPr' cx='12' cy='12' r='3'/%3E%3Ccircle class='spinner_qM83 spinner_ZTLf' cx='20' cy='12' r='3'/%3E%3C/svg%3E"); + mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_qM83%7Banimation:spinner_8HQG 1.05s infinite%7D.spinner_oXPr%7Banimation-delay:.1s%7D.spinner_ZTLf%7Banimation-delay:.2s%7D@keyframes spinner_8HQG%7B0%25,57.14%25%7Banimation-timing-function:cubic-bezier(0.33,.66,.66,1);transform:translate(0)%7D28.57%25%7Banimation-timing-function:cubic-bezier(0.33,0,.66,.33);transform:translateY(-6px)%7D100%25%7Btransform:translate(0)%7D%7D%3C/style%3E%3Ccircle class='spinner_qM83' cx='4' cy='12' r='3'/%3E%3Ccircle class='spinner_qM83 spinner_oXPr' cx='12' cy='12' r='3'/%3E%3Ccircle class='spinner_qM83 spinner_ZTLf' cx='20' cy='12' r='3'/%3E%3C/svg%3E"); +} + +.loading-sm { + width: 1.25rem; +} + +.loading-md { + width: 1.5rem; +} + +.loading-lg { + width: 2.5rem; +} + +:where(.menu li:empty) { + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + opacity: 0.1; + margin: 0.5rem 1rem; + height: 1px; +} + +.menu :where(li ul):before { + position: absolute; + bottom: 0.75rem; + inset-inline-start: 0px; + top: 0.75rem; + width: 1px; + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + opacity: 0.1; + content: ""; +} + +.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)), +.menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) { + border-radius: var(--rounded-btn, 0.5rem); + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + text-align: start; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; + text-wrap: balance; +} + +:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus, :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible { + cursor: pointer; + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + outline: 2px solid transparent; + outline-offset: 2px; +} + +.menu li > *:not(ul, .menu-title, details, .btn):active, +.menu li > *:not(ul, .menu-title, details, .btn).active, +.menu li > details > summary:active { + --tw-bg-opacity: 1; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))); +} + +.menu :where(li > details > summary)::-webkit-details-marker { + display: none; +} + +.menu :where(li > details > summary):after, +.menu :where(li > .menu-dropdown-toggle):after { + justify-self: end; + display: block; + margin-top: -0.5rem; + height: 0.5rem; + width: 0.5rem; + transform: rotate(45deg); + transition-property: transform, margin-top; + transition-duration: 0.3s; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + content: ""; + transform-origin: 75% 75%; + box-shadow: 2px 2px; + pointer-events: none; +} + +.menu :where(li > details[open] > summary):after, +.menu :where(li > .menu-dropdown-toggle.menu-dropdown-show):after { + transform: rotate(225deg); + margin-top: 0; +} + +.mockup-phone .display { + overflow: hidden; + border-radius: 40px; + margin-top: -25px; +} + +.mockup-browser .mockup-browser-toolbar .input { + position: relative; + margin-left: auto; + margin-right: auto; + display: block; + height: 1.75rem; + width: 24rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + padding-left: 2rem; + direction: ltr; +} + +.mockup-browser .mockup-browser-toolbar .input:before { + content: ""; + position: absolute; + left: 0.5rem; + top: 50%; + aspect-ratio: 1 / 1; + height: 0.75rem; + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-radius: 9999px; + border-width: 2px; + border-color: currentColor; + opacity: 0.6; +} + +.mockup-browser .mockup-browser-toolbar .input:after { + content: ""; + position: absolute; + left: 1.25rem; + top: 50%; + height: 0.5rem; + --tw-translate-y: 25%; + --tw-rotate: -45deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-radius: 9999px; + border-width: 1px; + border-color: currentColor; + opacity: 0.6; +} + +.modal:not(dialog:not(.modal-open)), + .modal::backdrop { + background-color: #0006; + animation: modal-pop 0.2s ease-out; +} + +.modal-backdrop { + z-index: -1; + grid-column-start: 1; + grid-row-start: 1; + display: grid; + align-self: stretch; + justify-self: stretch; + color: transparent; +} + +.modal-open .modal-box, +.modal-toggle:checked + .modal .modal-box, +.modal:target .modal-box, +.modal[open] .modal-box { + --tw-translate-y: 0px; + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.modal-action > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +@keyframes modal-pop { + 0% { + opacity: 0; + } +} + +.progress::-moz-progress-bar { + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); +} + +.progress-primary::-moz-progress-bar { + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); +} + +.progress:indeterminate { + --progress-color: var(--fallback-bc,oklch(var(--bc)/1)); + background-image: repeating-linear-gradient( + 90deg, + var(--progress-color) -1%, + var(--progress-color) 10%, + transparent 10%, + transparent 90% + ); + background-size: 200%; + background-position-x: 15%; + animation: progress-loading 5s ease-in-out infinite; +} + +.progress-primary:indeterminate { + --progress-color: var(--fallback-p,oklch(var(--p)/1)); +} + +.progress::-webkit-progress-bar { + border-radius: var(--rounded-box, 1rem); + background-color: transparent; +} + +.progress::-webkit-progress-value { + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); +} + +.progress-primary::-webkit-progress-value { + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); +} + +.progress:indeterminate::-moz-progress-bar { + background-color: transparent; + background-image: repeating-linear-gradient( + 90deg, + var(--progress-color) -1%, + var(--progress-color) 10%, + transparent 10%, + transparent 90% + ); + background-size: 200%; + background-position-x: 15%; + animation: progress-loading 5s ease-in-out infinite; +} + +@keyframes progress-loading { + 50% { + background-position-x: -115%; + } +} + +.radio:focus { + box-shadow: none; +} + +.radio:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); +} + +.radio:checked, + .radio[aria-checked="true"] { + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + background-image: none; + animation: radiomark var(--animation-input, 0.2s) ease-out; + box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset; +} + +.radio-primary { + --chkbg: var(--p); + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); +} + +.radio-primary:focus-visible { + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +.radio-primary:checked, + .radio-primary[aria-checked="true"] { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.radio:disabled { + cursor: not-allowed; + opacity: 0.2; +} + +@keyframes radiomark { + 0% { + box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } + + 50% { + box-shadow: 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } + + 100% { + box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } +} + +.range:focus-visible::-webkit-slider-thumb { + --focus-shadow: 0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset, 0 0 0 2rem var(--range-shdw) inset; +} + +.range:focus-visible::-moz-range-thumb { + --focus-shadow: 0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset, 0 0 0 2rem var(--range-shdw) inset; +} + +.range::-webkit-slider-runnable-track { + height: 0.5rem; + width: 100%; + border-radius: var(--rounded-box, 1rem); + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); +} + +.range::-moz-range-track { + height: 0.5rem; + width: 100%; + border-radius: var(--rounded-box, 1rem); + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); +} + +.range::-webkit-slider-thumb { + position: relative; + height: 1.5rem; + width: 1.5rem; + border-radius: var(--rounded-box, 1rem); + border-style: none; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + appearance: none; + -webkit-appearance: none; + top: 50%; + color: var(--range-shdw); + transform: translateY(-50%); + --filler-size: 100rem; + --filler-offset: 0.6rem; + box-shadow: 0 0 0 3px var(--range-shdw) inset, + var(--focus-shadow, 0 0), + calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size); +} + +.range::-moz-range-thumb { + position: relative; + height: 1.5rem; + width: 1.5rem; + border-radius: var(--rounded-box, 1rem); + border-style: none; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + top: 50%; + color: var(--range-shdw); + --filler-size: 100rem; + --filler-offset: 0.5rem; + box-shadow: 0 0 0 3px var(--range-shdw) inset, + var(--focus-shadow, 0 0), + calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size); +} + +@keyframes rating-pop { + 0% { + transform: translateY(-0.125em); + } + + 40% { + transform: translateY(-0.125em); + } + + 100% { + transform: translateY(0); + } +} + +.select-bordered { + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.select:focus { + box-shadow: none; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.select-disabled, + .select:disabled, + .select[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.select-disabled::-moz-placeholder, .select:disabled::-moz-placeholder, .select[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.select-disabled::placeholder, + .select:disabled::placeholder, + .select[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.select-multiple, + .select[multiple], + .select[size].select:not([size="1"]) { + background-image: none; + padding-right: 1rem; +} + +[dir="rtl"] .select { + background-position: calc(0% + 12px) calc(1px + 50%), + calc(0% + 16px) calc(1px + 50%); +} + +@keyframes skeleton { + from { + background-position: 150%; + } + + to { + background-position: -50%; + } +} + +:where(.stats) > :not([hidden]) ~ :not([hidden]) { + --tw-divide-x-reverse: 0; + border-right-width: calc(1px * var(--tw-divide-x-reverse)); + border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); + --tw-divide-y-reverse: 0; + border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(0px * var(--tw-divide-y-reverse)); +} + +:is([dir="rtl"] .stats > :not([hidden]) ~ :not([hidden])) { + --tw-divide-x-reverse: 1; +} + +.steps .step:before { + top: 0px; + grid-column-start: 1; + grid-row-start: 1; + height: 0.5rem; + width: 100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + content: ""; + margin-inline-start: -100%; +} + +.steps .step:after { + content: counter(step); + counter-increment: step; + z-index: 1; + position: relative; + grid-column-start: 1; + grid-row-start: 1; + display: grid; + height: 2rem; + width: 2rem; + place-items: center; + place-self: center; + border-radius: 9999px; + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +.steps .step:first-child:before { + content: none; +} + +.steps .step[data-content]:after { + content: attr(data-content); +} + +.tabs-lifted > .tab:focus-visible { + border-end-end-radius: 0; + border-end-start-radius: 0; +} + +.tab.tab-active:not(.tab-disabled):not([disabled]), + .tab:is(input:checked) { + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 1; + --tw-text-opacity: 1; +} + +.tab:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.tab:focus-visible { + outline: 2px solid currentColor; + outline-offset: -5px; +} + +.tab-disabled, + .tab[disabled] { + cursor: not-allowed; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.tabs-bordered > .tab { + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.2; + border-style: solid; + border-bottom-width: calc(var(--tab-border, 1px) + 1px); +} + +.tabs-lifted > .tab { + border: var(--tab-border, 1px) solid transparent; + border-width: 0 0 var(--tab-border, 1px) 0; + border-start-start-radius: var(--tab-radius, 0.5rem); + border-start-end-radius: var(--tab-radius, 0.5rem); + border-bottom-color: var(--tab-border-color); + padding-inline-start: var(--tab-padding, 1rem); + padding-inline-end: var(--tab-padding, 1rem); + padding-top: var(--tab-border, 1px); +} + +.tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]), + .tabs-lifted > .tab:is(input:checked) { + background-color: var(--tab-bg); + border-width: var(--tab-border, 1px) var(--tab-border, 1px) 0 var(--tab-border, 1px); + border-inline-start-color: var(--tab-border-color); + border-inline-end-color: var(--tab-border-color); + border-top-color: var(--tab-border-color); + padding-inline-start: calc(var(--tab-padding, 1rem) - var(--tab-border, 1px)); + padding-inline-end: calc(var(--tab-padding, 1rem) - var(--tab-border, 1px)); + padding-bottom: var(--tab-border, 1px); + padding-top: 0; +} + +.tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]):before, .tabs-lifted > .tab:is(input:checked):before { + z-index: 1; + content: ""; + display: block; + position: absolute; + width: calc(100% + var(--tab-radius, 0.5rem) * 2); + height: var(--tab-radius, 0.5rem); + bottom: 0; + background-size: var(--tab-radius, 0.5rem); + background-position: top left, + top right; + background-repeat: no-repeat; + --tab-grad: calc(69% - var(--tab-border, 1px)); + --radius-start: radial-gradient( + circle at top left, + transparent var(--tab-grad), + var(--tab-border-color) calc(var(--tab-grad) + 0.25px), + var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)), + var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px) + ); + --radius-end: radial-gradient( + circle at top right, + transparent var(--tab-grad), + var(--tab-border-color) calc(var(--tab-grad) + 0.25px), + var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)), + var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px) + ); + background-image: var(--radius-start), var(--radius-end); +} + +.tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]):first-child:before, .tabs-lifted > .tab:is(input:checked):first-child:before { + background-image: var(--radius-end); + background-position: top right; +} + +[dir="rtl"] .tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]):first-child:before, [dir="rtl"] .tabs-lifted > .tab:is(input:checked):first-child:before { + background-image: var(--radius-start); + background-position: top left; +} + +.tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]):last-child:before, .tabs-lifted > .tab:is(input:checked):last-child:before { + background-image: var(--radius-start); + background-position: top left; +} + +[dir="rtl"] .tabs-lifted > .tab.tab-active:not(.tab-disabled):not([disabled]):last-child:before, [dir="rtl"] .tabs-lifted > .tab:is(input:checked):last-child:before { + background-image: var(--radius-end); + background-position: top right; +} + +.tabs-lifted + > .tab-active:not(.tab-disabled):not([disabled]) + + .tabs-lifted + .tab-active:not(.tab-disabled):not([disabled]):before, .tabs-lifted > .tab:is(input:checked) + .tabs-lifted .tab:is(input:checked):before { + background-image: var(--radius-end); + background-position: top right; +} + +.tabs-boxed { + border-radius: var(--rounded-btn, 0.5rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + padding: 0.25rem; +} + +.tabs-boxed .tab { + border-radius: var(--rounded-btn, 0.5rem); +} + +.tabs-boxed .tab-active:not(.tab-disabled):not([disabled]), + .tabs-boxed :is(input:checked) { + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +:is([dir="rtl"] .table) { + text-align: right; +} + +.table :where(th, td) { + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.75rem; + vertical-align: middle; +} + +.table tr.active, + .table tr.active:nth-child(even), + .table-zebra tbody tr:nth-child(even) { + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); +} + +.table-zebra tr.active, + .table-zebra tr.active:nth-child(even), + .table-zebra-zebra tbody tr:nth-child(even) { + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); +} + +.table :where(thead, tbody) :where(tr:not(:last-child)), + .table :where(thead, tbody) :where(tr:first-child:last-child) { + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-bottom-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); +} + +.table :where(thead, tfoot) { + white-space: nowrap; + font-size: 0.75rem; + line-height: 1rem; + font-weight: 700; + color: var(--fallback-bc,oklch(var(--bc)/0.6)); +} + +.timeline hr { + height: 0.25rem; +} + +:where(.timeline hr) { + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); +} + +:where(.timeline:has(.timeline-middle) hr):first-child { + border-start-end-radius: var(--rounded-badge, 1.9rem); + border-end-end-radius: var(--rounded-badge, 1.9rem); + border-start-start-radius: 0px; + border-end-start-radius: 0px; +} + +:where(.timeline:has(.timeline-middle) hr):last-child { + border-start-start-radius: var(--rounded-badge, 1.9rem); + border-end-start-radius: var(--rounded-badge, 1.9rem); + border-start-end-radius: 0px; + border-end-end-radius: 0px; +} + +:where(.timeline:not(:has(.timeline-middle)) :first-child hr:last-child) { + border-start-start-radius: var(--rounded-badge, 1.9rem); + border-end-start-radius: var(--rounded-badge, 1.9rem); + border-start-end-radius: 0px; + border-end-end-radius: 0px; +} + +:where(.timeline:not(:has(.timeline-middle)) :last-child hr:first-child) { + border-start-end-radius: var(--rounded-badge, 1.9rem); + border-end-end-radius: var(--rounded-badge, 1.9rem); + border-start-start-radius: 0px; + border-end-start-radius: 0px; +} + +.timeline-box { + border-radius: var(--rounded-box, 1rem); + border-width: 1px; + --tw-border-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +@keyframes toast-pop { + 0% { + transform: scale(0.9); + opacity: 0; + } + + 100% { + transform: scale(1); + opacity: 1; + } +} + +[dir="rtl"] .toggle { + --handleoffsetcalculator: calc(var(--handleoffset) * 1); +} + +.toggle:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.toggle:hover { + background-color: currentColor; +} + +.toggle:checked, + .toggle[checked="true"], + .toggle[aria-checked="true"] { + background-image: none; + --handleoffsetcalculator: var(--handleoffset); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +[dir="rtl"] .toggle:checked, [dir="rtl"] .toggle[checked="true"], [dir="rtl"] .toggle[aria-checked="true"] { + --handleoffsetcalculator: calc(var(--handleoffset) * -1); +} + +.toggle:indeterminate { + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset; +} + +[dir="rtl"] .toggle:indeterminate { + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset; +} + +.toggle:disabled { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + background-color: transparent; + opacity: 0.3; + --togglehandleborder: 0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset, + var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset; +} + +.glass, + .glass.btn-active { + border: none; + -webkit-backdrop-filter: blur(var(--glass-blur, 40px)); + backdrop-filter: blur(var(--glass-blur, 40px)); + background-color: transparent; + background-image: linear-gradient( + 135deg, + rgb(255 255 255 / var(--glass-opacity, 30%)) 0%, + rgb(0 0 0 / 0%) 100% + ), + linear-gradient( + var(--glass-reflex-degree, 100deg), + rgb(255 255 255 / var(--glass-reflex-opacity, 10%)) 25%, + rgb(0 0 0 / 0%) 25% + ); + box-shadow: 0 0 0 1px rgb(255 255 255 / var(--glass-border-opacity, 10%)) inset, + 0 0 0 2px rgb(0 0 0 / 5%); + text-shadow: 0 1px rgb(0 0 0 / var(--glass-text-shadow-opacity, 5%)); +} + +@media (hover: hover) { + .glass.btn-active { + border: none; + -webkit-backdrop-filter: blur(var(--glass-blur, 40px)); + backdrop-filter: blur(var(--glass-blur, 40px)); + background-color: transparent; + background-image: linear-gradient( + 135deg, + rgb(255 255 255 / var(--glass-opacity, 30%)) 0%, + rgb(0 0 0 / 0%) 100% + ), + linear-gradient( + var(--glass-reflex-degree, 100deg), + rgb(255 255 255 / var(--glass-reflex-opacity, 10%)) 25%, + rgb(0 0 0 / 0%) 25% + ); + box-shadow: 0 0 0 1px rgb(255 255 255 / var(--glass-border-opacity, 10%)) inset, + 0 0 0 2px rgb(0 0 0 / 5%); + text-shadow: 0 1px rgb(0 0 0 / var(--glass-text-shadow-opacity, 5%)); + } +} + +.badge-xs { + height: 0.75rem; + font-size: 0.75rem; + line-height: .75rem; + padding-left: 0.313rem; + padding-right: 0.313rem; +} + +.badge-sm { + height: 1rem; + font-size: 0.75rem; + line-height: 1rem; + padding-left: 0.438rem; + padding-right: 0.438rem; +} + +.btm-nav-xs > *:where(.active) { + border-top-width: 1px; +} + +.btm-nav-sm > *:where(.active) { + border-top-width: 2px; +} + +.btm-nav-md > *:where(.active) { + border-top-width: 2px; +} + +.btm-nav-lg > *:where(.active) { + border-top-width: 4px; +} + +.btn-xs { + height: 1.5rem; + min-height: 1.5rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + font-size: 0.75rem; +} + +.btn-sm { + height: 2rem; + min-height: 2rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + font-size: 0.875rem; +} + +.btn-square:where(.btn-xs) { + height: 1.5rem; + width: 1.5rem; + padding: 0px; +} + +.btn-square:where(.btn-sm) { + height: 2rem; + width: 2rem; + padding: 0px; +} + +.btn-circle:where(.btn-xs) { + height: 1.5rem; + width: 1.5rem; + border-radius: 9999px; + padding: 0px; +} + +.btn-circle:where(.btn-sm) { + height: 2rem; + width: 2rem; + border-radius: 9999px; + padding: 0px; +} + +[type="checkbox"].checkbox-sm { + height: 1.25rem; + width: 1.25rem; +} + +.indicator :where(.indicator-item) { + bottom: auto; + inset-inline-end: 0px; + inset-inline-start: auto; + top: 0px; + --tw-translate-y: -50%; + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +:is([dir="rtl"] .indicator :where(.indicator-item)) { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-start) { + inset-inline-end: auto; + inset-inline-start: 0px; + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +:is([dir="rtl"] .indicator :where(.indicator-item.indicator-start)) { + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-center) { + inset-inline-end: 50%; + inset-inline-start: 50%; + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +:is([dir="rtl"] .indicator :where(.indicator-item.indicator-center)) { + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-end) { + inset-inline-end: 0px; + inset-inline-start: auto; + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +:is([dir="rtl"] .indicator :where(.indicator-item.indicator-end)) { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-bottom) { + bottom: 0px; + top: auto; + --tw-translate-y: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-middle) { + bottom: 50%; + top: 50%; + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.indicator :where(.indicator-item.indicator-top) { + bottom: auto; + top: 0px; + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.input-xs { + height: 1.5rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + font-size: 0.75rem; + line-height: 1rem; + line-height: 1.625; +} + +.input-sm { + height: 2rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + font-size: 0.875rem; + line-height: 2rem; +} + +.join.join-vertical { + flex-direction: column; +} + +.join.join-vertical .join-item:first-child:not(:last-child), + .join.join-vertical *:first-child:not(:last-child) .join-item { + border-end-start-radius: 0; + border-end-end-radius: 0; + border-start-start-radius: inherit; + border-start-end-radius: inherit; +} + +.join.join-vertical .join-item:last-child:not(:first-child), + .join.join-vertical *:last-child:not(:first-child) .join-item { + border-start-start-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: inherit; + border-end-end-radius: inherit; +} + +.join.join-horizontal { + flex-direction: row; +} + +.join.join-horizontal .join-item:first-child:not(:last-child), + .join.join-horizontal *:first-child:not(:last-child) .join-item { + border-end-end-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: inherit; + border-start-start-radius: inherit; +} + +.join.join-horizontal .join-item:last-child:not(:first-child), + .join.join-horizontal *:last-child:not(:first-child) .join-item { + border-end-start-radius: 0; + border-start-start-radius: 0; + border-end-end-radius: inherit; + border-start-end-radius: inherit; +} + +.menu-horizontal { + display: inline-flex; + flex-direction: row; +} + +.menu-horizontal > li:not(.menu-title) > details > ul { + position: absolute; +} + +.select-sm { + height: 2rem; + min-height: 2rem; + padding-left: 0.75rem; + padding-right: 2rem; + font-size: 0.875rem; + line-height: 2rem; +} + +[dir="rtl"] .select-sm { + padding-left: 2rem; + padding-right: 0.75rem; +} + +.stats-vertical { + grid-auto-flow: row; +} + +.steps-horizontal .step { + display: grid; + grid-template-columns: repeat(1, minmax(0, 1fr)); + grid-template-rows: repeat(2, minmax(0, 1fr)); + place-items: center; + text-align: center; +} + +.steps-vertical .step { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-rows: repeat(1, minmax(0, 1fr)); +} + +.tabs-md :where(.tab) { + height: 2rem; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + --tab-padding: 1rem; +} + +.tabs-lg :where(.tab) { + height: 3rem; + font-size: 1.125rem; + line-height: 1.75rem; + line-height: 2; + --tab-padding: 1.25rem; +} + +.tabs-sm :where(.tab) { + height: 1.5rem; + font-size: 0.875rem; + line-height: .75rem; + --tab-padding: 0.75rem; +} + +.tabs-xs :where(.tab) { + height: 1.25rem; + font-size: 0.75rem; + line-height: .75rem; + --tab-padding: 0.5rem; +} + +.timeline-vertical { + flex-direction: column; +} + +.timeline-compact .timeline-start, .timeline-horizontal.timeline-compact .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; +} + +.timeline-compact li:has(.timeline-start) .timeline-end, .timeline-horizontal.timeline-compact li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; +} + +.timeline-vertical.timeline-compact > li { + --timeline-col-start: 0; +} + +.timeline-vertical.timeline-compact .timeline-start { + grid-column-start: 3; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 4; + align-self: center; + justify-self: start; +} + +.timeline-vertical.timeline-compact li:has(.timeline-start) .timeline-end { + grid-column-start: auto; + grid-row-start: none; +} + +:where(.timeline-vertical > li) { + --timeline-row-start: minmax(0, 1fr); + --timeline-row-end: minmax(0, 1fr); + justify-items: center; +} + +.timeline-vertical > li > hr { + height: 100%; +} + +:where(.timeline-vertical > li > hr):first-child { + grid-column-start: 2; + grid-row-start: 1; +} + +:where(.timeline-vertical > li > hr):last-child { + grid-column-start: 2; + grid-column-end: auto; + grid-row-start: 3; + grid-row-end: none; +} + +.timeline-vertical .timeline-start { + grid-column-start: 1; + grid-column-end: 2; + grid-row-start: 1; + grid-row-end: 4; + align-self: center; + justify-self: end; +} + +.timeline-vertical .timeline-end { + grid-column-start: 3; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 4; + align-self: center; + justify-self: start; +} + +.timeline-vertical:where(.timeline-snap-icon) > li { + --timeline-col-start: minmax(0, 1fr); + --timeline-row-start: 0.5rem; +} + +.timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 2; + align-self: flex-end; + justify-self: center; +} + +.timeline-horizontal .timeline-end { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + align-self: flex-start; + justify-self: center; +} + +:where(.timeline-snap-icon) > li, +.timeline-horizontal:where(.timeline-snap-icon) > li { + --timeline-col-start: 0.5rem; + --timeline-row-start: minmax(0, 1fr); +} + +.tooltip { + position: relative; + display: inline-block; + --tooltip-offset: calc(100% + 1px + var(--tooltip-tail, 0px)); +} + +.tooltip:before { + position: absolute; + pointer-events: none; + z-index: 1; + content: var(--tw-content); + --tw-content: attr(data-tip); +} + +.tooltip:before, .tooltip-top:before { + transform: translateX(-50%); + top: auto; + left: 50%; + right: auto; + bottom: var(--tooltip-offset); +} + +.tooltip-bottom:before { + transform: translateX(-50%); + top: var(--tooltip-offset); + left: 50%; + right: auto; + bottom: auto; +} + +.card-compact .card-body { + padding: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.card-compact .card-title { + margin-bottom: 0.25rem; +} + +.card-normal .card-body { + padding: var(--padding-card, 2rem); + font-size: 1rem; + line-height: 1.5rem; +} + +.card-normal .card-title { + margin-bottom: 0.75rem; +} + +.join.join-vertical > :where(*:not(:first-child)) { + margin-left: 0px; + margin-right: 0px; + margin-top: -1px; +} + +.join.join-horizontal > :where(*:not(:first-child)) { + margin-top: 0px; + margin-bottom: 0px; + margin-inline-start: -1px; +} + +.menu-horizontal > li:not(.menu-title) > details > ul { + margin-inline-start: 0px; + margin-top: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-inline-end: 0.5rem; +} + +.menu-horizontal > li > details > ul:before { + content: none; +} + +:where(.menu-horizontal > li:not(.menu-title) > details > ul) { + border-radius: var(--rounded-box, 1rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.menu-sm :where(li:not(.menu-title) > *:not(ul, details, .menu-title)), .menu-sm :where(li:not(.menu-title) > details > summary:not(.menu-title)) { + border-radius: var(--rounded-btn, 0.5rem); + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.25rem; + padding-bottom: 0.25rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.menu-sm .menu-title { + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.modal-top :where(.modal-box) { + width: 100%; + max-width: none; + --tw-translate-y: -2.5rem; + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-bottom-right-radius: var(--rounded-box, 1rem); + border-bottom-left-radius: var(--rounded-box, 1rem); + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +.modal-middle :where(.modal-box) { + width: 91.666667%; + max-width: 32rem; + --tw-translate-y: 0px; + --tw-scale-x: .9; + --tw-scale-y: .9; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-top-left-radius: var(--rounded-box, 1rem); + border-top-right-radius: var(--rounded-box, 1rem); + border-bottom-right-radius: var(--rounded-box, 1rem); + border-bottom-left-radius: var(--rounded-box, 1rem); +} + +.modal-bottom :where(.modal-box) { + width: 100%; + max-width: none; + --tw-translate-y: 2.5rem; + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + border-top-left-radius: var(--rounded-box, 1rem); + border-top-right-radius: var(--rounded-box, 1rem); + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +.stats-vertical > :not([hidden]) ~ :not([hidden]) { + --tw-divide-x-reverse: 0; + border-right-width: calc(0px * var(--tw-divide-x-reverse)); + border-left-width: calc(0px * calc(1 - var(--tw-divide-x-reverse))); + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.stats-vertical { + overflow-y: auto; +} + +.steps-horizontal .step { + grid-template-rows: 40px 1fr; + grid-template-columns: auto; + min-width: 4rem; +} + +.steps-horizontal .step:before { + height: 0.5rem; + width: 100%; + --tw-translate-x: 0px; + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + content: ""; + margin-inline-start: -100%; +} + +:is([dir="rtl"] .steps-horizontal .step):before { + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.steps-vertical .step { + gap: 0.5rem; + grid-template-columns: 40px 1fr; + grid-template-rows: auto; + min-height: 4rem; + justify-items: start; +} + +.steps-vertical .step:before { + height: 100%; + width: 0.5rem; + --tw-translate-x: -50%; + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + margin-inline-start: 50%; +} + +:is([dir="rtl"] .steps-vertical .step):before { + --tw-translate-x: 50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.timeline-vertical > li > hr { + width: 0.25rem; +} + +:where(.timeline-vertical:has(.timeline-middle) > li > hr):first-child { + border-bottom-right-radius: var(--rounded-badge, 1.9rem); + border-bottom-left-radius: var(--rounded-badge, 1.9rem); + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +:where(.timeline-vertical:has(.timeline-middle) > li > hr):last-child { + border-top-left-radius: var(--rounded-badge, 1.9rem); + border-top-right-radius: var(--rounded-badge, 1.9rem); + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +:where(.timeline-vertical:not(:has(.timeline-middle)) :first-child > hr:last-child) { + border-top-left-radius: var(--rounded-badge, 1.9rem); + border-top-right-radius: var(--rounded-badge, 1.9rem); + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +:where(.timeline-vertical:not(:has(.timeline-middle)) :last-child > hr:first-child) { + border-bottom-right-radius: var(--rounded-badge, 1.9rem); + border-bottom-left-radius: var(--rounded-badge, 1.9rem); + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +:where(.timeline-horizontal:has(.timeline-middle) > li > hr):first-child { + border-start-end-radius: var(--rounded-badge, 1.9rem); + border-end-end-radius: var(--rounded-badge, 1.9rem); + border-start-start-radius: 0px; + border-end-start-radius: 0px; +} + +:where(.timeline-horizontal:has(.timeline-middle) > li > hr):last-child { + border-start-start-radius: var(--rounded-badge, 1.9rem); + border-end-start-radius: var(--rounded-badge, 1.9rem); + border-start-end-radius: 0px; + border-end-end-radius: 0px; +} + +.tooltip { + position: relative; + display: inline-block; + text-align: center; + --tooltip-tail: 0.1875rem; + --tooltip-color: var(--fallback-n,oklch(var(--n)/1)); + --tooltip-text-color: var(--fallback-nc,oklch(var(--nc)/1)); + --tooltip-tail-offset: calc(100% + 0.0625rem - var(--tooltip-tail)); +} + +.tooltip:before, +.tooltip:after { + opacity: 0; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-delay: 100ms; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +.tooltip:after { + position: absolute; + content: ""; + border-style: solid; + border-width: var(--tooltip-tail, 0); + width: 0; + height: 0; + display: block; +} + +.tooltip:before { + max-width: 20rem; + border-radius: 0.25rem; + padding-left: 0.5rem; + padding-right: 0.5rem; + padding-top: 0.25rem; + padding-bottom: 0.25rem; + font-size: 0.875rem; + line-height: 1.25rem; + background-color: var(--tooltip-color); + color: var(--tooltip-text-color); + width: -moz-max-content; + width: max-content; +} + +.tooltip.tooltip-open:before { + opacity: 1; + transition-delay: 75ms; +} + +.tooltip.tooltip-open:after { + opacity: 1; + transition-delay: 75ms; +} + +.tooltip:hover:before { + opacity: 1; + transition-delay: 75ms; +} + +.tooltip:hover:after { + opacity: 1; + transition-delay: 75ms; +} + +.tooltip:has(:focus-visible):after, +.tooltip:has(:focus-visible):before { + opacity: 1; + transition-delay: 75ms; +} + +.tooltip:not([data-tip]):hover:before, +.tooltip:not([data-tip]):hover:after { + visibility: hidden; + opacity: 0; +} + +.tooltip:after, .tooltip-top:after { + transform: translateX(-50%); + border-color: var(--tooltip-color) transparent transparent transparent; + top: auto; + left: 50%; + right: auto; + bottom: var(--tooltip-tail-offset); +} + +.tooltip-bottom:after { + transform: translateX(-50%); + border-color: transparent transparent var(--tooltip-color) transparent; + top: var(--tooltip-tail-offset); + left: 50%; + right: auto; + bottom: auto; +} + +.fade-out { + opacity: 0; + transition: opacity 150ms ease-in-out; +} + +.visible { + visibility: visible; +} + +.invisible { + visibility: hidden; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.left-2 { + left: 0.5rem; +} + +.right-0 { + right: 0px; +} + +.right-5 { + right: 1.25rem; +} + +.top-0 { + top: 0px; +} + +.top-2 { + top: 0.5rem; +} + +.top-5 { + top: 1.25rem; +} + +.z-0 { + z-index: 0; +} + +.z-10 { + z-index: 10; +} + +.z-50 { + z-index: 50; +} + +.z-\[1\] { + z-index: 1; +} + +.z-\[5000\] { + z-index: 5000; +} + +.z-\[6000\] { + z-index: 6000; +} + +.m-0 { + margin: 0px; +} + +.m-2 { + margin: 0.5rem; +} + +.m-5 { + margin: 1.25rem; +} + +.m-auto { + margin: auto; +} + +.mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.mx-5 { + margin-left: 1.25rem; + margin-right: 1.25rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.my-10 { + margin-top: 2.5rem; + margin-bottom: 2.5rem; +} + +.my-2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +.my-3 { + margin-top: 0.75rem; + margin-bottom: 0.75rem; +} + +.my-4 { + margin-top: 1rem; + margin-bottom: 1rem; +} + +.my-5 { + margin-top: 1.25rem; + margin-bottom: 1.25rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mb-5 { + margin-bottom: 1.25rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.mb-8 { + margin-bottom: 2rem; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.ml-4 { + margin-left: 1rem; +} + +.ml-auto { + margin-left: auto; +} + +.mr-2 { + margin-right: 0.5rem; +} + +.mr-4 { + margin-right: 1rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-10 { + margin-top: 2.5rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-3 { + margin-top: 0.75rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mt-5 { + margin-top: 1.25rem; +} + +.mt-6 { + margin-top: 1.5rem; +} + +.mt-8 { + margin-top: 2rem; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +.inline { + display: inline; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.table { + display: table; +} + +.grid { + display: grid; +} + +.contents { + display: contents; +} + +.hidden { + display: none; +} + +.h-4 { + height: 1rem; +} + +.h-48 { + height: 12rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-8 { + height: 2rem; +} + +.h-96 { + height: 24rem; +} + +.h-\[250px\] { + height: 250px; +} + +.h-\[25rem\] { + height: 25rem; +} + +.h-fit { + height: -moz-fit-content; + height: fit-content; +} + +.h-full { + height: 100%; +} + +.max-h-96 { + max-height: 24rem; +} + +.min-h-80 { + min-height: 20rem; +} + +.min-h-screen { + min-height: 100vh; +} + +.w-1\/2 { + width: 50%; +} + +.w-10\/12 { + width: 83.333333%; +} + +.w-4 { + width: 1rem; +} + +.w-4\/12 { + width: 33.333333%; +} + +.w-5 { + width: 1.25rem; +} + +.w-52 { + width: 13rem; +} + +.w-6 { + width: 1.5rem; +} + +.w-64 { + width: 16rem; +} + +.w-8 { + width: 2rem; +} + +.w-80 { + width: 20rem; +} + +.w-96 { + width: 24rem; +} + +.w-auto { + width: auto; +} + +.w-full { + width: 100%; +} + +.min-w-52 { + min-width: 13rem; +} + +.min-w-full { + min-width: 100%; +} + +.max-w-2xl { + max-width: 42rem; +} + +.max-w-3xl { + max-width: 48rem; +} + +.max-w-5xl { + max-width: 64rem; +} + +.max-w-md { + max-width: 28rem; +} + +.max-w-sm { + max-width: 24rem; +} + +.max-w-xs { + max-width: 20rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +.shrink-0 { + flex-shrink: 0; +} + +.translate-x-full { + --tw-translate-x: 100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.cursor-pointer { + cursor: pointer; +} + +.resize { + resize: both; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.flex-row { + flex-direction: row; +} + +.flex-col { + flex-direction: column; +} + +.flex-col-reverse { + flex-direction: column-reverse; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.items-center { + align-items: center; +} + +.justify-start { + justify-content: flex-start; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-3 { + gap: 0.75rem; +} + +.gap-4 { + gap: 1rem; +} + +.gap-5 { + gap: 1.25rem; +} + +.gap-6 { + gap: 1.5rem; +} + +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); +} + +.space-y-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + +.divide-y > :not([hidden]) ~ :not([hidden]) { + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.divide-base-300 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-divide-opacity, 1))); +} + +.justify-self-end { + justify-self: end; +} + +.justify-self-center { + justify-self: center; +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-ellipsis { + text-overflow: ellipsis; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-box { + border-radius: var(--rounded-box, 1rem); +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-t-none { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +.border { + border-width: 1px; +} + +.border-2 { + border-width: 2px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-dashed { + border-style: dashed; +} + +.border-base-300 { + --tw-border-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity, 1))); +} + +.border-blue-300 { + --tw-border-opacity: 1; + border-color: rgb(147 197 253 / var(--tw-border-opacity, 1)); +} + +.border-error { + --tw-border-opacity: 1; + border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity, 1))); +} + +.border-gray-500 { + --tw-border-opacity: 1; + border-color: rgb(107 114 128 / var(--tw-border-opacity, 1)); +} + +.border-red-300 { + --tw-border-opacity: 1; + border-color: rgb(252 165 165 / var(--tw-border-opacity, 1)); +} + +.border-sky-500 { + --tw-border-opacity: 1; + border-color: rgb(14 165 233 / var(--tw-border-opacity, 1)); +} + +.border-opacity-30 { + --tw-border-opacity: 0.3; +} + +.bg-base-100 { + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity, 1))); +} + +.bg-base-200 { + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity, 1))); +} + +.bg-base-300 { + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity, 1))); +} + +.bg-blue-100 { + --tw-bg-opacity: 1; + background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)); +} + +.bg-blue-500 { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1)); +} + +.bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1)); +} + +.bg-blue-900 { + --tw-bg-opacity: 1; + background-color: rgb(30 58 138 / var(--tw-bg-opacity, 1)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1)); +} + +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); +} + +.bg-green-50 { + --tw-bg-opacity: 1; + background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1)); +} + +.bg-green-500 { + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1)); +} + +.bg-neutral { + --tw-bg-opacity: 1; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity, 1))); +} + +.bg-red-100 { + --tw-bg-opacity: 1; + background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1)); +} + +.bg-red-50 { + --tw-bg-opacity: 1; + background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1)); +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1)); +} + +.bg-secondary-content { + --tw-bg-opacity: 1; + background-color: var(--fallback-sc,oklch(var(--sc)/var(--tw-bg-opacity, 1))); +} + +.stroke-current { + stroke: currentColor; +} + +.stroke-info { + stroke: var(--fallback-in,oklch(var(--in)/1)); +} + +.object-cover { + -o-object-fit: cover; + object-fit: cover; +} + +.p-0 { + padding: 0px; +} + +.p-2 { + padding: 0.5rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-4 { + padding: 1rem; +} + +.p-5 { + padding: 1.25rem; +} + +.px-1 { + padding-left: 0.25rem; + padding-right: 0.25rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-20 { + padding-top: 5rem; + padding-bottom: 5rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-5 { + padding-top: 1.25rem; + padding-bottom: 1.25rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.pl-4 { + padding-left: 1rem; +} + +.pl-6 { + padding-left: 1.5rem; +} + +.pr-10 { + padding-right: 2.5rem; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.font-mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + +.text-5xl { + font-size: 3rem; + line-height: 1; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-black { + font-weight: 900; +} + +.font-bold { + font-weight: 700; +} + +.font-medium { + font-weight: 500; +} + +.font-semibold { + font-weight: 600; +} + +.normal-case { + text-transform: none; +} + +.italic { + font-style: italic; +} + +.text-accent { + --tw-text-opacity: 1; + color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity, 1))); +} + +.text-accent-content { + --tw-text-opacity: 1; + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity, 1))); +} + +.text-base-content { + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity, 1))); +} + +.text-base-content\/60 { + color: var(--fallback-bc,oklch(var(--bc)/0.6)); +} + +.text-base-content\/70 { + color: var(--fallback-bc,oklch(var(--bc)/0.7)); +} + +.text-base-content\/80 { + color: var(--fallback-bc,oklch(var(--bc)/0.8)); +} + +.text-blue-600 { + --tw-text-opacity: 1; + color: rgb(37 99 235 / var(--tw-text-opacity, 1)); +} + +.text-blue-700 { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity, 1)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity, 1)); +} + +.text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity, 1)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity, 1)); +} + +.text-green-500 { + --tw-text-opacity: 1; + color: rgb(34 197 94 / var(--tw-text-opacity, 1)); +} + +.text-neutral-content { + --tw-text-opacity: 1; + color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity, 1))); +} + +.text-primary { + --tw-text-opacity: 1; + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity, 1))); +} + +.text-red-500 { + --tw-text-opacity: 1; + color: rgb(239 68 68 / var(--tw-text-opacity, 1)); +} + +.text-red-700 { + --tw-text-opacity: 1; + color: rgb(185 28 28 / var(--tw-text-opacity, 1)); +} + +.text-secondary { + --tw-text-opacity: 1; + color: var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity, 1))); +} + +.text-success { + --tw-text-opacity: 1; + color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity, 1))); +} + +.text-warning { + --tw-text-opacity: 1; + color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity, 1))); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity, 1)); +} + +.underline { + text-decoration-line: underline; +} + +.decoration-dotted { + text-decoration-style: dotted; +} + +.placeholder-base-content\/70::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/0.7)); +} + +.placeholder-base-content\/70::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/0.7)); +} + +.opacity-0 { + opacity: 0; +} + +.opacity-50 { + opacity: 0.5; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-2xl { + --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); + --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-sm { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-xl { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.grayscale { + --tw-grayscale: grayscale(100%); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-shadow { + transition-property: box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-200 { + transition-duration: 200ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +@tailwind daisyui; + +/* + +@layer components { + .btn-primary { + @apply py-2 px-4 bg-blue-200; + } +} + +*/ + +/* Leaflet Panel Styles */ + +.leaflet-right-panel { + margin-top: 80px; + /* Give space for controls above */ + margin-right: 10px; + transform: none; + transition: right 0.3s ease-in-out; + z-index: 400; + background: white; + border-radius: 4px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} + +.leaflet-right-panel.controls-shifted { + right: 310px; +} + +.leaflet-control-button { + background-color: white !important; + color: #374151 !important; +} + +.leaflet-control-button:hover { + background-color: #f3f4f6 !important; +} + +/* Drawer Panel Styles */ + +.leaflet-drawer { + position: absolute; + top: 0; + right: 0; + width: 338px; + height: 100%; + background: rgba(255, 255, 255, 0.5); + transform: translateX(100%); + transition: transform 0.3s ease-in-out; + z-index: 450; + box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1); +} + +.leaflet-drawer.open { + transform: translateX(0); +} + +/* Controls transition */ + +.leaflet-control-layers, +.leaflet-control-button, +.toggle-panel-button { + transition: right 0.3s ease-in-out; + z-index: 500; +} + +.controls-shifted { + right: 338px !important; +} + +/* Selection Tool Styles */ + +.leaflet-control-custom { + background-color: white; + border-radius: 4px; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} + +.leaflet-control-custom:hover { + background-color: #f3f4f6; +} + +#selection-tool-button.active { + background-color: #60a5fa; + color: white; +} + +/* Cancel Selection Button */ + +#cancel-selection-button { + margin-bottom: 1rem; + width: 100%; +} + +@media (hover: hover) { + .hover\:btn-ghost:hover:hover { + border-color: transparent; + } + + @supports (color: oklch(0 0 0)) { + .hover\:btn-ghost:hover:hover { + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + } + } + + .hover\:btn-ghost:hover:hover { + border-color: transparent; + } + + @supports (color: oklch(0 0 0)) { + .hover\:btn-ghost:hover:hover { + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + } + } + + .hover\:btn-info:hover.btn-outline:hover { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .hover\:btn-info:hover.btn-outline:hover { + background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + } + } + + .hover\:btn-info:hover.btn-outline:hover { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .hover\:btn-info:hover.btn-outline:hover { + background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + } + } +} + +@supports not (color: oklch(0 0 0)) { + .hover\:btn-info:hover { + --btn-color: var(--fallback-in); + } +} + +@supports (color: color-mix(in oklab, black, black)) { + .hover\:btn-info:hover.btn-outline.btn-active { + background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black); + } +} + +@supports (color: oklch(0 0 0)) { + .hover\:btn-info:hover { + --btn-color: var(--in); + } +} + +.hover\:btn-info:hover { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); + outline-color: var(--fallback-in,oklch(var(--in)/1)); +} + +.hover\:btn-ghost:hover { + border-width: 1px; + border-color: transparent; + background-color: transparent; + color: currentColor; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + outline-color: currentColor; +} + +.hover\:btn-ghost:hover.btn-active { + border-color: transparent; + background-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.hover\:btn-info:hover.btn-outline { + --tw-text-opacity: 1; + color: var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity))); +} + +.hover\:btn-info:hover.btn-outline.btn-active { + --tw-text-opacity: 1; + color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity))); +} + +.hover\:input-primary:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); +} + +.hover\:input-primary:hover:focus,.hover\:input-primary:hover:focus-within { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +.focus\:input-ghost:focus { + --tw-bg-opacity: 0.05; +} + +.focus\:input-ghost:focus:focus,.focus\:input-ghost:focus:focus-within { + --tw-bg-opacity: 1; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + box-shadow: none; +} + +@media not all and (min-width: 768px) { + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; + } + + .max-md\:timeline-compact.timeline-vertical > li { + --timeline-col-start: 0; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; + } + + .max-md\:timeline-compact.timeline-vertical > li { + --timeline-col-start: 0; + } + + .max-md\:timeline-compact.timeline-vertical .timeline-start { + grid-column-start: 3; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 4; + align-self: center; + justify-self: start; + } + + .max-md\:timeline-compact,.max-md\:timeline-compact +.timeline-horizontal { + --timeline-row-start: 0; + } + + .max-md\:timeline-compact .timeline-start,.max-md\:timeline-compact .timeline-horizontal .timeline-start { + grid-column-start: 1; + grid-column-end: 4; + grid-row-start: 3; + grid-row-end: 4; + margin: 0.25rem; + align-self: flex-start; + justify-self: center; + } + + .max-md\:timeline-compact li:has(.timeline-start) .timeline-end,.max-md\:timeline-compact .timeline-horizontal li:has(.timeline-start) .timeline-end { + grid-column-start: none; + grid-row-start: auto; + } + + .max-md\:timeline-compact.timeline-vertical > li { + --timeline-col-start: 0; + } + + .max-md\:timeline-compact.timeline-vertical .timeline-start { + grid-column-start: 3; + grid-column-end: 4; + grid-row-start: 1; + grid-row-end: 4; + align-self: center; + justify-self: start; + } + + .max-md\:timeline-compact.timeline-vertical li:has(.timeline-start) .timeline-end { + grid-column-start: auto; + grid-row-start: none; + } +} + +@media (min-width: 1024px) { + .lg\:stats-horizontal { + grid-auto-flow: column; + } + + .lg\:stats-horizontal > :not([hidden]) ~ :not([hidden]) { + --tw-divide-x-reverse: 0; + border-right-width: calc(1px * var(--tw-divide-x-reverse)); + border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); + --tw-divide-y-reverse: 0; + border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(0px * var(--tw-divide-y-reverse)); + } + + .lg\:stats-horizontal { + overflow-x: auto; + } + + :is([dir="rtl"] .lg\:stats-horizontal) { + --tw-divide-x-reverse: 1; + } +} + +.last\:border-0:last-child { + border-width: 0px; +} + +.hover\:scale-105:hover { + --tw-scale-x: 1.05; + --tw-scale-y: 1.05; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.hover\:cursor-pointer:hover { + cursor: pointer; +} + +.hover\:bg-accent:hover { + --tw-bg-opacity: 1; + background-color: var(--fallback-a,oklch(var(--a)/var(--tw-bg-opacity, 1))); +} + +.hover\:bg-base-200:hover { + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity, 1))); +} + +.hover\:bg-base-300:hover { + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity, 1))); +} + +.hover\:text-accent-content:hover { + --tw-text-opacity: 1; + color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity, 1))); +} + +.hover\:underline:hover { + text-decoration-line: underline; +} + +.hover\:no-underline:hover { + text-decoration-line: none; +} + +.hover\:shadow-2xl:hover { + --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); + --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.hover\:shadow-lg:hover { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.hover\:shadow-blue-500\/50:hover { + --tw-shadow-color: rgb(59 130 246 / 0.5); + --tw-shadow: var(--tw-shadow-colored); +} + +.focus\:border-primary:focus { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity, 1))); +} + +.focus\:bg-base-100:focus { + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity, 1))); +} + +.group:hover .group-hover\:opacity-100 { + opacity: 1; +} + +@media (min-width: 640px) { + .sm\:inline { + display: inline; + } + + .sm\:w-1\/12 { + width: 8.333333%; + } + + .sm\:w-2\/12 { + width: 16.666667%; + } + + .sm\:w-6\/12 { + width: 50%; + } + + .sm\:grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .sm\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .sm\:flex-row { + flex-direction: row; + } + + .sm\:items-end { + align-items: flex-end; + } + + .sm\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + } + + .sm\:space-y-0 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0px * var(--tw-space-y-reverse)); + } +} + +@media (min-width: 768px) { + .md\:h-64 { + height: 16rem; + } + + .md\:min-h-64 { + min-height: 16rem; + } + + .md\:w-1\/12 { + width: 8.333333%; + } + + .md\:w-2\/12 { + width: 16.666667%; + } + + .md\:w-2\/3 { + width: 66.666667%; + } + + .md\:w-3\/12 { + width: 25%; + } + + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:flex-row { + flex-direction: row; + } + + .md\:items-end { + align-items: flex-end; + } + + .md\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + } + + .md\:text-end { + text-align: end; + } +} + +@media (min-width: 1024px) { + .lg\:flex { + display: flex; + } + + .lg\:hidden { + display: none; + } + + .lg\:w-1\/12 { + width: 8.333333%; + } + + .lg\:w-1\/2 { + width: 50%; + } + + .lg\:w-2\/12 { + width: 16.666667%; + } + + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .lg\:flex-row { + flex-direction: row; + } + + .lg\:flex-row-reverse { + flex-direction: row-reverse; + } + + .lg\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + } + + .lg\:text-left { + text-align: left; + } +} + +@media (prefers-color-scheme: dark) { + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1)); + } +} diff --git a/app/models/concerns/distanceable.rb b/app/models/concerns/distanceable.rb index 7ddc190d..f9c28477 100644 --- a/app/models/concerns/distanceable.rb +++ b/app/models/concerns/distanceable.rb @@ -50,16 +50,43 @@ module Distanceable return 0 if points.length < 2 - total_meters = points.each_cons(2).sum do |point1, point2| - connection.select_value( - 'SELECT ST_Distance(ST_GeomFromEWKT($1)::geography, ST_GeomFromEWKT($2)::geography)', - nil, - [point1.lonlat, point2.lonlat] - ) - end + # OPTIMIZED: Single SQL query instead of N individual queries + total_meters = calculate_batch_distances(points).sum total_meters.to_f / ::DISTANCE_UNITS[unit.to_sym] end + + # Optimized batch distance calculation using single SQL query + def calculate_batch_distances(points) + return [] if points.length < 2 + + point_pairs = points.each_cons(2).to_a + return [] if point_pairs.empty? + + # Create a VALUES clause with all point pairs + values_clause = point_pairs.map.with_index do |(p1, p2), index| + "(#{index}, ST_GeomFromEWKT('#{p1.lonlat}')::geography, ST_GeomFromEWKT('#{p2.lonlat}')::geography)" + end.join(', ') + + # Single query to calculate all distances + results = connection.execute(<<-SQL.squish) + WITH point_pairs AS ( + SELECT + pair_id, + point1, + point2 + FROM (VALUES #{values_clause}) AS t(pair_id, point1, point2) + ) + SELECT + pair_id, + ST_Distance(point1, point2) as distance_meters + FROM point_pairs + ORDER BY pair_id + SQL + + # Return array of distances in meters + results.map { |row| row['distance_meters'].to_f } + end end def distance_to(other_point, unit = :km) diff --git a/app/models/track.rb b/app/models/track.rb index 9e9724a7..b79de93e 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -25,6 +25,112 @@ class Track < ApplicationRecord .first end + # Optimized SQL segmentation using PostgreSQL window functions + def self.segment_points_in_sql(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters, untracked_only: false) + time_threshold_seconds = time_threshold_minutes * 60 + + where_clause = if untracked_only + "WHERE user_id = $1 AND timestamp BETWEEN $2 AND $3 AND track_id IS NULL" + else + "WHERE user_id = $1 AND timestamp BETWEEN $2 AND $3" + end + + sql = <<~SQL + WITH points_with_gaps AS ( + SELECT + id, + timestamp, + lonlat, + LAG(lonlat) OVER (ORDER BY timestamp) as prev_lonlat, + LAG(timestamp) OVER (ORDER BY timestamp) as prev_timestamp, + ST_Distance( + lonlat::geography, + LAG(lonlat) OVER (ORDER BY timestamp)::geography + ) as distance_meters, + (timestamp - LAG(timestamp) OVER (ORDER BY timestamp)) as time_diff_seconds + FROM points + #{where_clause} + ORDER BY timestamp + ), + segment_breaks AS ( + SELECT *, + CASE + WHEN prev_lonlat IS NULL THEN 1 + WHEN time_diff_seconds > $4 THEN 1 + WHEN distance_meters > $5 THEN 1 + ELSE 0 + END as is_break + FROM points_with_gaps + ), + segments AS ( + SELECT *, + SUM(is_break) OVER (ORDER BY timestamp ROWS UNBOUNDED PRECEDING) as segment_id + FROM segment_breaks + ) + SELECT + segment_id, + array_agg(id ORDER BY timestamp) as point_ids, + count(*) as point_count, + min(timestamp) as start_timestamp, + max(timestamp) as end_timestamp, + sum(COALESCE(distance_meters, 0)) as total_distance_meters + FROM segments + GROUP BY segment_id + HAVING count(*) >= 2 + ORDER BY segment_id + SQL + + results = Point.connection.exec_query( + sql, + 'segment_points_in_sql', + [user_id, start_timestamp, end_timestamp, time_threshold_seconds, distance_threshold_meters] + ) + + # Convert results to segment data + segments_data = [] + results.each do |row| + segments_data << { + segment_id: row['segment_id'].to_i, + point_ids: parse_postgres_array(row['point_ids']), + point_count: row['point_count'].to_i, + start_timestamp: row['start_timestamp'].to_i, + end_timestamp: row['end_timestamp'].to_i, + total_distance_meters: row['total_distance_meters'].to_f + } + end + + segments_data + end + + # Get actual Point objects for each segment with pre-calculated distances + def self.get_segments_with_points(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters, untracked_only: false) + segments_data = segment_points_in_sql(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters, untracked_only: untracked_only) + + # Get all point IDs we need + all_point_ids = segments_data.flat_map { |seg| seg[:point_ids] } + + # Single query to get all points + points_by_id = Point.where(id: all_point_ids).index_by(&:id) + + # Build segments with actual Point objects + segments_data.map do |seg_data| + { + points: seg_data[:point_ids].map { |id| points_by_id[id] }.compact, + pre_calculated_distance: seg_data[:total_distance_meters], + start_timestamp: seg_data[:start_timestamp], + end_timestamp: seg_data[:end_timestamp] + } + end + end + + # Parse PostgreSQL array format like "{1,2,3}" into Ruby array + def self.parse_postgres_array(pg_array_string) + return [] if pg_array_string.nil? || pg_array_string.empty? + + # Remove curly braces and split by comma + pg_array_string.gsub(/[{}]/, '').split(',').map(&:to_i) + end + private def broadcast_track_created diff --git a/app/services/tracks/generator.rb b/app/services/tracks/generator.rb index 9ffcdbb7..f39b9f8b 100644 --- a/app/services/tracks/generator.rb +++ b/app/services/tracks/generator.rb @@ -40,21 +40,32 @@ class Tracks::Generator def call clean_existing_tracks if should_clean_tracks? - points = load_points - Rails.logger.debug "Generator: loaded #{points.size} points for user #{user.id} in #{mode} mode" - return 0 if points.empty? + # Get timestamp range for SQL query + start_timestamp, end_timestamp = get_timestamp_range + + Rails.logger.debug "Generator: querying points for user #{user.id} in #{mode} mode" + + # Use optimized SQL segmentation with pre-calculated distances + untracked_only = (mode == :incremental) + segments = Track.get_segments_with_points( + user.id, + start_timestamp, + end_timestamp, + time_threshold_minutes, + distance_threshold_meters, + untracked_only: untracked_only + ) - segments = split_points_into_segments(points) - Rails.logger.debug "Generator: created #{segments.size} segments" + Rails.logger.debug "Generator: created #{segments.size} segments via SQL" tracks_created = 0 - segments.each do |segment| - track = create_track_from_segment(segment) + segments.each do |segment_data| + track = create_track_from_segment_optimized(segment_data) tracks_created += 1 if track end - Rails.logger.info "Generated #{tracks_created} tracks for user #{user.id} in #{mode} mode" + Rails.logger.info "Generated #{tracks_created} tracks for user #{user.id} in optimized #{mode} mode" tracks_created end @@ -99,6 +110,18 @@ class Tracks::Generator user.tracked_points.where(timestamp: day_range).order(:timestamp) end + def create_track_from_segment_optimized(segment_data) + points = segment_data[:points] + pre_calculated_distance = segment_data[:pre_calculated_distance] + + Rails.logger.debug "Generator: processing segment with #{points.size} points" + return unless points.size >= 2 + + track = create_track_from_points_optimized(points, pre_calculated_distance) + Rails.logger.debug "Generator: created track #{track&.id}" + track + end + def create_track_from_segment(segment) Rails.logger.debug "Generator: processing segment with #{segment.size} points" return unless segment.size >= 2 @@ -171,6 +194,31 @@ class Tracks::Generator scope.destroy_all end + # Get timestamp range for SQL query based on mode + def get_timestamp_range + case mode + when :bulk + if start_at && end_at + [start_at.to_i, end_at.to_i] + else + # Get full range for user + first_point = user.tracked_points.order(:timestamp).first + last_point = user.tracked_points.order(:timestamp).last + [first_point&.timestamp || 0, last_point&.timestamp || Time.current.to_i] + end + when :daily + day = start_at&.to_date || Date.current + [day.beginning_of_day.to_i, day.end_of_day.to_i] + when :incremental + # For incremental, we need all untracked points up to end_at + first_point = user.tracked_points.where(track_id: nil).order(:timestamp).first + end_timestamp = end_at ? end_at.to_i : Time.current.to_i + [first_point&.timestamp || 0, end_timestamp] + else + raise ArgumentError, "Unknown mode: #{mode}" + end + end + # Threshold methods from safe_settings def distance_threshold_meters @distance_threshold_meters ||= user.safe_settings.meters_between_routes.to_i diff --git a/app/services/tracks/segmentation.rb b/app/services/tracks/segmentation.rb index 57ca3b03..9f0842cc 100644 --- a/app/services/tracks/segmentation.rb +++ b/app/services/tracks/segmentation.rb @@ -86,11 +86,15 @@ module Tracks::Segmentation end def calculate_km_distance_between_points(point1, point2) - lat1, lon1 = point_coordinates(point1) - lat2, lon2 = point_coordinates(point2) - - # Use Geocoder to match behavior with frontend (same library used elsewhere in app) - Geocoder::Calculations.distance_between([lat1, lon1], [lat2, lon2], units: :km) + # OPTIMIZED: Use PostGIS for more accurate distance calculation (same as track distance) + # This maintains consistency with track distance calculations + distance_meters = Point.connection.select_value( + 'SELECT ST_Distance(ST_GeomFromEWKT($1)::geography, ST_GeomFromEWKT($2)::geography)', + nil, + [point1.lonlat, point2.lonlat] + ) + + distance_meters.to_f / 1000.0 # Convert meters to kilometers end def should_finalize_segment?(segment_points, grace_period_minutes = 5) diff --git a/app/services/tracks/track_builder.rb b/app/services/tracks/track_builder.rb index 99830bc1..95bbcae3 100644 --- a/app/services/tracks/track_builder.rb +++ b/app/services/tracks/track_builder.rb @@ -82,6 +82,38 @@ module Tracks::TrackBuilder end end + # Optimized version that uses pre-calculated distance from SQL + def create_track_from_points_optimized(points, pre_calculated_distance) + return nil if points.size < 2 + + track = Track.new( + user_id: user.id, + start_at: Time.zone.at(points.first.timestamp), + end_at: Time.zone.at(points.last.timestamp), + original_path: build_path(points) + ) + + # Use pre-calculated distance from SQL instead of recalculating + track.distance = pre_calculated_distance.round + track.duration = calculate_duration(points) + track.avg_speed = calculate_average_speed(track.distance, track.duration) + + # Calculate elevation statistics (no DB queries needed) + elevation_stats = calculate_elevation_stats(points) + track.elevation_gain = elevation_stats[:gain] + track.elevation_loss = elevation_stats[:loss] + track.elevation_max = elevation_stats[:max] + track.elevation_min = elevation_stats[:min] + + if track.save + Point.where(id: points.map(&:id)).update_all(track_id: track.id) + track + else + Rails.logger.error "Failed to create track for user #{user.id}: #{track.errors.full_messages.join(', ')}" + nil + end + end + def build_path(points) Tracks::BuildPath.new(points).call end diff --git a/app/views/stats/index.html.erb b/app/views/stats/index.html.erb index a5ab367b..af42647b 100644 --- a/app/views/stats/index.html.erb +++ b/app/views/stats/index.html.erb @@ -21,7 +21,9 @@ <% end %> - <%= link_to 'Update stats', update_all_stats_path, data: { turbo_method: :put }, class: 'btn btn-primary mt-5' %> + <% if current_user.active? %> + <%= link_to 'Update stats', update_all_stats_path, data: { turbo_method: :put }, class: 'btn btn-primary mt-5' %> + <% end %>
<% @stats.each do |year, stats| %> @@ -33,7 +35,7 @@ <%= link_to '[Map]', map_url(year_timespan(year)), class: 'underline hover:no-underline' %>
- Last updated: <%= human_date(stats.first.updated_at) %> + Last update: <%= human_date(stats.first.updated_at) %> <%= link_to '๐Ÿ”„', update_year_month_stats_path(year, :all), data: { turbo_method: :put }, class: 'text-sm text-gray-500 hover:underline' %>
diff --git a/config/environments/development.rb b/config/environments/development.rb index c940de0e..a5b3fce4 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -3,6 +3,17 @@ require 'active_support/core_ext/integer/time' Rails.application.configure do + unless ENV['SELF_HOSTED'] == 'true' + config.after_initialize do + Bullet.enable = true + Bullet.alert = true + Bullet.bullet_logger = true + Bullet.console = true + Bullet.rails_logger = true + Bullet.add_footer = true + end + end + # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded any time diff --git a/config/environments/test.rb b/config/environments/test.rb index e138d076..b4884952 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -8,6 +8,12 @@ require 'active_support/core_ext/integer/time' # and recreated between test runs. Don't rely on the data there! Rails.application.configure do + config.after_initialize do + Bullet.enable = true + Bullet.bullet_logger = true + Bullet.raise = true # raise an error if n+1 query occurs + end + # Settings specified here will take precedence over those in config/application.rb. # While tests run files are not watched, reloading is not necessary. diff --git a/lib/optimized_tracks_v1.rb b/lib/optimized_tracks_v1.rb new file mode 100644 index 00000000..08969aa4 --- /dev/null +++ b/lib/optimized_tracks_v1.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +# Optimization V1: LAG-based distance calculation with Ruby segmentation +# This keeps the existing Ruby segmentation logic but uses PostgreSQL LAG +# for batch distance calculations instead of individual queries + +module OptimizedTracksV1 + extend ActiveSupport::Concern + + module ClassMethods + # V1: Use LAG to get all consecutive distances in a single query + def calculate_all_consecutive_distances(points) + return [] if points.length < 2 + + point_ids = points.map(&:id).join(',') + + results = connection.execute(<<-SQL.squish) + WITH points_with_previous AS ( + SELECT + id, + timestamp, + lonlat, + LAG(lonlat) OVER (ORDER BY timestamp) as prev_lonlat, + LAG(timestamp) OVER (ORDER BY timestamp) as prev_timestamp, + LAG(id) OVER (ORDER BY timestamp) as prev_id + FROM points + WHERE id IN (#{point_ids}) + ) + SELECT + id, + prev_id, + timestamp, + prev_timestamp, + ST_Distance(lonlat::geography, prev_lonlat::geography) as distance_meters, + (timestamp - prev_timestamp) as time_diff_seconds + FROM points_with_previous + WHERE prev_lonlat IS NOT NULL + ORDER BY timestamp + SQL + + # Return hash mapping point_id => {distance_to_previous, time_diff} + distance_map = {} + results.each do |row| + distance_map[row['id'].to_i] = { + distance_meters: row['distance_meters'].to_f, + time_diff_seconds: row['time_diff_seconds'].to_i, + prev_id: row['prev_id'].to_i + } + end + + distance_map + end + + # V1: Optimized total distance using LAG (already exists in distanceable.rb) + def total_distance_lag(points, unit = :m) + unless ::DISTANCE_UNITS.key?(unit.to_sym) + raise ArgumentError, "Invalid unit. Supported units are: #{::DISTANCE_UNITS.keys.join(', ')}" + end + + return 0 if points.length < 2 + + point_ids = points.map(&:id).join(',') + + distance_in_meters = connection.select_value(<<-SQL.squish) + WITH points_with_previous AS ( + SELECT + lonlat, + LAG(lonlat) OVER (ORDER BY timestamp) as prev_lonlat + FROM points + WHERE id IN (#{point_ids}) + ) + SELECT COALESCE( + SUM(ST_Distance(lonlat::geography, prev_lonlat::geography)), + 0 + ) + FROM points_with_previous + WHERE prev_lonlat IS NOT NULL + SQL + + distance_in_meters.to_f / ::DISTANCE_UNITS[unit.to_sym] + end + end +end + +# Optimized segmentation module using pre-calculated distances +module OptimizedSegmentationV1 + extend ActiveSupport::Concern + + private + + def split_points_into_segments_v1(points) + return [] if points.empty? + + # V1: Pre-calculate all distances and time diffs in one query + if points.size > 1 + distance_data = Point.calculate_all_consecutive_distances(points) + else + distance_data = {} + end + + segments = [] + current_segment = [] + + points.each do |point| + if current_segment.empty? + # First point always starts a segment + current_segment = [point] + elsif should_start_new_segment_v1?(point, current_segment.last, distance_data) + # Finalize current segment if it has enough points + segments << current_segment if current_segment.size >= 2 + current_segment = [point] + else + current_segment << point + end + end + + # Don't forget the last segment + segments << current_segment if current_segment.size >= 2 + + segments + end + + def should_start_new_segment_v1?(current_point, previous_point, distance_data) + return false if previous_point.nil? + + # Get pre-calculated data for this point + point_data = distance_data[current_point.id] + return false unless point_data + + # Check time threshold + time_threshold_seconds = time_threshold_minutes.to_i * 60 + return true if point_data[:time_diff_seconds] > time_threshold_seconds + + # Check distance threshold + distance_meters = point_data[:distance_meters] + return true if distance_meters > distance_threshold_meters + + false + end +end + +# Add methods to Point class +class Point + extend OptimizedTracksV1::ClassMethods +end \ No newline at end of file diff --git a/lib/optimized_tracks_v2.rb b/lib/optimized_tracks_v2.rb new file mode 100644 index 00000000..03981fe6 --- /dev/null +++ b/lib/optimized_tracks_v2.rb @@ -0,0 +1,291 @@ +# frozen_string_literal: true + +# Optimization V2: Full SQL segmentation using PostgreSQL window functions +# This does both distance calculation AND segmentation entirely in SQL + +module OptimizedTracksV2 + extend ActiveSupport::Concern + + module ClassMethods + # V2: Complete segmentation in SQL using LAG and window functions + def segment_points_in_sql(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters) + time_threshold_seconds = time_threshold_minutes * 60 + + sql = <<~SQL + WITH points_with_gaps AS ( + SELECT + id, + timestamp, + lonlat, + LAG(lonlat) OVER (ORDER BY timestamp) as prev_lonlat, + LAG(timestamp) OVER (ORDER BY timestamp) as prev_timestamp, + ST_Distance( + lonlat::geography, + LAG(lonlat) OVER (ORDER BY timestamp)::geography + ) as distance_meters, + (timestamp - LAG(timestamp) OVER (ORDER BY timestamp)) as time_diff_seconds + FROM points + WHERE user_id = $1 + AND timestamp BETWEEN $2 AND $3 + ORDER BY timestamp + ), + segment_breaks AS ( + SELECT *, + CASE + WHEN prev_lonlat IS NULL THEN 1 + WHEN time_diff_seconds > $4 THEN 1 + WHEN distance_meters > $5 THEN 1 + ELSE 0 + END as is_break + FROM points_with_gaps + ), + segments AS ( + SELECT *, + SUM(is_break) OVER (ORDER BY timestamp ROWS UNBOUNDED PRECEDING) as segment_id + FROM segment_breaks + ) + SELECT + segment_id, + array_agg(id ORDER BY timestamp) as point_ids, + count(*) as point_count, + min(timestamp) as start_timestamp, + max(timestamp) as end_timestamp, + sum(COALESCE(distance_meters, 0)) as total_distance_meters + FROM segments + GROUP BY segment_id + HAVING count(*) >= 2 + ORDER BY segment_id + SQL + + results = connection.exec_query( + sql, + 'segment_points_in_sql', + [user_id, start_timestamp, end_timestamp, time_threshold_seconds, distance_threshold_meters] + ) + + # Convert results to segment data + segments_data = [] + results.each do |row| + segments_data << { + segment_id: row['segment_id'].to_i, + point_ids: parse_postgres_array(row['point_ids']), + point_count: row['point_count'].to_i, + start_timestamp: row['start_timestamp'].to_i, + end_timestamp: row['end_timestamp'].to_i, + total_distance_meters: row['total_distance_meters'].to_f + } + end + + segments_data + end + + # V2: Get actual Point objects for each segment + def get_segments_with_points(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters) + segments_data = segment_points_in_sql(user_id, start_timestamp, end_timestamp, time_threshold_minutes, distance_threshold_meters) + + # Get all point IDs we need + all_point_ids = segments_data.flat_map { |seg| seg[:point_ids] } + + # Single query to get all points + points_by_id = Point.where(id: all_point_ids).index_by(&:id) + + # Build segments with actual Point objects + segments_data.map do |seg_data| + { + points: seg_data[:point_ids].map { |id| points_by_id[id] }.compact, + pre_calculated_distance: seg_data[:total_distance_meters], + start_timestamp: seg_data[:start_timestamp], + end_timestamp: seg_data[:end_timestamp] + } + end + end + + private + + # Parse PostgreSQL array format like "{1,2,3}" into Ruby array + def parse_postgres_array(pg_array_string) + return [] if pg_array_string.nil? || pg_array_string.empty? + + # Remove curly braces and split by comma + pg_array_string.gsub(/[{}]/, '').split(',').map(&:to_i) + end + end +end + +# Optimized generator using V2 SQL segmentation +class OptimizedTracksGeneratorV2 + attr_reader :user, :start_at, :end_at, :mode + + def initialize(user, start_at: nil, end_at: nil, mode: :bulk) + @user = user + @start_at = start_at + @end_at = end_at + @mode = mode.to_sym + end + + def call + clean_existing_tracks if should_clean_tracks? + + # Get timestamp range for SQL query + start_timestamp, end_timestamp = get_timestamp_range + + Rails.logger.debug "OptimizedGeneratorV2: querying points for user #{user.id} in #{mode} mode" + + # V2: Get segments directly from SQL with pre-calculated distances + segments = Point.get_segments_with_points( + user.id, + start_timestamp, + end_timestamp, + time_threshold_minutes, + distance_threshold_meters + ) + + Rails.logger.debug "OptimizedGeneratorV2: created #{segments.size} segments via SQL" + + tracks_created = 0 + + segments.each do |segment_data| + track = create_track_from_segment_v2(segment_data) + tracks_created += 1 if track + end + + Rails.logger.info "Generated #{tracks_created} tracks for user #{user.id} in optimized V2 #{mode} mode" + tracks_created + end + + private + + def create_track_from_segment_v2(segment_data) + points = segment_data[:points] + pre_calculated_distance = segment_data[:pre_calculated_distance] + + Rails.logger.debug "OptimizedGeneratorV2: processing segment with #{points.size} points" + return unless points.size >= 2 + + track = Track.new( + user_id: user.id, + start_at: Time.zone.at(points.first.timestamp), + end_at: Time.zone.at(points.last.timestamp), + original_path: build_path(points) + ) + + # V2: Use pre-calculated distance from SQL + track.distance = pre_calculated_distance.round + track.duration = calculate_duration(points) + track.avg_speed = calculate_average_speed(track.distance, track.duration) + + # Calculate elevation statistics (no DB queries needed) + elevation_stats = calculate_elevation_stats(points) + track.elevation_gain = elevation_stats[:gain] + track.elevation_loss = elevation_stats[:loss] + track.elevation_max = elevation_stats[:max] + track.elevation_min = elevation_stats[:min] + + if track.save + Point.where(id: points.map(&:id)).update_all(track_id: track.id) + track + else + Rails.logger.error "Failed to create track for user #{user.id}: #{track.errors.full_messages.join(', ')}" + nil + end + end + + def get_timestamp_range + case mode + when :bulk + if start_at && end_at + [start_at.to_i, end_at.to_i] + else + # Get full range for user + first_point = user.tracked_points.order(:timestamp).first + last_point = user.tracked_points.order(:timestamp).last + [first_point&.timestamp || 0, last_point&.timestamp || Time.current.to_i] + end + when :daily + day = start_at&.to_date || Date.current + [day.beginning_of_day.to_i, day.end_of_day.to_i] + when :incremental + # For incremental, we need all untracked points up to end_at + first_point = user.tracked_points.where(track_id: nil).order(:timestamp).first + end_timestamp = end_at ? end_at.to_i : Time.current.to_i + [first_point&.timestamp || 0, end_timestamp] + end + end + + def should_clean_tracks? + case mode + when :bulk, :daily then true + else false + end + end + + def clean_existing_tracks + case mode + when :bulk + scope = user.tracks + if start_at && end_at + scope = scope.where(start_at: start_at..end_at) + end + scope.destroy_all + when :daily + day = start_at&.to_date || Date.current + range = day.beginning_of_day..day.end_of_day + user.tracks.where(start_at: range).destroy_all + end + end + + # Helper methods (same as original) + def build_path(points) + Tracks::BuildPath.new(points).call + end + + def calculate_duration(points) + points.last.timestamp - points.first.timestamp + end + + def calculate_average_speed(distance_in_meters, duration_seconds) + return 0.0 if duration_seconds <= 0 || distance_in_meters <= 0 + + speed_mps = distance_in_meters.to_f / duration_seconds + (speed_mps * 3.6).round(2) # m/s to km/h + end + + def calculate_elevation_stats(points) + altitudes = points.map(&:altitude).compact + return { gain: 0, loss: 0, max: 0, min: 0 } if altitudes.empty? + + elevation_gain = 0 + elevation_loss = 0 + previous_altitude = altitudes.first + + altitudes[1..].each do |altitude| + diff = altitude - previous_altitude + if diff > 0 + elevation_gain += diff + else + elevation_loss += diff.abs + end + previous_altitude = altitude + end + + { + gain: elevation_gain.round, + loss: elevation_loss.round, + max: altitudes.max, + min: altitudes.min + } + end + + def distance_threshold_meters + @distance_threshold_meters ||= user.safe_settings.meters_between_routes.to_i + end + + def time_threshold_minutes + @time_threshold_minutes ||= user.safe_settings.minutes_between_routes.to_i + end +end + +# Add methods to Point class +class Point + extend OptimizedTracksV2::ClassMethods +end \ No newline at end of file diff --git a/lib/results.md b/lib/results.md new file mode 100644 index 00000000..b9d3bcc4 --- /dev/null +++ b/lib/results.md @@ -0,0 +1,122 @@ +## Original + +Generator: created track 227296 +Generated 1437 tracks for user 1 in bulk mode +โœ… Generation completed successfully + +============================================================ +๐Ÿ“Š BENCHMARK RESULTS +============================================================ +Status: โœ… SUCCESS +Execution Time: 1m 28.5s +Tracks Created: 1437 +Timeframe Coverage: 8.0% of user's total data + +๐Ÿ’พ Memory Usage: + Start: 210.9MB + End: 433.2MB + Memory Increase: +222.3MB + +๐Ÿ—„๏ธ Database Performance: + Total Queries: 115920 + Total Query Time: 50453.1ms + Average Query Time: 0.44ms + Slow Queries (>100ms): 63 + 1. 983.24ms - SELECT COUNT(*) FROM "points" WHERE "points"."user_id" = $1 AND "points"."timestamp" BETWEEN $2 A... + 2. 2826.02ms - SELECT "points".* FROM "points" WHERE "points"."user_id" = $1 AND "points"."timestamp" BETWEEN $2... + 3. 217.02ms - UPDATE "points" SET "track_id" = $1 WHERE "points"."id" IN ($2, $3, $4, $5, $6, $7, $8, $9, $10, ... + +โœ”๏ธ Post-Generation Validation: + Points in Timeframe: 111609 + Points with Tracks: 110167 + Points without Tracks: 1442 + Track Records: 1437 + โœ… Data integrity: PASS + +๐Ÿ” Performance Analysis: + Speed Rating: ๐Ÿš€ Excellent (1m 28.5s) + Memory Rating: ๐Ÿงก High (433.2MB peak) + Recommendation: Consider database optimization or smaller batch sizes + +๐Ÿ”ฎ Extrapolation for Full Dataset: + Full Dataset Size: 1,403,662 points + Scaling Factor: 12.6x + Estimated Full Time: 18m 32.8s + Estimated Full Memory: 5447.6MB + +============================================================ +๐Ÿ“‹ BENCHMARK SUMMARY +============================================================ +โฑ๏ธ Total Time: 1m 28.5s +๐Ÿ“ Points Processed: 111,609 +๐Ÿ›ค๏ธ Tracks Created: 1437 +๐Ÿš€ Processing Speed: 1261.4 points/second +๐Ÿ“… Timeframe: 2024-01-01 to 2024-12-31 +๐Ÿ‘ค User: demo@dawarich.app (ID: 1) +โœ… Status: COMPLETED + + +## Iteration 1 + +Generator: created track 244784 +Generated 1435 tracks for user 1 in optimized bulk mode +โœ… Generation completed successfully + +============================================================ +๐Ÿ“Š BENCHMARK RESULTS +============================================================ +Status: โœ… SUCCESS +Execution Time: 56.4s +Tracks Created: 1435 +Points Processed: 111,609 +Processing Speed: 1978.3 points/second +Average Points/Track: 77.8 +Timeframe Coverage: 8.0% of user's total data + +๐Ÿ’พ Memory Usage: + Start: 297.2MB + End: 407.5MB + Memory Increase: +110.3MB + +๐Ÿ—„๏ธ Database Performance: + Total Queries: 7178 + Total Query Time: 44521.33ms + Average Query Time: 6.2ms + Slow Queries (>100ms): 88 + 1. 2338.43ms - WITH points_with_gaps AS ( + SELECT + id, + timestamp, + lonlat, + LAG(lonlat) OVER (ORDE... + 2. 4156.84ms - SELECT "points".* FROM "points" WHERE "points"."id" IN (2163775, 2163776, 2163777, 2163778, 21637... + 3. 298.62ms - UPDATE "points" SET "track_id" = $1 WHERE "points"."id" IN ($2, $3, $4, $5, $6, $7, $8, $9, $10, ... + +โœ”๏ธ Post-Generation Validation: + Points in Timeframe: 111609 + Points with Tracks: 110123 + Points without Tracks: 1486 + Track Records: 1435 + โœ… Data integrity: PASS + +๐Ÿ” Performance Analysis: + Speed Rating: ๐Ÿš€ Excellent (56.4s) + Memory Rating: ๐Ÿงก High (407.5MB peak) + Recommendation: Consider database optimization or smaller batch sizes + +๐Ÿ”ฎ Extrapolation for Full Dataset: + Full Dataset Size: 1,403,662 points + Scaling Factor: 12.6x + Estimated Full Time: 11m 49.5s + Estimated Full Memory: 5125.0MB + +============================================================ +๐Ÿ“‹ BENCHMARK SUMMARY +============================================================ +โฑ๏ธ Total Time: 56.4s +๐Ÿ“ Points Processed: 111,609 +๐Ÿ›ค๏ธ Tracks Created: 1435 +๐Ÿš€ Processing Speed: 1978.3 points/second +๐Ÿ“… Timeframe: 2024-01-01 to 2024-12-31 +๐Ÿ‘ค User: demo@dawarich.app (ID: 1) +โœ… Status: COMPLETED diff --git a/lib/timestamps.rb b/lib/timestamps.rb index ea7358cc..2154a3ef 100644 --- a/lib/timestamps.rb +++ b/lib/timestamps.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true module Timestamps - def self.parse_timestamp(timestamp) begin # if the timestamp is in ISO 8601 format, try to parse it diff --git a/lib/tracks_optimization_benchmark.rb b/lib/tracks_optimization_benchmark.rb new file mode 100644 index 00000000..bac160d5 --- /dev/null +++ b/lib/tracks_optimization_benchmark.rb @@ -0,0 +1,625 @@ +# frozen_string_literal: true + +require_relative 'optimized_tracks_v1' +require_relative 'optimized_tracks_v2' + +# Benchmark script to compare three different track generation approaches: +# - Original: Individual distance queries (current implementation) +# - V1: LAG-based distance pre-calculation with Ruby segmentation +# - V2: Full SQL segmentation with PostgreSQL window functions +# +# Usage: +# rails runner lib/tracks_optimization_benchmark.rb USER_ID START_DATE END_DATE + +class TracksOptimizationBenchmark + attr_reader :user, :start_date, :end_date, :start_timestamp, :end_timestamp + + def initialize(user_id, start_date, end_date) + @user = User.find(user_id) + @start_date = Date.parse(start_date) + @end_date = Date.parse(end_date) + @start_timestamp = @start_date.beginning_of_day.to_i + @end_timestamp = @end_date.end_of_day.to_i + + puts "๐Ÿ”ฌ Track Generation Optimization Benchmark" + puts "๐Ÿ‘ค User: #{user.email} (ID: #{user.id})" + puts "๐Ÿ“… Timeframe: #{start_date} to #{end_date}" + + check_data_availability + end + + def run_all_benchmarks + results = {} + + puts "\n" + "=" * 80 + puts "๐Ÿƒ RUNNING ALL BENCHMARKS" + puts "=" * 80 + + # Test Original approach + puts "\n1๏ธโƒฃ Testing ORIGINAL approach..." + results[:original] = benchmark_original + + # Test V1 approach + puts "\n2๏ธโƒฃ Testing V1 (LAG + Ruby) approach..." + results[:v1] = benchmark_v1 + + # Test V2 approach + puts "\n3๏ธโƒฃ Testing V2 (Full SQL) approach..." + results[:v2] = benchmark_v2 + + # Compare results + puts "\n" + "=" * 80 + puts "๐Ÿ“Š PERFORMANCE COMPARISON" + puts "=" * 80 + compare_results(results) + + # Save results to files + save_results_to_files(results) + + results + end + + private + + def check_data_availability + point_count = user.tracked_points.where(timestamp: start_timestamp..end_timestamp).count + existing_tracks = user.tracks.where(start_at: Time.zone.at(start_timestamp)..Time.zone.at(end_timestamp)).count + + puts "๐Ÿ“Š Dataset: #{point_count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse} points" + puts "๐Ÿ›ค๏ธ Existing tracks: #{existing_tracks}" + + if point_count == 0 + puts "โŒ No points found in timeframe" + exit 1 + end + + if point_count > 50000 + puts "โš ๏ธ Large dataset detected. This benchmark may take a while..." + end + end + + def benchmark_original + puts " Using standard Tracks::Generator..." + + # Clean existing tracks + cleanup_tracks + + # Monitor performance + memory_start = get_memory_mb + query_monitor = QueryMonitor.new + query_monitor.start + + start_time = Time.current + + begin + generator = Tracks::Generator.new( + user, + start_at: Time.zone.at(start_timestamp), + end_at: Time.zone.at(end_timestamp), + mode: :bulk + ) + tracks_created = generator.call + success = true + rescue => e + success = false + error = e.message + tracks_created = 0 + end + + end_time = Time.current + memory_end = get_memory_mb + query_monitor.stop + + execution_time = end_time - start_time + + result = { + approach: "Original", + success: success, + error: error, + execution_time: execution_time, + tracks_created: tracks_created, + memory_increase: memory_end - memory_start, + query_count: query_monitor.query_count, + query_time_ms: query_monitor.total_time_ms + } + + print_result(result) + result + end + + def benchmark_v1 + puts " Using V1: LAG + Ruby segmentation..." + + # Clean existing tracks + cleanup_tracks + + # For V1, we need to modify the existing generator to use our optimized methods + # This is a simplified test - in practice we'd modify the actual generator + + memory_start = get_memory_mb + query_monitor = QueryMonitor.new + query_monitor.start + + start_time = Time.current + + begin + # Load points + points = user.tracked_points + .where(timestamp: start_timestamp..end_timestamp) + .order(:timestamp) + + # V1: Use optimized segmentation with pre-calculated distances + if points.size > 1 + distance_data = Point.calculate_all_consecutive_distances(points) + else + distance_data = {} + end + + # Segment using V1 approach (simplified for benchmark) + segments = split_points_with_precalculated_distances(points, distance_data) + + tracks_created = 0 + segments.each do |segment| + if segment.size >= 2 + track = create_track_v1(segment) + tracks_created += 1 if track + end + end + + success = true + rescue => e + success = false + error = e.message + tracks_created = 0 + end + + end_time = Time.current + memory_end = get_memory_mb + query_monitor.stop + + execution_time = end_time - start_time + + result = { + approach: "V1 (LAG + Ruby)", + success: success, + error: error, + execution_time: execution_time, + tracks_created: tracks_created, + memory_increase: memory_end - memory_start, + query_count: query_monitor.query_count, + query_time_ms: query_monitor.total_time_ms + } + + print_result(result) + result + end + + def benchmark_v2 + puts " Using V2: Full SQL segmentation..." + + cleanup_tracks + + memory_start = get_memory_mb + query_monitor = QueryMonitor.new + query_monitor.start + + start_time = Time.current + + begin + generator = OptimizedTracksGeneratorV2.new( + user, + start_at: Time.zone.at(start_timestamp), + end_at: Time.zone.at(end_timestamp), + mode: :bulk + ) + tracks_created = generator.call + success = true + rescue => e + success = false + error = e.message + tracks_created = 0 + end + + end_time = Time.current + memory_end = get_memory_mb + query_monitor.stop + + execution_time = end_time - start_time + + result = { + approach: "V2 (Full SQL)", + success: success, + error: error, + execution_time: execution_time, + tracks_created: tracks_created, + memory_increase: memory_end - memory_start, + query_count: query_monitor.query_count, + query_time_ms: query_monitor.total_time_ms + } + + print_result(result) + result + end + + def split_points_with_precalculated_distances(points, distance_data) + return [] if points.empty? + + segments = [] + current_segment = [] + + points.each do |point| + if current_segment.empty? + current_segment = [point] + elsif should_break_segment_v1?(point, current_segment.last, distance_data) + segments << current_segment if current_segment.size >= 2 + current_segment = [point] + else + current_segment << point + end + end + + segments << current_segment if current_segment.size >= 2 + segments + end + + def should_break_segment_v1?(current_point, previous_point, distance_data) + return false if previous_point.nil? + + point_data = distance_data[current_point.id] + return false unless point_data + + time_threshold_seconds = user.safe_settings.minutes_between_routes.to_i * 60 + distance_threshold_meters = user.safe_settings.meters_between_routes.to_i + + return true if point_data[:time_diff_seconds] > time_threshold_seconds + return true if point_data[:distance_meters] > distance_threshold_meters + + false + end + + def create_track_v1(points) + return nil if points.size < 2 + + track = Track.new( + user_id: user.id, + start_at: Time.zone.at(points.first.timestamp), + end_at: Time.zone.at(points.last.timestamp), + original_path: build_path(points) + ) + + # Use LAG-based distance calculation + track.distance = Point.total_distance_lag(points, :m).round + track.duration = points.last.timestamp - points.first.timestamp + track.avg_speed = calculate_average_speed(track.distance, track.duration) + + # Elevation stats (same as original) + elevation_stats = calculate_elevation_stats(points) + track.elevation_gain = elevation_stats[:gain] + track.elevation_loss = elevation_stats[:loss] + track.elevation_max = elevation_stats[:max] + track.elevation_min = elevation_stats[:min] + + if track.save + Point.where(id: points.map(&:id)).update_all(track_id: track.id) + track + else + nil + end + end + + def cleanup_tracks + user.tracks.where(start_at: Time.zone.at(start_timestamp)..Time.zone.at(end_timestamp)).destroy_all + end + + def print_result(result) + status = result[:success] ? "โœ… SUCCESS" : "โŒ FAILED" + puts " #{status}" + puts " โฑ๏ธ Time: #{format_duration(result[:execution_time])}" + puts " ๐Ÿ›ค๏ธ Tracks: #{result[:tracks_created]}" + puts " ๐Ÿ’พ Memory: +#{result[:memory_increase].round(1)}MB" + puts " ๐Ÿ—„๏ธ Queries: #{result[:query_count]} (#{result[:query_time_ms].round(1)}ms)" + puts " โŒ Error: #{result[:error]}" if result[:error] + end + + def compare_results(results) + return unless results[:original] && results[:v1] && results[:v2] + + puts sprintf("%-20s %-10s %-12s %-10s %-15s %-10s", + "Approach", "Time", "Tracks", "Memory", "Queries", "Query Time") + puts "-" * 80 + + [:original, :v1, :v2].each do |approach| + result = results[approach] + next unless result[:success] + + puts sprintf("%-20s %-10s %-12s %-10s %-15s %-10s", + result[:approach], + format_duration(result[:execution_time]), + result[:tracks_created], + "+#{result[:memory_increase].round(1)}MB", + result[:query_count], + "#{result[:query_time_ms].round(1)}ms") + end + + # Calculate improvements + if results[:original][:success] + original_time = results[:original][:execution_time] + original_queries = results[:original][:query_count] + + puts "\n๐Ÿš€ Performance Improvements vs Original:" + + if results[:v1][:success] + v1_speedup = (original_time / results[:v1][:execution_time]).round(2) + v1_query_reduction = ((original_queries - results[:v1][:query_count]) / original_queries.to_f * 100).round(1) + puts " V1: #{v1_speedup}x faster, #{v1_query_reduction}% fewer queries" + end + + if results[:v2][:success] + v2_speedup = (original_time / results[:v2][:execution_time]).round(2) + v2_query_reduction = ((original_queries - results[:v2][:query_count]) / original_queries.to_f * 100).round(1) + puts " V2: #{v2_speedup}x faster, #{v2_query_reduction}% fewer queries" + end + end + end + + def save_results_to_files(results) + timestamp = Time.current.strftime('%Y%m%d_%H%M%S') + point_count = user.tracked_points.where(timestamp: start_timestamp..end_timestamp).count + + # Create detailed results structure + benchmark_data = { + meta: { + timestamp: Time.current.iso8601, + user_id: user.id, + user_email: user.email, + start_date: start_date.strftime('%Y-%m-%d'), + end_date: end_date.strftime('%Y-%m-%d'), + point_count: point_count, + ruby_version: RUBY_VERSION, + rails_version: Rails.version, + database_adapter: ActiveRecord::Base.connection.adapter_name + }, + results: results, + performance_analysis: analyze_performance_data(results) + } + + # Save JSON results for programmatic analysis + json_filename = "tracks_optimization_#{timestamp}.json" + json_path = Rails.root.join('lib', json_filename) + File.write(json_path, JSON.pretty_generate(benchmark_data)) + + # Save human-readable markdown report + md_filename = "tracks_optimization_#{timestamp}.md" + md_path = Rails.root.join('lib', md_filename) + File.write(md_path, generate_markdown_report(benchmark_data)) + + puts "\n๐Ÿ’พ Results saved:" + puts " ๐Ÿ“„ JSON: #{json_path}" + puts " ๐Ÿ“ Report: #{md_path}" + end + + def analyze_performance_data(results) + return {} unless results[:original] && results[:original][:success] + + original = results[:original] + analysis = { + baseline: { + execution_time: original[:execution_time], + query_count: original[:query_count], + memory_usage: original[:memory_increase] + } + } + + [:v1, :v2].each do |version| + next unless results[version] && results[version][:success] + + result = results[version] + analysis[version] = { + speedup_factor: (original[:execution_time] / result[:execution_time]).round(2), + query_reduction_percent: ((original[:query_count] - result[:query_count]) / original[:query_count].to_f * 100).round(1), + memory_change_percent: ((result[:memory_increase] - original[:memory_increase]) / original[:memory_increase].to_f * 100).round(1), + execution_time_saved: (original[:execution_time] - result[:execution_time]).round(2) + } + end + + analysis + end + + def generate_markdown_report(benchmark_data) + meta = benchmark_data[:meta] + results = benchmark_data[:results] + analysis = benchmark_data[:performance_analysis] + + report = <<~MD + # Tracks Generation Optimization Benchmark Report + + **Generated:** #{meta[:timestamp]} + **User:** #{meta[:user_email]} (ID: #{meta[:user_id]}) + **Timeframe:** #{meta[:start_date]} to #{meta[:end_date]} + **Dataset:** #{meta[:point_count].to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse} points + **Environment:** Ruby #{meta[:ruby_version]}, Rails #{meta[:rails_version]}, #{meta[:database_adapter]} + + ## Summary + + This benchmark compares three approaches to track generation: + - **Original:** Individual PostGIS queries for each distance calculation + - **V1 (LAG + Ruby):** PostgreSQL LAG for batch distance calculation, Ruby segmentation + - **V2 (Full SQL):** Complete segmentation using PostgreSQL window functions + + ## Results + + | Approach | Status | Time | Tracks | Memory | Queries | Query Time | + |----------|--------|------|--------|--------|---------|------------| + MD + + [:original, :v1, :v2].each do |approach| + next unless results[approach] + + result = results[approach] + status = result[:success] ? "โœ…" : "โŒ" + + report += "| #{result[:approach]} | #{status} | #{format_duration(result[:execution_time])} | #{result[:tracks_created]} | +#{result[:memory_increase].round(1)}MB | #{result[:query_count]} | #{result[:query_time_ms].round(1)}ms |\n" + end + + if analysis[:v1] || analysis[:v2] + report += "\n## Performance Improvements\n\n" + + if analysis[:v1] + v1 = analysis[:v1] + report += "### V1 (LAG + Ruby) vs Original\n" + report += "- **#{v1[:speedup_factor]}x faster** execution\n" + report += "- **#{v1[:query_reduction_percent]}% fewer** database queries\n" + report += "- **#{format_duration(v1[:execution_time_saved])} time saved**\n" + report += "- Memory change: #{v1[:memory_change_percent] > 0 ? '+' : ''}#{v1[:memory_change_percent]}%\n\n" + end + + if analysis[:v2] + v2 = analysis[:v2] + report += "### V2 (Full SQL) vs Original\n" + report += "- **#{v2[:speedup_factor]}x faster** execution\n" + report += "- **#{v2[:query_reduction_percent]}% fewer** database queries\n" + report += "- **#{format_duration(v2[:execution_time_saved])} time saved**\n" + report += "- Memory change: #{v2[:memory_change_percent] > 0 ? '+' : ''}#{v2[:memory_change_percent]}%\n\n" + end + end + + # Add detailed results + report += "## Detailed Results\n\n" + + [:original, :v1, :v2].each do |approach| + next unless results[approach] + + result = results[approach] + report += "### #{result[:approach]}\n\n" + + if result[:success] + report += "- โœ… **Status:** Success\n" + report += "- โฑ๏ธ **Execution Time:** #{format_duration(result[:execution_time])}\n" + report += "- ๐Ÿ›ค๏ธ **Tracks Created:** #{result[:tracks_created]}\n" + report += "- ๐Ÿ’พ **Memory Increase:** +#{result[:memory_increase].round(1)}MB\n" + report += "- ๐Ÿ—„๏ธ **Database Queries:** #{result[:query_count]}\n" + report += "- โšก **Query Time:** #{result[:query_time_ms].round(1)}ms\n" + + if result[:query_count] > 0 + avg_query_time = (result[:query_time_ms] / result[:query_count]).round(2) + report += "- ๐Ÿ“Š **Average Query Time:** #{avg_query_time}ms\n" + end + else + report += "- โŒ **Status:** Failed\n" + report += "- ๐Ÿšจ **Error:** #{result[:error]}\n" + end + + report += "\n" + end + + report += "## Recommendations\n\n" + + if analysis[:v2] && analysis[:v2][:speedup_factor] > analysis.dig(:v1, :speedup_factor).to_f + report += "๐Ÿš€ **V2 (Full SQL)** shows the best performance with #{analysis[:v2][:speedup_factor]}x speedup.\n\n" + report += "Benefits:\n" + report += "- Minimal database queries (#{results.dig(:v2, :query_count)} vs #{results.dig(:original, :query_count)})\n" + report += "- Fastest execution time\n" + report += "- Leverages PostgreSQL's optimized window functions\n\n" + elsif analysis[:v1] + report += "๐Ÿƒ **V1 (LAG + Ruby)** provides good performance improvements with #{analysis[:v1][:speedup_factor]}x speedup.\n\n" + end + + if results[:original] && results[:original][:query_count] > 50000 + report += "โš ๏ธ **Current implementation** makes excessive database queries (#{results[:original][:query_count]}) for this dataset size.\n\n" + end + + report += "---\n*Generated by TracksOptimizationBenchmark*" + + report + end + + # Helper methods + def get_memory_mb + `ps -o rss= -p #{Process.pid}`.to_i / 1024.0 + end + + def format_duration(seconds) + if seconds < 60 + "#{seconds.round(1)}s" + else + minutes = (seconds / 60).floor + remaining_seconds = (seconds % 60).round(1) + "#{minutes}m #{remaining_seconds}s" + end + end + + def build_path(points) + Tracks::BuildPath.new(points).call + end + + def calculate_average_speed(distance_in_meters, duration_seconds) + return 0.0 if duration_seconds <= 0 || distance_in_meters <= 0 + speed_mps = distance_in_meters.to_f / duration_seconds + (speed_mps * 3.6).round(2) + end + + def calculate_elevation_stats(points) + altitudes = points.map(&:altitude).compact + return { gain: 0, loss: 0, max: 0, min: 0 } if altitudes.empty? + + elevation_gain = 0 + elevation_loss = 0 + previous_altitude = altitudes.first + + altitudes[1..].each do |altitude| + diff = altitude - previous_altitude + if diff > 0 + elevation_gain += diff + else + elevation_loss += diff.abs + end + previous_altitude = altitude + end + + { gain: elevation_gain.round, loss: elevation_loss.round, max: altitudes.max, min: altitudes.min } + end +end + +# Simple query monitor for this benchmark +class QueryMonitor + attr_reader :query_count, :total_time_ms + + def initialize + @query_count = 0 + @total_time_ms = 0 + end + + def start + @subscription = ActiveSupport::Notifications.subscribe('sql.active_record') do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + next if event.payload[:name]&.include?('SCHEMA') + + @query_count += 1 + @total_time_ms += event.duration + end + end + + def stop + ActiveSupport::Notifications.unsubscribe(@subscription) if @subscription + end +end + +# Command line interface +if __FILE__ == $0 + if ARGV.length < 3 + puts "Usage: rails runner #{__FILE__} USER_ID START_DATE END_DATE" + puts "" + puts "Example:" + puts " rails runner #{__FILE__} 1 2024-01-01 2024-01-31" + exit 1 + end + + user_id = ARGV[0].to_i + start_date = ARGV[1] + end_date = ARGV[2] + + benchmark = TracksOptimizationBenchmark.new(user_id, start_date, end_date) + results = benchmark.run_all_benchmarks + + puts "\n๐ŸŽ‰ Benchmark completed! Check results above." +end \ No newline at end of file diff --git a/tracks_performance_optimization_options.md b/tracks_performance_optimization_options.md new file mode 100644 index 00000000..8f7c6601 --- /dev/null +++ b/tracks_performance_optimization_options.md @@ -0,0 +1,235 @@ +# Tracks Feature Performance Optimization Options + +## Current State Analysis + +### Performance Characteristics +- **Time Complexity:** O(n log n) where n = number of GPS points +- **Memory Usage:** Loads entire dataset into memory (~200-400 bytes per point) +- **Processing Mode:** Single-threaded, sequential segmentation +- **Database Load:** Multiple PostGIS distance calculations per point pair + +### Performance Estimates (Bulk Mode) +| Points | Processing Time | Memory Usage | Database Load | +|--------|----------------|--------------|---------------| +| 10K | 30-60 seconds | ~50 MB | Low | +| 100K | 5-15 minutes | ~200 MB | Medium | +| 1M+ | 30-90 minutes | 400+ MB | High | + +### Current Bottlenecks +1. **Memory constraints** - Loading all points at once +2. **PostGIS distance calculations** - Sequential, not optimized +3. **Single-threaded processing** - No parallelization +4. **No progress indication** - Users can't track long-running operations + +--- + +## Optimization Options + +### Option 1: Enhanced Time-Based Batching +**Complexity:** Low | **Impact:** High | **Risk:** Low + +#### Implementation +- Extend existing `:daily` mode with configurable batch sizes +- Add 1-point overlap between batches to maintain segmentation accuracy +- Implement batch-aware progress reporting + +#### Benefits +- **Memory reduction:** 90%+ reduction (from 400MB to ~40MB for 1M points) +- **Better UX:** Progress indication and cancellation support +- **Incremental processing:** Can resume interrupted operations +- **Lower DB pressure:** Smaller query result sets + +#### Changes Required +```ruby +# Enhanced generator with configurable batching +Tracks::Generator.new( + user, + mode: :batched, + batch_size: 24.hours, + enable_overlap: true +).call +``` + +#### Edge Cases to Handle +- Tracks spanning batch boundaries (solved with overlap) +- Midnight-crossing tracks in daily mode +- Deduplication of overlapping segments + +--- + +### Option 2: Spatial Indexing Optimization +**Complexity:** Medium | **Impact:** Medium | **Risk:** Low + +#### Implementation +- Replace individual PostGIS calls with batch distance calculations +- Implement spatial clustering for nearby points before segmentation +- Use PostGIS window functions for distance calculations + +#### Benefits +- **Faster distance calculations:** Batch operations vs individual queries +- **Reduced DB round-trips:** Single query for multiple distance calculations +- **Better index utilization:** Leverage existing spatial indexes + +#### Changes Required +```sql +-- Batch distance calculation approach +WITH point_distances AS ( + SELECT + id, + timestamp, + ST_Distance( + lonlat::geography, + LAG(lonlat::geography) OVER (ORDER BY timestamp) + ) as distance_to_previous + FROM points + WHERE user_id = ? + ORDER BY timestamp +) +SELECT * FROM point_distances WHERE distance_to_previous > ? +``` + +--- + +### Option 3: Parallel Processing with Worker Pools +**Complexity:** High | **Impact:** High | **Risk:** Medium + +#### Implementation +- Split large datasets into non-overlapping time ranges +- Process multiple batches in parallel using Sidekiq workers +- Implement coordination mechanism for dependent segments + +#### Benefits +- **Faster processing:** Utilize multiple CPU cores +- **Scalable:** Performance scales with worker capacity +- **Background processing:** Non-blocking for users + +#### Challenges +- **Complex coordination:** Managing dependencies between batches +- **Resource competition:** Multiple workers accessing same user's data +- **Error handling:** Partial failure scenarios + +#### Architecture +```ruby +# Parallel processing coordinator +class Tracks::ParallelGenerator + def call + time_ranges = split_into_parallel_ranges + + time_ranges.map do |range| + Tracks::BatchProcessorJob.perform_later(user_id, range) + end + end +end +``` + +--- + +### Option 4: Incremental Algorithm Enhancement +**Complexity:** Medium | **Impact:** Medium | **Risk:** Medium + +#### Implementation +- Enhance existing `:incremental` mode with smarter buffering +- Implement sliding window approach for active track detection +- Add automatic track finalization based on time gaps + +#### Benefits +- **Real-time processing:** Process points as they arrive +- **Lower memory footprint:** Only active segments in memory +- **Better for live tracking:** Immediate track updates + +#### Current Limitations +- Existing incremental mode processes untracked points only +- No automatic track finalization +- Limited to single active track per user + +--- + +### Option 5: Database-Level Optimization +**Complexity:** Low-Medium | **Impact:** Medium | **Risk:** Low + +#### Implementation +- Add composite indexes for common query patterns +- Implement materialized views for expensive calculations +- Use database-level segmentation logic + +#### Benefits +- **Faster queries:** Better index utilization +- **Reduced Ruby processing:** Move logic to database +- **Consistent performance:** Database optimizations benefit all modes + +#### Proposed Indexes +```sql +-- Optimized for bulk processing +CREATE INDEX CONCURRENTLY idx_points_user_timestamp_track +ON points(user_id, timestamp) WHERE track_id IS NULL; + +-- Optimized for incremental processing +CREATE INDEX CONCURRENTLY idx_points_untracked_timestamp +ON points(timestamp) WHERE track_id IS NULL; +``` + +--- + +## Recommended Implementation Strategy + +### Phase 1: Quick Wins (Week 1-2) +1. **Implement Enhanced Time-Based Batching** (Option 1) + - Extend existing daily mode with overlap + - Add progress reporting + - Configurable batch sizes + +### Phase 2: Database Optimization (Week 3) +2. **Add Database-Level Optimizations** (Option 5) + - Create optimized indexes + - Implement batch distance calculations + +### Phase 3: Advanced Features (Week 4-6) +3. **Spatial Indexing Optimization** (Option 2) + - Replace individual distance calculations + - Implement spatial clustering + +### Phase 4: Future Enhancements +4. **Parallel Processing** (Option 3) - Consider for v2 +5. **Incremental Enhancement** (Option 4) - For real-time features + +--- + +## Risk Assessment + +### Low Risk +- **Time-based batching:** Builds on existing daily mode +- **Database indexes:** Standard optimization technique +- **Progress reporting:** UI enhancement only + +### Medium Risk +- **Spatial optimization:** Requires careful testing of distance calculations +- **Incremental enhancement:** Changes to existing algorithm logic + +### High Risk +- **Parallel processing:** Complex coordination, potential race conditions +- **Major algorithm changes:** Could introduce segmentation bugs + +--- + +## Success Metrics + +### Performance Targets +- **Memory usage:** < 100MB for datasets up to 1M points +- **Processing time:** < 10 minutes for 1M points +- **User experience:** Progress indication and cancellation + +### Monitoring Points +- Database query performance +- Memory consumption during processing +- User-reported processing times +- Track generation accuracy (no regression) + +--- + +## Next Steps + +1. **Choose initial approach** based on urgency and resources +2. **Create feature branch** for selected optimization +3. **Implement comprehensive testing** including edge cases +4. **Monitor performance** in staging environment +5. **Gradual rollout** with feature flags \ No newline at end of file