Spaces:
Running
Running
Mark Duppenthaler
commited on
Commit
·
7f6ef8f
1
Parent(s):
ca345b7
Updated table. No more individual rows, separate tabs for leaderboard type, export tables
Browse files- frontend/dist/assets/index-BWZpYvtq.css +0 -1
- frontend/dist/assets/index-BbusHoyK.css +1 -0
- frontend/dist/assets/{index-D2ksG3qQ.js → index-GljWyhYi.js} +0 -0
- frontend/dist/index.html +2 -2
- frontend/package-lock.json +10 -0
- frontend/package.json +2 -1
- frontend/src/App.tsx +39 -52
- frontend/src/components/IndependentMetricsTable.tsx +0 -69
- frontend/src/components/LeaderboardPage.tsx +17 -7
- frontend/src/components/LeaderboardTable.tsx +128 -240
- frontend/src/components/LeaderboardTabs.tsx +0 -0
- frontend/src/components/QualityMetricsTable.tsx +193 -0
- tests/README.md +64 -0
- tests/__init__.py +2 -0
- tests/conftest.py +30 -0
- tests/test_app.py +249 -0
frontend/dist/assets/index-BWZpYvtq.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-700:oklch(37.3% .034 259.733);--color-black:#000;--spacing:.25rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--ease-in:cubic-bezier(.4,0,1,1);--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}}:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@property --radialprogress{syntax: "<percentage>"; inherits: true; initial-value: 0%;}:root{scrollbar-color:currentColor #0000}@supports (color:color-mix(in lab,red,red)){:root{scrollbar-color:color-mix(in oklch,currentColor 35%,#0000)#0000}}:root{--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E")}:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not([class*=drawer-open])>.drawer-toggle:checked){overflow:hidden}:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){scrollbar-gutter:stable;background-image:linear-gradient(var(--color-base-100),var(--color-base-100));--root-bg:var(--color-base-100)}@supports (color:color-mix(in lab,red,red)){:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){--root-bg:color-mix(in srgb,var(--color-base-100),oklch(0% 0 0) 40%)}}:where(.modal[open],.modal-open,.modal-toggle:checked+.modal):not(.modal-start,.modal-end){scrollbar-gutter:stable}:root,[data-theme]{background-color:var(--root-bg,var(--color-base-100));color:var(--color-base-content)}}@layer components;@layer utilities{.diff{webkit-user-select:none;-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.diff:focus-visible,.diff:has(.diff-item-1:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.tab{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;text-align:center;webkit-user-select:none;-webkit-user-select:none;user-select:none;flex-wrap:wrap;justify-content:center;align-items:center;display:inline-flex;position:relative}@media (hover:hover){.tab:hover{color:var(--color-base-content)}}.tab{--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));order:var(--tab-order);height:var(--tab-height);border-color:#0000;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem}.tab:is(input[type=radio]){min-width:fit-content}.tab:is(input[type=radio]):after{content:attr(aria-label)}.tab:is(label){position:relative}.tab:is(label) input{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;position:absolute;top:0;right:0;bottom:0;left:0}:is(.tab:checked,.tab:is(label:has(:checked)),.tab:is(.tab-active,[aria-selected=true]))+.tab-content{height:calc(100% - var(--tab-height) + var(--border));display:block}.tab:not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true]){color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.tab:not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true]){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}}.tab:not(input):empty{cursor:default;flex-grow:1}.tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.tab:focus{outline-offset:2px;outline:2px solid #0000}}.tab:focus-visible,.tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.tab[disabled]{pointer-events:none;opacity:.4}.collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem)*6);background-color:currentColor;display:inline-block;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.pointer-events-none{pointer-events:none}.collapse:not(td,tr,colgroup){visibility:visible}.collapse{border-radius:var(--radius-box,1rem);isolation:isolate;grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.collapse>input:is([type=checkbox],[type=radio]){-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;z-index:1;grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.collapse:is([open],:focus:not(.collapse-close)),.collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.collapse:is([open],:focus:not(.collapse-close))>.collapse-content,.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.collapse:focus-visible,.collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.collapse:not(.collapse-close)>input[type=checkbox],.collapse:not(.collapse-close)>input[type=radio]:not(:checked),.collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.collapse:focus:not(.collapse-close,.collapse[open])>.collapse-title{cursor:unset}.collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content),.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.collapse[open].collapse-arrow>.collapse-title:after,.collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after,.collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse[open].collapse-plus>.collapse-title:after,.collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after,.collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.collapse:is(details){width:100%}.collapse:is(details) summary{display:block;position:relative}.collapse:is(details) summary::-webkit-details-marker{display:none}.collapse:is(details) summary{outline:none}.collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:visibility .2s,padding .2s ease-out,background-color .2s ease-out}.collapse{visibility:collapse}.visible{visibility:visible}.toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;vertical-align:middle;webkit-user-select:none;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;display:inline-grid;position:relative;box-shadow:inset 0 1px}@supports (color:color-mix(in lab,red,red)){.toggle{box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000) inset}}.toggle{--input-color:var(--color-base-content);transition:color .3s,grid-template-columns .2s}@supports (color:color-mix(in lab,red,red)){.toggle{--input-color:color-mix(in oklab,var(--color-base-content)50%,#0000)}}.toggle{--toggle-p:calc(var(--size)*.125);--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size)}.toggle>*{z-index:1;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.toggle>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.toggle>:focus{outline-offset:2px;outline:2px solid #0000}}.toggle>:nth-child(2){color:var(--color-base-100);rotate:none}.toggle>:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor;background-color:currentColor;grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@supports (color:color-mix(in lab,red,red)){.toggle:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000)}}.toggle:before{background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise)}@media (forced-colors:active){.toggle:before{outline-style:var(--tw-outline-style);outline-offset:-1px;outline-width:1px}}@media print{.toggle:before{outline-offset:-1rem;outline:.25rem solid}}.toggle:focus-visible,.toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{background-color:currentColor}@starting-style{:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{opacity:0}}.toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.toggle:disabled{cursor:not-allowed;opacity:.3}.toggle:disabled:before{border:var(--border)solid currentColor;background-color:#0000}.input{cursor:text;border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);touch-action:manipulation;border-color:var(--input-color);box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab,red,red)){.input{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.input{--size:calc(var(--size-field,.25rem)*10);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.input{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.input:where(input){display:inline-flex}.input :where(input){-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none;width:100%;height:100%;display:inline-flex}.input :where(input):focus,.input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus,.input :where(input):focus-within{outline-offset:2px;outline:2px solid #0000}}.input :where(input[type=url]),.input :where(input[type=email]){direction:ltr}.input :where(input[type=date]){display:inline-block}.input:focus,.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.input:focus,.input:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.input:focus,.input:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}.input:has(>input[disabled]),.input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.input:has(>input[disabled]),.input:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]){box-shadow:none}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.table:where(:dir(rtl),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){:is(.table tr.row-hover,.table tr.row-hover:nth-child(2n)):hover{background-color:var(--color-base-200)}}.table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.table :where(thead,tfoot){white-space:nowrap;color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(thead,tfoot){color:color-mix(in oklab,var(--color-base-content)60%,transparent)}}.table :where(thead,tfoot){font-size:.875rem;font-weight:600}.table :where(tfoot){border-top:var(--border)solid var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,#0000)}}.table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,#0000)}}.steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.steps .step>.step-icon,.steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.steps .step-neutral+.step-neutral:before,.steps .step-neutral:after,.steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-primary+.step-primary:before,.steps .step-primary:after,.steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-secondary+.step-secondary:before,.steps .step-secondary:after,.steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-accent+.step-accent:before,.steps .step-accent:after,.steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-info+.step-info:before,.steps .step-info:after,.steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-success+.step-success:before,.steps .step-success:after,.steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-warning+.step-warning:before,.steps .step-warning:after,.steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-error+.step-error:before,.steps .step-error:after,.steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.range{-webkit-appearance:none;-moz-appearance:none;appearance:none;webkit-appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:currentColor}@supports (color:color-mix(in lab,red,red)){.range{--range-bg:color-mix(in oklab,currentColor 10%,#0000)}}.range{cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:#0000;border:none;overflow:hidden}[dir=rtl] .range{--range-dir:-1}.range:focus{outline:none}.range:focus-visible{outline-offset:2px;outline:2px solid}.range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.range::-webkit-slider-runnable-track{border:1px solid}.range::-moz-range-track{border:1px solid}}.range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;-webkit-appearance:none;-moz-appearance:none;appearance:none;webkit-appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}@supports (color:color-mix(in lab,red,red)){.range::-webkit-slider-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))}}.range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}.range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}@supports (color:color-mix(in lab,red,red)){.range::-moz-range-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))}}.range:disabled{cursor:not-allowed;opacity:.3}.range\!{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;webkit-appearance:none!important;--range-thumb:var(--color-base-100)!important;--range-thumb-size:calc(var(--size-selector,.25rem)*6)!important;--range-progress:currentColor!important;--range-fill:1!important;--range-p:.25rem!important;--range-bg:currentColor!important}@supports (color:color-mix(in lab,red,red)){.range\!{--range-bg:color-mix(in oklab,currentColor 10%,#0000)!important}}.range\!{cursor:pointer!important;vertical-align:middle!important;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector))!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;width:clamp(3rem,20rem,100%)!important;height:var(--range-thumb-size)!important;background-color:#0000!important;border:none!important;overflow:hidden!important}[dir=rtl] .range\!{--range-dir:-1!important}.range\!:focus{outline:none!important}.range\!:focus-visible{outline-offset:2px!important;outline:2px solid!important}.range\!::-webkit-slider-runnable-track{background-color:var(--range-bg)!important;border-radius:var(--radius-selector)!important;width:100%!important;height:calc(var(--range-thumb-size)*.5)!important}@media (forced-colors:active){.range\!::-webkit-slider-runnable-track{border:1px solid!important}.range\!::-moz-range-track{border:1px solid!important}}.range\!::-webkit-slider-thumb{box-sizing:border-box!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;height:var(--range-thumb-size)!important;width:var(--range-thumb-size)!important;border:var(--range-p)solid!important;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;webkit-appearance:none!important;color:var(--range-progress)!important;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important;background-color:currentColor!important;position:relative!important;top:50%!important;transform:translateY(-50%)!important}@supports (color:color-mix(in lab,red,red)){.range\!::-webkit-slider-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important}}.range\!::-moz-range-track{background-color:var(--range-bg)!important;border-radius:var(--radius-selector)!important;width:100%!important;height:calc(var(--range-thumb-size)*.5)!important}.range\!::-moz-range-thumb{box-sizing:border-box!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;height:var(--range-thumb-size)!important;width:var(--range-thumb-size)!important;border:var(--range-p)solid!important;color:var(--range-progress)!important;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important;background-color:currentColor!important;position:relative!important;top:50%!important}@supports (color:color-mix(in lab,red,red)){.range\!::-moz-range-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important}}.range\!:disabled{cursor:not-allowed!important;opacity:.3!important}.tabs-border .tab{--tab-border-color:#0000 #0000 var(--tab-border-color)#0000;border-radius:var(--radius-field);position:relative}.tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}:is(.tabs-border .tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled,[disabled]),.tabs-border .tab:is(input:checked),.tabs-border .tab:is(label:has(:checked))):before{--tab-border-color:currentColor;border-top:3px solid}.select{border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);touch-action:manipulation;text-overflow:ellipsis;box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;background-image:linear-gradient(45deg,#0000 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,#0000 50%);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;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab,red,red)){.select{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.select{border-color:var(--input-color);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.select{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.select{--size:calc(var(--size-field,.25rem)*10)}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.select select:focus,.select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.select select:focus,.select select:focus-within{outline-offset:2px;outline:2px solid #0000}}.select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.select:focus,.select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.select:focus,.select:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.select:focus,.select:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}.select:has(>select[disabled]),.select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.select:has(>select[disabled]),.select:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.timeline{display:flex;position:relative}.timeline>li{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));flex-shrink:0;align-items:center;display:grid;position:relative}.timeline>li>hr{border:none;width:100%}.timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.timeline>li>hr{border:.1px solid var(--color-base-300)}}.timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.timeline:has(.timeline-middle hr):last-child,.timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.collapse-title{grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.checkbox{border:var(--border)solid var(--input-color,var(--color-base-content))}@supports (color:color-mix(in lab,red,red)){.checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,#0000))}}.checkbox{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 0 #0000 inset,0 0 #0000;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;display:inline-block;position:relative}.checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0 3px oklch(100% 0 0/calc(var(--depth)*.1)) inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.checkbox:checked,.checkbox[aria-checked=true]{background-color:var(--input-color,#0000);box-shadow:0 0 #0000 inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}:is(.checkbox:checked,.checkbox[aria-checked=true]):before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){:is(.checkbox:checked,.checkbox[aria-checked=true]):before{--tw-content:"✔︎";clip-path:none;background-color:#0000;rotate:none}}@media print{:is(.checkbox:checked,.checkbox[aria-checked=true]):before{--tw-content:"✔︎";clip-path:none;background-color:#0000;rotate:none}}.checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.checkbox:disabled{cursor:not-allowed;opacity:.2}.radio{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;display:inline-block;position:relative}@supports (color:color-mix(in lab,red,red)){.radio{border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,#0000))}}.radio{box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1)) inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor)}.radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.radio:focus-visible{outline:2px solid}.radio:checked,.radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}:is(.radio:checked,.radio[aria-checked=true]):before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){:is(.radio:checked,.radio[aria-checked=true]):before{outline-style:var(--tw-outline-style);outline-offset:-1px;outline-width:1px}}@media print{:is(.radio:checked,.radio[aria-checked=true]):before{outline-offset:-1rem;outline:.25rem solid}}.radio:disabled{cursor:not-allowed;opacity:.2}.stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-box);background-color:currentColor;width:100%;height:.5rem;position:relative;overflow:hidden}@supports (color:color-mix(in lab,red,red)){.progress{background-color:color-mix(in oklab,currentColor 20%,transparent)}}.progress{color:var(--color-base-content)}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:#0000;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:#0000}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-12{top:calc(var(--spacing)*12)}.right-2{right:calc(var(--spacing)*2)}.left-0{left:calc(var(--spacing)*0)}.textarea{border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;touch-action:manipulation;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}@supports (color:color-mix(in lab,red,red)){.textarea{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.textarea{--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.textarea{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.textarea textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none}.textarea textarea:focus,.textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.textarea textarea:focus,.textarea textarea:focus-within{outline-offset:2px;outline:2px solid #0000}}.textarea:focus,.textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.textarea:focus,.textarea:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.textarea:focus,.textarea:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){box-shadow:none}.textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.stack>*{width:100%;height:100%}.stack>:nth-child(n+2){opacity:.7;width:100%}.stack>:nth-child(2){z-index:2;opacity:.9}.stack>:first-child{z-index:3;width:100%}:is(.stack,.stack.stack-bottom)>*{grid-area:3/3/6/4}:is(.stack,.stack.stack-bottom)>:nth-child(2){grid-area:2/2/5/5}:is(.stack,.stack.stack-bottom)>:first-child{grid-area:1/1/4/6}.stack.stack-top>*{grid-area:1/3/4/4}.stack.stack-top>:nth-child(2){grid-area:2/2/5/5}.stack.stack-top>:first-child{grid-area:3/1/6/6}.stack.stack-start>*{grid-area:3/1/4/4}.stack.stack-start>:nth-child(2){grid-area:2/2/5/5}.stack.stack-start>:first-child{grid-area:1/3/6/6}.stack.stack-end>*{grid-area:3/3/4/6}.stack.stack-end>:nth-child(2){grid-area:2/2/5/5}.stack.stack-end>:first-child{grid-area:1/1/6/4}.z-10{z-index:10}.z-20{z-index:20}.tab-content{order:var(--tabcontent-order);--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);border-color:#0000;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.container\!{width:100%!important}@media (min-width:40rem){.container\!{max-width:40rem!important}}@media (min-width:48rem){.container\!{max-width:48rem!important}}@media (min-width:64rem){.container\!{max-width:64rem!important}}@media (min-width:80rem){.container\!{max-width:80rem!important}}@media (min-width:96rem){.container\!{max-width:96rem!important}}.filter{flex-wrap:wrap;display:flex}.filter input[type=radio]{width:auto}.filter input{opacity:1;transition:margin .1s,opacity .3s,padding .3s,border-width .1s;overflow:hidden;scale:1}.filter input:not(:last-child){margin-inline-end:.25rem}.filter input.filter-reset{aspect-ratio:1}.filter input.filter-reset:after{content:"×"}.filter:not(:has(input:checked:not(.filter-reset))) .filter-reset,.filter:not(:has(input:checked:not(.filter-reset))) input[type=reset],.filter:has(input:checked:not(.filter-reset)) input:not(:checked,.filter-reset,input[type=reset]){opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.mx-auto{margin-inline:auto}.input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.my-4{margin-block:calc(var(--spacing)*4)}.label{white-space:nowrap;color:currentColor;align-items:center;gap:.375rem;display:inline-flex}@supports (color:color-mix(in lab,red,red)){.label{color:color-mix(in oklab,currentColor 60%,transparent)}}.label:has(input){cursor:pointer}.label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid currentColor;margin-inline:-.75rem .75rem}@supports (color:color-mix(in lab,red,red)){.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,#0000)}}.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid currentColor;margin-inline:.75rem -.75rem}@supports (color:color-mix(in lab,red,red)){.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,#0000)}}.mt-8{margin-top:calc(var(--spacing)*8)}.mr-2{margin-right:calc(var(--spacing)*2)}.fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:var(--color-base-content);width:.5rem;height:.5rem;display:inline-block}@supports (color:color-mix(in lab,red,red)){.status{background-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.status{vertical-align:middle;color:#0000004d;background-position:50%;background-repeat:no-repeat}@supports (color:color-mix(in lab,red,red)){.status{color:#0000004d}@supports (color:color-mix(in lab,red,red)){.status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}}.status{background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),#0000);box-shadow:0 2px 3px -1px}@supports (color:color-mix(in lab,red,red)){.status{box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),#0000)}}.tabs{--tabs-height:auto;--tabs-direction:row;--tab-height:calc(var(--size-field,.25rem)*10);height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.join{--join-ss:0;--join-se:0;--join-es:0;--join-ee:0;align-items:stretch;display:inline-flex}.join :where(.join-item){border-start-start-radius:var(--join-ss,0);border-start-end-radius:var(--join-se,0);border-end-end-radius:var(--join-ee,0);border-end-start-radius:var(--join-es,0)}.join :where(.join-item) *{--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.join>.join-item:where(:first-child),.join :first-child:not(:last-child) :where(.join-item){--join-ss:var(--radius-field);--join-se:0;--join-es:var(--radius-field);--join-ee:0}.join>.join-item:where(:last-child),.join :last-child:not(:first-child) :where(.join-item){--join-ss:0;--join-se:var(--radius-field);--join-es:0;--join-ee:var(--radius-field)}.join>.join-item:where(:only-child),.join :only-child :where(.join-item){--join-ss:var(--radius-field);--join-se:var(--radius-field);--join-es:var(--radius-field);--join-ee:var(--radius-field)}.mask{vertical-align:middle;display:inline-block;-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-64{height:calc(var(--spacing)*64)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\[80vh\]{max-height:80vh}.min-h-screen{min-height:100vh}.loading-lg{width:calc(var(--size-selector,.25rem)*7)}.w-4{width:calc(var(--spacing)*4)}.w-11\/12{width:91.6667%}.w-48{width:calc(var(--spacing)*48)}.w-full{width:100%}.max-w-4xl{max-width:var(--container-4xl)}.max-w-full{max-width:100%}.min-w-\[220px\]{min-width:220px}.min-w-max{min-width:max-content}.flex-1{flex:1}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.link{cursor:pointer;text-decoration-line:underline}.link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.link:focus{outline-offset:2px;outline:2px solid #0000}}.link:focus-visible{outline-offset:2px;outline:2px solid}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b-3{border-bottom-style:var(--tw-border-style);border-bottom-width:3px}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-700{border-color:var(--color-gray-700)}.border-b-gray-700{border-bottom-color:var(--color-gray-700)}.bg-base-100{background-color:var(--color-base-100)}.bg-base-200{background-color:var(--color-base-200)}.loading-spinner{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}.radio-sm{padding:.1875rem}.radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.p-4{padding:calc(var(--spacing)*4)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-1{padding-block:calc(var(--spacing)*1)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-10{padding-left:calc(var(--spacing)*10)}.text-center{text-align:center}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-gray-400{color:var(--color-gray-400)}.text-primary{color:var(--color-primary)}.text-red-500{color:var(--color-red-500)}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.blur{--tw-blur:blur(8px);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,)}.invert{--tw-invert:invert(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,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition\!{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events!important;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))!important;transition-duration:var(--tw-duration,var(--default-transition-duration))!important}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:bg-base-100:hover{background-color:var(--color-base-100)}.hover\:bg-base-200:hover{background-color:var(--color-base-200)}.hover\:bg-base-300:hover{background-color:var(--color-base-300)}}@media (min-width:48rem){.md\:w-1\/2{width:50%}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:gap-x-4{column-gap:calc(var(--spacing)*4)}}@media (min-width:64rem){.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}}@keyframes radio{0%{padding:5px}50%{padding:3px}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}@keyframes progress{50%{background-position-x:-115%}}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@keyframes dropdown{0%{opacity:0}}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
|
|
|
frontend/dist/assets/index-BbusHoyK.css
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
/*! tailwindcss v4.1.8 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-700:oklch(37.3% .034 259.733);--color-black:#000;--spacing:.25rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--ease-in:cubic-bezier(.4,0,1,1);--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}}:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@property --radialprogress{syntax: "<percentage>"; inherits: true; initial-value: 0%;}:root{scrollbar-color:currentColor #0000}@supports (color:color-mix(in lab,red,red)){:root{scrollbar-color:color-mix(in oklch,currentColor 35%,#0000)#0000}}:root{--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E")}:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not([class*=drawer-open])>.drawer-toggle:checked){overflow:hidden}:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){scrollbar-gutter:stable;background-image:linear-gradient(var(--color-base-100),var(--color-base-100));--root-bg:var(--color-base-100)}@supports (color:color-mix(in lab,red,red)){:where(:root:has(.modal-open,.modal[open],.modal:target,.modal-toggle:checked,.drawer:not(.drawer-open)>.drawer-toggle:checked)){--root-bg:color-mix(in srgb,var(--color-base-100),oklch(0% 0 0) 40%)}}:where(.modal[open],.modal-open,.modal-toggle:checked+.modal):not(.modal-start,.modal-end){scrollbar-gutter:stable}:root,[data-theme]{background-color:var(--root-bg,var(--color-base-100));color:var(--color-base-content)}}@layer components;@layer utilities{.diff{webkit-user-select:none;-webkit-user-select:none;user-select:none;direction:ltr;grid-template-columns:auto 1fr;width:100%;display:grid;position:relative;overflow:hidden;container-type:inline-size}.diff:focus-visible,.diff:has(.diff-item-1:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px;outline-color:var(--color-base-content)}.diff:focus-visible .diff-resizer{min-width:90cqi;max-width:90cqi}.diff:has(.diff-item-2:focus-visible){outline-style:var(--tw-outline-style);outline-offset:1px;outline-width:2px}.diff:has(.diff-item-2:focus-visible) .diff-resizer{min-width:10cqi;max-width:10cqi}@supports (-webkit-overflow-scrolling:touch) and (overflow:-webkit-paged-x){.diff:focus .diff-resizer{min-width:10cqi;max-width:10cqi}.diff:has(.diff-item-1:focus) .diff-resizer{min-width:90cqi;max-width:90cqi}}.tab{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;text-align:center;webkit-user-select:none;-webkit-user-select:none;user-select:none;flex-wrap:wrap;justify-content:center;align-items:center;display:inline-flex;position:relative}@media (hover:hover){.tab:hover{color:var(--color-base-content)}}.tab{--tab-p:1rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));order:var(--tab-order);height:var(--tab-height);border-color:#0000;padding-inline-start:var(--tab-p);padding-inline-end:var(--tab-p);font-size:.875rem}.tab:is(input[type=radio]){min-width:fit-content}.tab:is(input[type=radio]):after{content:attr(aria-label)}.tab:is(label){position:relative}.tab:is(label) input{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;position:absolute;top:0;right:0;bottom:0;left:0}:is(.tab:checked,.tab:is(label:has(:checked)),.tab:is(.tab-active,[aria-selected=true]))+.tab-content{height:calc(100% - var(--tab-height) + var(--border));display:block}.tab:not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true]){color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.tab:not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true]){color:color-mix(in oklab,var(--color-base-content)50%,transparent)}}.tab:not(input):empty{cursor:default;flex-grow:1}.tab:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.tab:focus{outline-offset:2px;outline:2px solid #0000}}.tab:focus-visible,.tab:is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.tab[disabled]{pointer-events:none;opacity:.4}.collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:1.9rem;width:.5rem;height:.5rem;transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);display:block;position:absolute;inset-inline-end:1.4rem;transform:translateY(-100%)rotate(45deg);box-shadow:2px 2px}:where(.btn){width:unset}.btn{cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;webkit-user-select:none;-webkit-user-select:none;user-select:none;padding-inline:var(--btn-p);color:var(--btn-fg);--tw-prose-links:var(--btn-fg);height:var(--size);font-size:var(--fontsize,.875rem);outline-color:var(--btn-color,var(--color-base-content));background-color:var(--btn-bg);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--btn-noise);border-width:var(--border);border-style:solid;border-color:var(--btn-border);text-shadow:0 .5px oklch(100% 0 0/calc(var(--depth)*.15));touch-action:manipulation;box-shadow:0 .5px 0 .5px oklch(100% 0 0/calc(var(--depth)*6%)) inset,var(--btn-shadow);--size:calc(var(--size-field,.25rem)*10);--btn-bg:var(--btn-color,var(--color-base-200));--btn-fg:var(--color-base-content);--btn-p:1rem;--btn-border:var(--btn-bg);border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}@supports (color:color-mix(in lab,red,red)){.btn{--btn-border:color-mix(in oklab,var(--btn-bg),#000 calc(var(--depth)*5%))}}.btn{--btn-shadow:0 3px 2px -2px var(--btn-bg),0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab,red,red)){.btn{--btn-shadow:0 3px 2px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000),0 4px 3px -2px color-mix(in oklab,var(--btn-bg)calc(var(--depth)*30%),#0000)}}.btn{--btn-noise:var(--fx-noise)}.prose .btn{text-decoration-line:none}@media (hover:hover){.btn:hover{--btn-bg:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab,red,red)){.btn:hover{--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}}.btn:focus-visible{isolation:isolate;outline-width:2px;outline-style:solid}.btn:active:not(.btn-active){--btn-bg:var(--btn-color,var(--color-base-200));translate:0 .5px}@supports (color:color-mix(in lab,red,red)){.btn:active:not(.btn-active){--btn-bg:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 5%)}}.btn:active:not(.btn-active){--btn-border:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab,red,red)){.btn:active:not(.btn-active){--btn-border:color-mix(in oklab,var(--btn-color,var(--color-base-200)),#000 7%)}}.btn:active:not(.btn-active){--btn-shadow:0 0 0 0 oklch(0% 0 0/0),0 0 0 0 oklch(0% 0 0/0)}.btn:is(:disabled,[disabled],.btn-disabled):not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.btn:is(:disabled,[disabled],.btn-disabled):not(.btn-link,.btn-ghost){background-color:color-mix(in oklab,var(--color-base-content)10%,transparent)}}.btn:is(:disabled,[disabled],.btn-disabled):not(.btn-link,.btn-ghost){box-shadow:none}.btn:is(:disabled,[disabled],.btn-disabled){pointer-events:none;--btn-border:#0000;--btn-noise:none;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.btn:is(:disabled,[disabled],.btn-disabled){--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}@media (hover:hover){.btn:is(:disabled,[disabled],.btn-disabled):hover{pointer-events:none;background-color:var(--color-neutral)}@supports (color:color-mix(in lab,red,red)){.btn:is(:disabled,[disabled],.btn-disabled):hover{background-color:color-mix(in oklab,var(--color-neutral)20%,transparent)}}.btn:is(:disabled,[disabled],.btn-disabled):hover{--btn-border:#0000;--btn-fg:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.btn:is(:disabled,[disabled],.btn-disabled):hover{--btn-fg:color-mix(in oklch,var(--color-base-content)20%,#0000)}}}.btn:is(input[type=checkbox],input[type=radio]){-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn:is(input[type=checkbox],input[type=radio]):after{content:attr(aria-label)}.btn:where(input:checked:not(.filter .btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);isolation:isolate}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem)*6);background-color:currentColor;display:inline-block;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.pointer-events-none{pointer-events:none}.collapse:not(td,tr,colgroup){visibility:visible}.collapse{border-radius:var(--radius-box,1rem);isolation:isolate;grid-template-rows:max-content 0fr;width:100%;transition:grid-template-rows .2s;display:grid;position:relative;overflow:hidden}.collapse>input:is([type=checkbox],[type=radio]){-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0;z-index:1;grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.collapse:is([open],:focus:not(.collapse-close)),.collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.collapse:is([open],:focus:not(.collapse-close))>.collapse-content,.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible;min-height:fit-content}.collapse:focus-visible,.collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.collapse:not(.collapse-close)>input[type=checkbox],.collapse:not(.collapse-close)>input[type=radio]:not(:checked),.collapse:not(.collapse-close)>.collapse-title{cursor:pointer}.collapse:focus:not(.collapse-close,.collapse[open])>.collapse-title{cursor:unset}.collapse:is([open],:focus:not(.collapse-close))>:where(.collapse-content),.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem;transition:padding .2s ease-out,background-color .2s ease-out}.collapse[open].collapse-arrow>.collapse-title:after,.collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse.collapse-open.collapse-plus>.collapse-title:after{content:"−"}.collapse.collapse-arrow:focus:not(.collapse-close)>.collapse-title:after,.collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse[open].collapse-plus>.collapse-title:after,.collapse.collapse-plus:focus:not(.collapse-close)>.collapse-title:after,.collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{content:"−"}.collapse:is(details){width:100%}.collapse:is(details) summary{display:block;position:relative}.collapse:is(details) summary::-webkit-details-marker{display:none}.collapse:is(details) summary{outline:none}.collapse-content{visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;transition:visibility .2s,padding .2s ease-out,background-color .2s ease-out}.collapse{visibility:collapse}.visible{visibility:visible}.toggle{border:var(--border)solid currentColor;color:var(--input-color);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;vertical-align:middle;webkit-user-select:none;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p),var(--radius-selector-max)) + min(var(--border),var(--radius-selector-max)));padding:var(--toggle-p);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;display:inline-grid;position:relative;box-shadow:inset 0 1px}@supports (color:color-mix(in lab,red,red)){.toggle{box-shadow:0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000) inset}}.toggle{--input-color:var(--color-base-content);transition:color .3s,grid-template-columns .2s}@supports (color:color-mix(in lab,red,red)){.toggle{--input-color:color-mix(in oklab,var(--color-base-content)50%,#0000)}}.toggle{--toggle-p:calc(var(--size)*.125);--size:calc(var(--size-selector,.25rem)*6);width:calc((var(--size)*2) - (var(--border) + var(--toggle-p))*2);height:var(--size)}.toggle>*{z-index:1;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.toggle>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.toggle>:focus{outline-offset:2px;outline:2px solid #0000}}.toggle>:nth-child(2){color:var(--color-base-100);rotate:none}.toggle>:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.toggle:has(:checked)>:nth-child(3){opacity:1;rotate:none}.toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);height:100%;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor;background-color:currentColor;grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@supports (color:color-mix(in lab,red,red)){.toggle:before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000)}}.toggle:before{background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise)}@media (forced-colors:active){.toggle:before{outline-style:var(--tw-outline-style);outline-offset:-1px;outline-width:1px}}@media print{.toggle:before{outline-offset:-1rem;outline:.25rem solid}}.toggle:focus-visible,.toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{background-color:currentColor}@starting-style{:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{opacity:0}}.toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.toggle:disabled{cursor:not-allowed;opacity:.3}.toggle:disabled:before{border:var(--border)solid currentColor;background-color:#0000}.input{cursor:text;border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;width:clamp(3rem,20rem,100%);height:var(--size);touch-action:manipulation;border-color:var(--input-color);box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;font-size:.875rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab,red,red)){.input{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.input{--size:calc(var(--size-field,.25rem)*10);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.input{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.input:where(input){display:inline-flex}.input :where(input){-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none;width:100%;height:100%;display:inline-flex}.input :where(input):focus,.input :where(input):focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input :where(input):focus,.input :where(input):focus-within{outline-offset:2px;outline:2px solid #0000}}.input :where(input[type=url]),.input :where(input[type=email]){direction:ltr}.input :where(input[type=date]){display:inline-block}.input:focus,.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.input:focus,.input:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.input:focus,.input:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}.input:has(>input[disabled]),.input:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.input:has(>input[disabled]),.input:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]){box-shadow:none}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.input::-webkit-date-and-time-value{text-align:inherit}.input[type=number]::-webkit-inner-spin-button{margin-block:-.75rem;margin-inline-end:-.75rem}.input::-webkit-calendar-picker-indicator{position:absolute;inset-inline-end:.75em}.table{border-radius:var(--radius-box);text-align:left;width:100%;font-size:.875rem;position:relative}.table:where(:dir(rtl),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){:is(.table tr.row-hover,.table tr.row-hover:nth-child(2n)):hover{background-color:var(--color-base-200)}}.table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.table :where(thead,tfoot){white-space:nowrap;color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(thead,tfoot){color:color-mix(in oklab,var(--color-base-content)60%,transparent)}}.table :where(thead,tfoot){font-size:.875rem;font-weight:600}.table :where(tfoot){border-top:var(--border)solid var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(tfoot){border-top:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,#0000)}}.table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.table :where(thead tr,tbody tr:not(:last-child)){border-bottom:var(--border)solid color-mix(in oklch,var(--color-base-content)5%,#0000)}}.steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);--tw-content:"";content:var(--tw-content);border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.steps .step>.step-icon,.steps .step:not(:has(.step-icon)):after{content:counter(step);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.steps .step:first-child:before{content:none}.steps .step[data-content]:after{content:attr(data-content)}.steps .step-neutral+.step-neutral:before,.steps .step-neutral:after,.steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-primary+.step-primary:before,.steps .step-primary:after,.steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-secondary+.step-secondary:before,.steps .step-secondary:after,.steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-accent+.step-accent:before,.steps .step-accent:after,.steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-info+.step-info:before,.steps .step-info:after,.steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-success+.step-success:before,.steps .step-success:after,.steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-warning+.step-warning:before,.steps .step-warning:after,.steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-error+.step-error:before,.steps .step-error:after,.steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.range{-webkit-appearance:none;-moz-appearance:none;appearance:none;webkit-appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem)*6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:currentColor}@supports (color:color-mix(in lab,red,red)){.range{--range-bg:color-mix(in oklab,currentColor 10%,#0000)}}.range{cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:#0000;border:none;overflow:hidden}[dir=rtl] .range{--range-dir:-1}.range:focus{outline:none}.range:focus-visible{outline-offset:2px;outline:2px solid}.range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}@media (forced-colors:active){.range::-webkit-slider-runnable-track{border:1px solid}.range::-moz-range-track{border:1px solid}}.range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;-webkit-appearance:none;-moz-appearance:none;appearance:none;webkit-appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%;transform:translateY(-50%)}@supports (color:color-mix(in lab,red,red)){.range::-webkit-slider-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))}}.range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size)*.5)}.range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p)solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill));background-color:currentColor;position:relative;top:50%}@supports (color:color-mix(in lab,red,red)){.range::-moz-range-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))}}.range:disabled{cursor:not-allowed;opacity:.3}.range\!{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;webkit-appearance:none!important;--range-thumb:var(--color-base-100)!important;--range-thumb-size:calc(var(--size-selector,.25rem)*6)!important;--range-progress:currentColor!important;--range-fill:1!important;--range-p:.25rem!important;--range-bg:currentColor!important}@supports (color:color-mix(in lab,red,red)){.range\!{--range-bg:color-mix(in oklab,currentColor 10%,#0000)!important}}.range\!{cursor:pointer!important;vertical-align:middle!important;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector))!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;width:clamp(3rem,20rem,100%)!important;height:var(--range-thumb-size)!important;background-color:#0000!important;border:none!important;overflow:hidden!important}[dir=rtl] .range\!{--range-dir:-1!important}.range\!:focus{outline:none!important}.range\!:focus-visible{outline-offset:2px!important;outline:2px solid!important}.range\!::-webkit-slider-runnable-track{background-color:var(--range-bg)!important;border-radius:var(--radius-selector)!important;width:100%!important;height:calc(var(--range-thumb-size)*.5)!important}@media (forced-colors:active){.range\!::-webkit-slider-runnable-track{border:1px solid!important}.range\!::-moz-range-track{border:1px solid!important}}.range\!::-webkit-slider-thumb{box-sizing:border-box!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;height:var(--range-thumb-size)!important;width:var(--range-thumb-size)!important;border:var(--range-p)solid!important;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;webkit-appearance:none!important;color:var(--range-progress)!important;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important;background-color:currentColor!important;position:relative!important;top:50%!important;transform:translateY(-50%)!important}@supports (color:color-mix(in lab,red,red)){.range\!::-webkit-slider-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important}}.range\!::-moz-range-track{background-color:var(--range-bg)!important;border-radius:var(--radius-selector)!important;width:100%!important;height:calc(var(--range-thumb-size)*.5)!important}.range\!::-moz-range-thumb{box-sizing:border-box!important;border-radius:calc(var(--radius-selector) + min(var(--range-p),var(--radius-selector-max)))!important;height:var(--range-thumb-size)!important;width:var(--range-thumb-size)!important;border:var(--range-p)solid!important;color:var(--range-progress)!important;box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px currentColor,0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important;background-color:currentColor!important;position:relative!important;top:50%!important}@supports (color:color-mix(in lab,red,red)){.range\!::-moz-range-thumb{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px color-mix(in oklab,currentColor calc(var(--depth)*10%),#0000),0 0 0 2rem var(--range-thumb) inset,calc((var(--range-dir,1)*-100rem) - (var(--range-dir,1)*var(--range-thumb-size)/2)) 0 0 calc(100rem*var(--range-fill))!important}}.range\!:disabled{cursor:not-allowed!important;opacity:.3!important}.tabs-border .tab{--tab-border-color:#0000 #0000 var(--tab-border-color)#0000;border-radius:var(--radius-field);position:relative}.tabs-border .tab:before{--tw-content:"";content:var(--tw-content);background-color:var(--tab-border-color);border-radius:var(--radius-field);width:80%;height:3px;transition:background-color .2s;position:absolute;bottom:0;left:10%}:is(.tabs-border .tab:is(.tab-active,[aria-selected=true]):not(.tab-disabled,[disabled]),.tabs-border .tab:is(input:checked),.tabs-border .tab:is(label:has(:checked))):before{--tab-border-color:currentColor;border-top:3px solid}.select{border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-base-100);vertical-align:middle;width:clamp(3rem,20rem,100%);height:var(--size);touch-action:manipulation;text-overflow:ellipsis;box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;background-image:linear-gradient(45deg,#0000 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,#0000 50%);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;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-shrink:1;align-items:center;gap:.375rem;padding-inline:1rem 1.75rem;font-size:.875rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab,red,red)){.select{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.select{border-color:var(--input-color);--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.select{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.select{--size:calc(var(--size-field,.25rem)*10)}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}.select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:inherit;border-radius:inherit;border-style:none;width:calc(100% + 2.75rem);height:calc(100% - 2px);margin-inline:-1rem -1.75rem;padding-inline:1rem 1.75rem}.select select:focus,.select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.select select:focus,.select select:focus-within{outline-offset:2px;outline:2px solid #0000}}.select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}.select:focus,.select:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.select:focus,.select:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.select:focus,.select:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;z-index:1}.select:has(>select[disabled]),.select:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.select:has(>select[disabled]),.select:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.select:has(>select[disabled])>select[disabled]{cursor:not-allowed}.timeline{display:flex;position:relative}.timeline>li{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));flex-shrink:0;align-items:center;display:grid;position:relative}.timeline>li>hr{border:none;width:100%}.timeline>li>hr:first-child{grid-row-start:2;grid-column-start:1}.timeline>li>hr:last-child{grid-area:2/3/auto/none}@media print{.timeline>li>hr{border:.1px solid var(--color-base-300)}}.timeline :where(hr){background-color:var(--color-base-300);height:.25rem}.timeline:has(.timeline-middle hr):first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.timeline:has(.timeline-middle hr):last-child,.timeline:not(:has(.timeline-middle)) :first-child hr:last-child{border-start-start-radius:var(--radius-selector);border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:var(--radius-selector)}.timeline:not(:has(.timeline-middle)) :last-child hr:first-child{border-start-start-radius:0;border-start-end-radius:var(--radius-selector);border-end-end-radius:var(--radius-selector);border-end-start-radius:0}.collapse-title{grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.checkbox{border:var(--border)solid var(--input-color,var(--color-base-content))}@supports (color:color-mix(in lab,red,red)){.checkbox{border:var(--border)solid var(--input-color,color-mix(in oklab,var(--color-base-content)20%,#0000))}}.checkbox{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-selector);vertical-align:middle;color:var(--color-base-content);box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 0 #0000 inset,0 0 #0000;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);flex-shrink:0;padding:.25rem;transition:background-color .2s,box-shadow .2s;display:inline-block;position:relative}.checkbox:before{--tw-content:"";content:var(--tw-content);opacity:0;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);width:100%;height:100%;box-shadow:0 3px oklch(100% 0 0/calc(var(--depth)*.1)) inset;background-color:currentColor;font-size:1rem;line-height:.75;transition:clip-path .3s .1s,opacity .1s .1s,rotate .3s .1s,translate .3s .1s;display:block;rotate:45deg}.checkbox:focus-visible{outline:2px solid var(--input-color,currentColor);outline-offset:2px}.checkbox:checked,.checkbox[aria-checked=true]{background-color:var(--input-color,#0000);box-shadow:0 0 #0000 inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1))}:is(.checkbox:checked,.checkbox[aria-checked=true]):before{clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%);opacity:1}@media (forced-colors:active){:is(.checkbox:checked,.checkbox[aria-checked=true]):before{--tw-content:"✔︎";clip-path:none;background-color:#0000;rotate:none}}@media print{:is(.checkbox:checked,.checkbox[aria-checked=true]):before{--tw-content:"✔︎";clip-path:none;background-color:#0000;rotate:none}}.checkbox:indeterminate:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%);translate:0 -35%;rotate:none}.checkbox:disabled{cursor:not-allowed;opacity:.2}.radio{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;vertical-align:middle;border:var(--border)solid var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;display:inline-block;position:relative}@supports (color:color-mix(in lab,red,red)){.radio{border:var(--border)solid var(--input-color,color-mix(in srgb,currentColor 20%,#0000))}}.radio{box-shadow:0 1px oklch(0% 0 0/calc(var(--depth)*.1)) inset;--size:calc(var(--size-selector,.25rem)*6);width:var(--size);height:var(--size);color:var(--input-color,currentColor)}.radio:before{--tw-content:"";content:var(--tw-content);background-size:auto,calc(var(--noise)*100%);background-image:none,var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.radio:focus-visible{outline:2px solid}.radio:checked,.radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor;animation:.2s ease-out radio}:is(.radio:checked,.radio[aria-checked=true]):before{box-shadow:0 -1px oklch(0% 0 0/calc(var(--depth)*.1)) inset,0 8px 0 -4px oklch(100% 0 0/calc(var(--depth)*.1)) inset,0 1px oklch(0% 0 0/calc(var(--depth)*.1));background-color:currentColor}@media (forced-colors:active){:is(.radio:checked,.radio[aria-checked=true]):before{outline-style:var(--tw-outline-style);outline-offset:-1px;outline-width:1px}}@media print{:is(.radio:checked,.radio[aria-checked=true]):before{outline-offset:-1rem;outline:.25rem solid}}.radio:disabled{cursor:not-allowed;opacity:.2}.stats{border-radius:var(--radius-box);grid-auto-flow:column;display:inline-grid;position:relative;overflow-x:auto}.progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-box);background-color:currentColor;width:100%;height:.5rem;position:relative;overflow:hidden}@supports (color:color-mix(in lab,red,red)){.progress{background-color:color-mix(in oklab,currentColor 20%,transparent)}}.progress{color:var(--color-base-content)}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:#0000;background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:#0000}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-12{top:calc(var(--spacing)*12)}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.left-0{left:calc(var(--spacing)*0)}.textarea{border:var(--border)solid #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;touch-action:manipulation;border-color:var(--input-color);width:clamp(3rem,20rem,100%);min-height:5rem;box-shadow:0 1px var(--input-color) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset;flex-shrink:1;padding-block:.5rem;padding-inline:.75rem;font-size:.875rem}@supports (color:color-mix(in lab,red,red)){.textarea{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000) inset,0 -1px oklch(100% 0 0/calc(var(--depth)*.1)) inset}}.textarea{--input-color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.textarea{--input-color:color-mix(in oklab,var(--color-base-content)20%,#0000)}}.textarea textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0000;border:none}.textarea textarea:focus,.textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.textarea textarea:focus,.textarea textarea:focus-within{outline-offset:2px;outline:2px solid #0000}}.textarea:focus,.textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab,red,red)){.textarea:focus,.textarea:focus-within{box-shadow:0 1px color-mix(in oklab,var(--input-color)calc(var(--depth)*10%),#0000)}}.textarea:focus,.textarea:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){color:color-mix(in oklab,var(--color-base-content)40%,transparent)}}:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]))::placeholder{color:var(--color-base-content)}@supports (color:color-mix(in lab,red,red)){:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]))::placeholder{color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){box-shadow:none}.textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.stack>*{width:100%;height:100%}.stack>:nth-child(n+2){opacity:.7;width:100%}.stack>:nth-child(2){z-index:2;opacity:.9}.stack>:first-child{z-index:3;width:100%}:is(.stack,.stack.stack-bottom)>*{grid-area:3/3/6/4}:is(.stack,.stack.stack-bottom)>:nth-child(2){grid-area:2/2/5/5}:is(.stack,.stack.stack-bottom)>:first-child{grid-area:1/1/4/6}.stack.stack-top>*{grid-area:1/3/4/4}.stack.stack-top>:nth-child(2){grid-area:2/2/5/5}.stack.stack-top>:first-child{grid-area:3/1/6/6}.stack.stack-start>*{grid-area:3/1/4/4}.stack.stack-start>:nth-child(2){grid-area:2/2/5/5}.stack.stack-start>:first-child{grid-area:1/3/6/6}.stack.stack-end>*{grid-area:3/3/4/6}.stack.stack-end>:nth-child(2){grid-area:2/2/5/5}.stack.stack-end>:first-child{grid-area:1/1/6/4}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.tab-content{order:var(--tabcontent-order);--tabcontent-radius-ss:0;--tabcontent-radius-se:0;--tabcontent-radius-es:0;--tabcontent-radius-ee:0;--tabcontent-order:1;width:100%;margin:var(--tabcontent-margin);border-color:#0000;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.container\!{width:100%!important}@media (min-width:40rem){.container\!{max-width:40rem!important}}@media (min-width:48rem){.container\!{max-width:48rem!important}}@media (min-width:64rem){.container\!{max-width:64rem!important}}@media (min-width:80rem){.container\!{max-width:80rem!important}}@media (min-width:96rem){.container\!{max-width:96rem!important}}.filter{flex-wrap:wrap;display:flex}.filter input[type=radio]{width:auto}.filter input{opacity:1;transition:margin .1s,opacity .3s,padding .3s,border-width .1s;overflow:hidden;scale:1}.filter input:not(:last-child){margin-inline-end:.25rem}.filter input.filter-reset{aspect-ratio:1}.filter input.filter-reset:after{content:"×"}.filter:not(:has(input:checked:not(.filter-reset))) .filter-reset,.filter:not(:has(input:checked:not(.filter-reset))) input[type=reset],.filter:has(input:checked:not(.filter-reset)) input:not(:checked,.filter-reset,input[type=reset]){opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.mx-auto{margin-inline:auto}.input-sm{--size:calc(var(--size-field,.25rem)*8);font-size:.75rem}.input-sm[type=number]::-webkit-inner-spin-button{margin-block:-.5rem;margin-inline-end:-.75rem}.my-4{margin-block:calc(var(--spacing)*4)}.label{white-space:nowrap;color:currentColor;align-items:center;gap:.375rem;display:inline-flex}@supports (color:color-mix(in lab,red,red)){.label{color:color-mix(in oklab,currentColor 60%,transparent)}}.label:has(input){cursor:pointer}.label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid currentColor;margin-inline:-.75rem .75rem}@supports (color:color-mix(in lab,red,red)){.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border)solid color-mix(in oklab,currentColor 10%,#0000)}}.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid currentColor;margin-inline:.75rem -.75rem}@supports (color:color-mix(in lab,red,red)){.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border)solid color-mix(in oklab,currentColor 10%,#0000)}}.mt-8{margin-top:calc(var(--spacing)*8)}.mr-2{margin-right:calc(var(--spacing)*2)}.fieldset-legend{color:var(--color-base-content);justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:-.25rem;padding-block:.5rem;font-weight:600;display:flex}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:var(--color-base-content);width:.5rem;height:.5rem;display:inline-block}@supports (color:color-mix(in lab,red,red)){.status{background-color:color-mix(in oklab,var(--color-base-content)20%,transparent)}}.status{vertical-align:middle;color:#0000004d;background-position:50%;background-repeat:no-repeat}@supports (color:color-mix(in lab,red,red)){.status{color:#0000004d}@supports (color:color-mix(in lab,red,red)){.status{color:color-mix(in oklab,var(--color-black)30%,transparent)}}}.status{background-image:radial-gradient(circle at 35% 30%,oklch(1 0 0/calc(var(--depth)*.5)),#0000);box-shadow:0 2px 3px -1px}@supports (color:color-mix(in lab,red,red)){.status{box-shadow:0 2px 3px -1px color-mix(in oklab,currentColor calc(var(--depth)*100%),#0000)}}.tabs{--tabs-height:auto;--tabs-direction:row;--tab-height:calc(var(--size-field,.25rem)*10);height:var(--tabs-height);flex-wrap:wrap;flex-direction:var(--tabs-direction);display:flex}.fieldset{grid-template-columns:1fr;grid-auto-rows:max-content;gap:.375rem;padding-block:.25rem;font-size:.75rem;display:grid}.card-title{font-size:var(--cardtitle-fs,1.125rem);align-items:center;gap:.5rem;font-weight:600;display:flex}.mask{vertical-align:middle;display:inline-block;-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.btn-circle{width:var(--size);height:var(--size);border-radius:3.40282e38px;padding-inline:0}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-64{height:calc(var(--spacing)*64)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-\[80vh\]{max-height:80vh}.min-h-screen{min-height:100vh}.loading-lg{width:calc(var(--size-selector,.25rem)*7)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-11\/12{width:91.6667%}.w-48{width:calc(var(--spacing)*48)}.w-full{width:100%}.max-w-4xl{max-width:var(--container-4xl)}.max-w-full{max-width:100%}.min-w-\[220px\]{min-width:220px}.min-w-max{min-width:max-content}.flex-1{flex:1}.border-separate{border-collapse:separate}.border-spacing-0{--tw-border-spacing-x:calc(var(--spacing)*0);--tw-border-spacing-y:calc(var(--spacing)*0);border-spacing:var(--tw-border-spacing-x)var(--tw-border-spacing-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.link{cursor:pointer;text-decoration-line:underline}.link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.link:focus{outline-offset:2px;outline:2px solid #0000}}.link:focus-visible{outline-offset:2px;outline:2px solid}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b-3{border-bottom-style:var(--tw-border-style);border-bottom-width:3px}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-700{border-color:var(--color-gray-700)}.border-b-gray-700{border-bottom-color:var(--color-gray-700)}.bg-base-100{background-color:var(--color-base-100)}.bg-base-200{background-color:var(--color-base-200)}.loading-spinner{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}.radio-sm{padding:.1875rem}.radio-sm[type=radio]{--size:calc(var(--size-selector,.25rem)*5)}.p-4{padding:calc(var(--spacing)*4)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-1{padding-block:calc(var(--spacing)*1)}.pt-4{padding-top:calc(var(--spacing)*4)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-10{padding-left:calc(var(--spacing)*10)}.text-center{text-align:center}.text-left{text-align:left}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-gray-400{color:var(--color-gray-400)}.text-primary{color:var(--color-primary)}.text-red-500{color:var(--color-red-500)}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible){--btn-shadow:"";--btn-bg:#0000;--btn-border:#0000;--btn-noise:none}.btn-ghost:not(.btn-active,:hover,:active:focus,:focus-visible):not(:disabled,[disabled],.btn-disabled){--btn-fg:currentColor;outline-color:currentColor}@media (hover:none){.btn-ghost:hover:not(.btn-active,:active,:focus-visible,:disabled,[disabled],.btn-disabled){--btn-shadow:"";--btn-bg:#0000;--btn-border:#0000;--btn-noise:none;--btn-fg:currentColor}}.blur{--tw-blur:blur(8px);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,)}.invert{--tw-invert:invert(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,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition\!{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events!important;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function))!important;transition-duration:var(--tw-duration,var(--default-transition-duration))!important}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:bg-base-100:hover{background-color:var(--color-base-100)}.hover\:bg-base-200:hover{background-color:var(--color-base-200)}.hover\:bg-base-300:hover{background-color:var(--color-base-300)}}@media (min-width:48rem){.md\:w-1\/2{width:50%}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:gap-x-4{column-gap:calc(var(--spacing)*4)}}@media (min-width:64rem){.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}}@keyframes radio{0%{padding:5px}50%{padding:3px}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}@keyframes progress{50%{background-position-x:-115%}}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@keyframes dropdown{0%{opacity:0}}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@property --tw-border-spacing-x{syntax:"<length>";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:"<length>";inherits:false;initial-value:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
frontend/dist/assets/{index-D2ksG3qQ.js → index-GljWyhYi.js}
RENAMED
The diff for this file is too large to render.
See raw diff
|
|
frontend/dist/index.html
CHANGED
@@ -5,8 +5,8 @@
|
|
5 |
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
<title>🥇 Omni Seal Bench Watermarking Leaderboard</title>
|
8 |
-
<script type="module" crossorigin src="/assets/index-
|
9 |
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
10 |
</head>
|
11 |
<body>
|
12 |
<div id="root"></div>
|
|
|
5 |
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
7 |
<title>🥇 Omni Seal Bench Watermarking Leaderboard</title>
|
8 |
+
<script type="module" crossorigin src="/assets/index-GljWyhYi.js"></script>
|
9 |
+
<link rel="stylesheet" crossorigin href="/assets/index-BbusHoyK.css">
|
10 |
</head>
|
11 |
<body>
|
12 |
<div id="root"></div>
|
frontend/package-lock.json
CHANGED
@@ -8,6 +8,7 @@
|
|
8 |
"name": "frontend",
|
9 |
"version": "0.0.0",
|
10 |
"dependencies": {
|
|
|
11 |
"@tailwindcss/vite": "^4.0.0",
|
12 |
"@types/wavesurfer.js": "^6.0.12",
|
13 |
"react": "^18.3.1",
|
@@ -834,6 +835,15 @@
|
|
834 |
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
835 |
}
|
836 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
837 |
"node_modules/@humanwhocodes/config-array": {
|
838 |
"version": "0.13.0",
|
839 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
|
|
8 |
"name": "frontend",
|
9 |
"version": "0.0.0",
|
10 |
"dependencies": {
|
11 |
+
"@heroicons/react": "^2.2.0",
|
12 |
"@tailwindcss/vite": "^4.0.0",
|
13 |
"@types/wavesurfer.js": "^6.0.12",
|
14 |
"react": "^18.3.1",
|
|
|
835 |
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
836 |
}
|
837 |
},
|
838 |
+
"node_modules/@heroicons/react": {
|
839 |
+
"version": "2.2.0",
|
840 |
+
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
|
841 |
+
"integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
|
842 |
+
"license": "MIT",
|
843 |
+
"peerDependencies": {
|
844 |
+
"react": ">= 16 || ^19.0.0-rc"
|
845 |
+
}
|
846 |
+
},
|
847 |
"node_modules/@humanwhocodes/config-array": {
|
848 |
"version": "0.13.0",
|
849 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
frontend/package.json
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md,html}\""
|
11 |
},
|
12 |
"dependencies": {
|
|
|
13 |
"@tailwindcss/vite": "^4.0.0",
|
14 |
"@types/wavesurfer.js": "^6.0.12",
|
15 |
"react": "^18.3.1",
|
@@ -32,4 +33,4 @@
|
|
32 |
"typescript": "^5.4.5",
|
33 |
"vite": "^5.2.10"
|
34 |
}
|
35 |
-
}
|
|
|
10 |
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md,html}\""
|
11 |
},
|
12 |
"dependencies": {
|
13 |
+
"@heroicons/react": "^2.2.0",
|
14 |
"@tailwindcss/vite": "^4.0.0",
|
15 |
"@types/wavesurfer.js": "^6.0.12",
|
16 |
"react": "^18.3.1",
|
|
|
33 |
"typescript": "^5.4.5",
|
34 |
"vite": "^5.2.10"
|
35 |
}
|
36 |
+
}
|
frontend/src/App.tsx
CHANGED
@@ -1,17 +1,39 @@
|
|
1 |
import { useState, useEffect } from 'react'
|
2 |
-
import Examples from './components/Examples'
|
3 |
import LeaderboardPage from './components/LeaderboardPage'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
function App() {
|
6 |
-
const [activeTab, setActiveTab] = useState<
|
7 |
-
'leaderboard' | 'imageExamples' | 'audioExamples' | 'videoExamples'
|
8 |
-
>('leaderboard')
|
9 |
const [theme, setTheme] = useState<'dark' | 'light'>('dark')
|
10 |
|
11 |
useEffect(() => {
|
12 |
document.documentElement.setAttribute('data-theme', theme)
|
13 |
}, [theme])
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
return (
|
16 |
<div className="min-h-screen w-11/12 mx-auto">
|
17 |
<div className="bg-base-100 my-4">
|
@@ -30,55 +52,20 @@ function App() {
|
|
30 |
</div>
|
31 |
</div>
|
32 |
|
33 |
-
<div className="tabs tabs-border">
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
<input
|
47 |
-
type="radio"
|
48 |
-
name="my_tabs_6"
|
49 |
-
className="tab"
|
50 |
-
aria-label="Image Examples"
|
51 |
-
checked={activeTab === 'imageExamples'}
|
52 |
-
onChange={() => setActiveTab('imageExamples')}
|
53 |
-
/>
|
54 |
-
<div className="tab-content bg-base-100 ">
|
55 |
-
{activeTab === 'imageExamples' ? <Examples fileType="image" /> : null}
|
56 |
-
</div>
|
57 |
-
|
58 |
-
<input
|
59 |
-
type="radio"
|
60 |
-
name="my_tabs_6"
|
61 |
-
className="tab"
|
62 |
-
aria-label="Audio Examples"
|
63 |
-
checked={activeTab === 'audioExamples'}
|
64 |
-
onChange={() => setActiveTab('audioExamples')}
|
65 |
-
/>
|
66 |
-
<div className="tab-content bg-base-100 ">
|
67 |
-
{activeTab === 'audioExamples' ? <Examples fileType="audio" /> : null}
|
68 |
-
</div>
|
69 |
-
|
70 |
-
<input
|
71 |
-
type="radio"
|
72 |
-
name="my_tabs_6"
|
73 |
-
className="tab"
|
74 |
-
aria-label="Video Examples"
|
75 |
-
checked={activeTab === 'videoExamples'}
|
76 |
-
onChange={() => setActiveTab('videoExamples')}
|
77 |
-
/>
|
78 |
-
<div className="tab-content bg-base-100 ">
|
79 |
-
{activeTab === 'videoExamples' ? <Examples fileType="video" /> : null}
|
80 |
-
</div>
|
81 |
</div>
|
|
|
82 |
</div>
|
83 |
)
|
84 |
}
|
|
|
1 |
import { useState, useEffect } from 'react'
|
|
|
2 |
import LeaderboardPage from './components/LeaderboardPage'
|
3 |
+
import Examples from './components/Examples'
|
4 |
+
|
5 |
+
const TABS = [
|
6 |
+
{ label: 'Audio', type: 'audio-leaderboard' },
|
7 |
+
{ label: 'Image', type: 'image-leaderboard' },
|
8 |
+
{ label: 'Video', type: 'video-leaderboard' },
|
9 |
+
{ label: 'Image Examples', type: 'image-examples' },
|
10 |
+
{ label: 'Audio Examples', type: 'audio-examples' },
|
11 |
+
{ label: 'Video Examples', type: 'video-examples' },
|
12 |
+
]
|
13 |
|
14 |
function App() {
|
15 |
+
const [activeTab, setActiveTab] = useState<string>('audio-leaderboard')
|
|
|
|
|
16 |
const [theme, setTheme] = useState<'dark' | 'light'>('dark')
|
17 |
|
18 |
useEffect(() => {
|
19 |
document.documentElement.setAttribute('data-theme', theme)
|
20 |
}, [theme])
|
21 |
|
22 |
+
let content = null
|
23 |
+
if (activeTab === 'audio-leaderboard') {
|
24 |
+
content = <LeaderboardPage datasetType="audio" />
|
25 |
+
} else if (activeTab === 'image-leaderboard') {
|
26 |
+
content = <LeaderboardPage datasetType="image" />
|
27 |
+
} else if (activeTab === 'video-leaderboard') {
|
28 |
+
content = <LeaderboardPage datasetType="video" />
|
29 |
+
} else if (activeTab === 'image-examples') {
|
30 |
+
content = <Examples fileType="image" />
|
31 |
+
} else if (activeTab === 'audio-examples') {
|
32 |
+
content = <Examples fileType="audio" />
|
33 |
+
} else if (activeTab === 'video-examples') {
|
34 |
+
content = <Examples fileType="video" />
|
35 |
+
}
|
36 |
+
|
37 |
return (
|
38 |
<div className="min-h-screen w-11/12 mx-auto">
|
39 |
<div className="bg-base-100 my-4">
|
|
|
52 |
</div>
|
53 |
</div>
|
54 |
|
55 |
+
<div className="tabs tabs-border mb-2 ">
|
56 |
+
{TABS.map((tab) => (
|
57 |
+
<input
|
58 |
+
key={tab.type}
|
59 |
+
type="radio"
|
60 |
+
name="leaderboard_tabs"
|
61 |
+
className="tab"
|
62 |
+
aria-label={tab.label}
|
63 |
+
checked={activeTab === tab.type}
|
64 |
+
onChange={() => setActiveTab(tab.type)}
|
65 |
+
/>
|
66 |
+
))}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
</div>
|
68 |
+
<div className="w-full ">{content}</div>
|
69 |
</div>
|
70 |
)
|
71 |
}
|
frontend/src/components/IndependentMetricsTable.tsx
CHANGED
@@ -1,69 +0,0 @@
|
|
1 |
-
import React from 'react'
|
2 |
-
|
3 |
-
interface Row {
|
4 |
-
metric: string
|
5 |
-
[key: string]: string | number
|
6 |
-
}
|
7 |
-
|
8 |
-
interface IndependentMetricsTableProps {
|
9 |
-
independentMetrics: string[]
|
10 |
-
tableHeader: string[]
|
11 |
-
selectedModels: Set<string>
|
12 |
-
tableRows: Row[]
|
13 |
-
}
|
14 |
-
|
15 |
-
const IndependentMetricsTable: React.FC<IndependentMetricsTableProps> = ({
|
16 |
-
independentMetrics,
|
17 |
-
tableHeader,
|
18 |
-
selectedModels,
|
19 |
-
tableRows,
|
20 |
-
}) => {
|
21 |
-
if (independentMetrics.length === 0) return null
|
22 |
-
return (
|
23 |
-
<div className="overflow-x-auto max-h-[80vh] overflow-y-auto">
|
24 |
-
<table className="table w-full min-w-max border-gray-700 border">
|
25 |
-
<thead>
|
26 |
-
<tr>
|
27 |
-
<th className="sticky left-0 top-0 bg-base-100 z-20 border-gray-700 border">Metric</th>
|
28 |
-
{tableHeader
|
29 |
-
.filter((model) => selectedModels.has(model))
|
30 |
-
.map((model) => (
|
31 |
-
<th
|
32 |
-
key={`independent-${model}`}
|
33 |
-
className="sticky top-0 bg-base-100 z-10 text-center text-xs border-gray-700 border"
|
34 |
-
>
|
35 |
-
{model}
|
36 |
-
</th>
|
37 |
-
))}
|
38 |
-
</tr>
|
39 |
-
</thead>
|
40 |
-
<tbody>
|
41 |
-
{independentMetrics.sort().map((metric) => {
|
42 |
-
const row = tableRows.find((r) => r.metric === metric)
|
43 |
-
if (!row) return null
|
44 |
-
return (
|
45 |
-
<tr key={`independent-${metric}`} className="hover:bg-base-100">
|
46 |
-
<td className="sticky left-0 bg-base-100 z-10 border-gray-700 border">{metric}</td>
|
47 |
-
{tableHeader
|
48 |
-
.filter((model) => selectedModels.has(model))
|
49 |
-
.map((col) => {
|
50 |
-
const cell = row[col]
|
51 |
-
return (
|
52 |
-
<td
|
53 |
-
key={`independent-${metric}-${col}`}
|
54 |
-
className="text-center border-gray-700 border"
|
55 |
-
>
|
56 |
-
{!isNaN(Number(cell)) ? Number(Number(cell).toFixed(3)) : cell}
|
57 |
-
</td>
|
58 |
-
)
|
59 |
-
})}
|
60 |
-
</tr>
|
61 |
-
)
|
62 |
-
})}
|
63 |
-
</tbody>
|
64 |
-
</table>
|
65 |
-
</div>
|
66 |
-
)
|
67 |
-
}
|
68 |
-
|
69 |
-
export default IndependentMetricsTable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/src/components/LeaderboardPage.tsx
CHANGED
@@ -6,14 +6,24 @@ import ModelFilter from './ModelFilter'
|
|
6 |
import API from '../API'
|
7 |
import LoadingSpinner from './LoadingSpinner'
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
]
|
|
|
|
|
|
|
|
|
|
|
16 |
const [selectedDatasetName, setSelectedDatasetName] = useState(datasetNames[0])
|
|
|
|
|
|
|
|
|
|
|
17 |
const [models, setModels] = useState<string[]>([])
|
18 |
const [selectedModels, setSelectedModels] = useState<Set<string>>(new Set())
|
19 |
const [loading, setLoading] = useState(true)
|
|
|
6 |
import API from '../API'
|
7 |
import LoadingSpinner from './LoadingSpinner'
|
8 |
|
9 |
+
interface LeaderboardPageProps {
|
10 |
+
datasetType: 'audio' | 'image' | 'video'
|
11 |
+
}
|
12 |
+
|
13 |
+
const DATASET_NAMES: { [type: string]: string[] } = {
|
14 |
+
audio: ['voxpopuli_1k/audio', 'ravdess_1k/audio'],
|
15 |
+
image: ['val2014_1k/image'],
|
16 |
+
video: ['sav_val_full/video'],
|
17 |
+
}
|
18 |
+
|
19 |
+
const LeaderboardPage: React.FC<LeaderboardPageProps> = ({ datasetType }) => {
|
20 |
+
const datasetNames = DATASET_NAMES[datasetType]
|
21 |
const [selectedDatasetName, setSelectedDatasetName] = useState(datasetNames[0])
|
22 |
+
|
23 |
+
// Update selectedDatasetName when datasetType changes
|
24 |
+
useEffect(() => {
|
25 |
+
setSelectedDatasetName(DATASET_NAMES[datasetType][0])
|
26 |
+
}, [datasetType])
|
27 |
const [models, setModels] = useState<string[]>([])
|
28 |
const [selectedModels, setSelectedModels] = useState<Set<string>>(new Set())
|
29 |
const [loading, setLoading] = useState(true)
|
frontend/src/components/LeaderboardTable.tsx
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
import React, { useEffect, useState } from 'react'
|
|
|
2 |
import LeaderboardFilter from './LeaderboardFilter'
|
3 |
import LoadingSpinner from './LoadingSpinner'
|
4 |
-
import
|
5 |
|
6 |
interface LeaderboardTableProps {
|
7 |
benchmarkData: any
|
@@ -213,7 +214,6 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
213 |
|
214 |
const getSortConfig = () => {
|
215 |
// Find the first sorted column (overallMetric, model)
|
216 |
-
console.log({ sortState })
|
217 |
for (const overallMetric of overallMetrics) {
|
218 |
if (!selectedOverallMetrics.has(overallMetric)) continue
|
219 |
const models = tableHeader.filter((model) => selectedModels.has(model))
|
@@ -253,7 +253,6 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
253 |
const sortModelColumns = (models: string[], overallMetric: string): string[] => {
|
254 |
// Column sort takes precedence; if no column sort, return models in default order
|
255 |
const columnSortConfig = getColumnSortConfig()
|
256 |
-
console.log({ columnSortConfig, overallMetric })
|
257 |
if (columnSortConfig && columnSortConfig.overallMetric === overallMetric) {
|
258 |
// Sort by average value for each model in this overallMetric
|
259 |
return [...models].sort((a, b) => {
|
@@ -311,7 +310,7 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
311 |
}
|
312 |
|
313 |
// Identify metrics that don't belong to any overall metric group
|
314 |
-
const
|
315 |
// Get all metrics from the table rows
|
316 |
const allMetrics = tableRows.map((row) => row.metric as string)
|
317 |
|
@@ -469,8 +468,6 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
469 |
)
|
470 |
})
|
471 |
|
472 |
-
console.log({ modelOrderByOverallMetric })
|
473 |
-
|
474 |
return (
|
475 |
<div className="rounded">
|
476 |
{error && <div className="text-red-500">{error}</div>}
|
@@ -482,11 +479,11 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
482 |
selectedOverallMetrics={selectedOverallMetrics}
|
483 |
setSelectedOverallMetrics={setSelectedOverallMetrics}
|
484 |
/>
|
485 |
-
<LeaderboardFilter
|
486 |
groups={groupRows}
|
487 |
selectedMetrics={selectedMetrics}
|
488 |
setSelectedMetrics={setSelectedMetrics}
|
489 |
-
/>
|
490 |
</div>
|
491 |
|
492 |
{selectedModels.size === 0 || selectedMetrics.size === 0 ? (
|
@@ -495,28 +492,136 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
495 |
</div>
|
496 |
) : (
|
497 |
<>
|
498 |
-
{/*
|
499 |
-
<
|
500 |
-
|
501 |
tableHeader={tableHeader}
|
502 |
selectedModels={selectedModels}
|
503 |
tableRows={tableRows}
|
504 |
/>
|
505 |
|
506 |
{/* Main metrics table */}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
<div className="overflow-x-auto max-h-[80vh] overflow-y-auto">
|
508 |
-
<table className="table w-full min-w-max border-gray-700 border">
|
509 |
<thead>
|
510 |
<tr>
|
511 |
-
<th className="sticky left-0 top-0 bg-base-100 z-20 border-gray-700
|
512 |
-
Attack
|
513 |
</th>
|
514 |
{overallMetrics
|
515 |
.filter((metric) => selectedOverallMetrics.has(metric))
|
516 |
.map((metric) => (
|
517 |
<th
|
518 |
key={`header-metric-${metric}`}
|
519 |
-
className="bg-base-100 z-10 text-center text-xs border-gray-700
|
520 |
colSpan={modelOrderByOverallMetric[metric].length}
|
521 |
>
|
522 |
{metric}
|
@@ -524,7 +629,7 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
524 |
))}
|
525 |
</tr>
|
526 |
<tr>
|
527 |
-
<th className="sticky left-0 bg-base-100 z-
|
528 |
{overallMetrics
|
529 |
.filter((metric) => selectedOverallMetrics.has(metric))
|
530 |
.map((metric) => (
|
@@ -535,7 +640,7 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
535 |
return (
|
536 |
<th
|
537 |
key={`${metric}-${model}`}
|
538 |
-
className="sticky top-12 bg-base-100 z-10 text-center text-xs border
|
539 |
onClick={() => handleSort(metric, model)}
|
540 |
>
|
541 |
{model}
|
@@ -599,7 +704,7 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
599 |
className="bg-base-200 cursor-pointer hover:bg-base-300"
|
600 |
onClick={() => toggleGroup(group)}
|
601 |
>
|
602 |
-
<td className="sticky left-0 bg-base-200 z-10 font-medium
|
603 |
<span>{openGroupRows[group] ? '▼ ' : '▶ '}</span>
|
604 |
<span className="flex-1">{group}</span>
|
605 |
{/* Sort icon: only this triggers sort, and shows default if unsorted */}
|
@@ -671,13 +776,13 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
671 |
<React.Fragment key={`${group}-${subGroup}`}>
|
672 |
{/* Subgroup row with average stats for the subgroup */}
|
673 |
<tr
|
674 |
-
className="bg-base-100
|
675 |
-
onClick={() => toggleSubGroup(group, subGroup)}
|
676 |
>
|
677 |
-
<td className="sticky left-0 bg-base-100 z-10 pl-6 font-medium
|
678 |
-
<span>
|
679 |
{openSubGroupRows[group]?.[subGroup] ? '▼ ' : '▶ '}
|
680 |
-
</span>
|
681 |
<span className="flex-1">{subGroup}</span>
|
682 |
<span
|
683 |
className="ml-1 cursor-pointer"
|
@@ -739,223 +844,6 @@ const LeaderboardTable: React.FC<LeaderboardTableProps> = ({ benchmarkData, sele
|
|
739 |
</tr>
|
740 |
|
741 |
{/* Individual metric rows */}
|
742 |
-
{openSubGroupRows[group]?.[subGroup] &&
|
743 |
-
(() => {
|
744 |
-
// Sorting logic for individual metric rows
|
745 |
-
const sortConfig = getSortConfig()
|
746 |
-
let sortedMetrics = [...visibleSubgroupMetrics]
|
747 |
-
console.log(
|
748 |
-
'Sorting metrics for subgroup:',
|
749 |
-
group,
|
750 |
-
subGroup,
|
751 |
-
'with config:',
|
752 |
-
sortConfig
|
753 |
-
)
|
754 |
-
if (sortConfig) {
|
755 |
-
// Only sort metrics that match the selected overallMetric and model
|
756 |
-
const allMetricsWithName = findAllMetricsForName(
|
757 |
-
sortConfig.overallMetric
|
758 |
-
)
|
759 |
-
const metricsInSubgroupForThisMetric = sortedMetrics.filter(
|
760 |
-
(m) => allMetricsWithName.includes(m)
|
761 |
-
)
|
762 |
-
const metricsNotInSubgroupForThisMetric =
|
763 |
-
sortedMetrics.filter(
|
764 |
-
(m) => !allMetricsWithName.includes(m)
|
765 |
-
)
|
766 |
-
// Only apply subcolumn sort to matching metrics, leave others in original order
|
767 |
-
sortedMetrics = [
|
768 |
-
...sortRowsBySubcolumn(
|
769 |
-
metricsInSubgroupForThisMetric,
|
770 |
-
sortConfig.overallMetric,
|
771 |
-
sortConfig.model,
|
772 |
-
sortConfig.direction
|
773 |
-
),
|
774 |
-
...metricsNotInSubgroupForThisMetric,
|
775 |
-
]
|
776 |
-
} else {
|
777 |
-
// Fallback sort logic (category, overall, strength)
|
778 |
-
sortedMetrics = sortedMetrics.sort((a, b) => {
|
779 |
-
// For metrics with format {category}_{strength}_{overall_metric_name},
|
780 |
-
// First sort by category, then by overall_metric_name, then by strength
|
781 |
-
|
782 |
-
// First extract the overall metric group
|
783 |
-
const getOverallMetricGroup = (metric: string) => {
|
784 |
-
for (const overall of overallMetrics) {
|
785 |
-
if (
|
786 |
-
metric.endsWith(`_${overall}`) ||
|
787 |
-
metric === overall
|
788 |
-
) {
|
789 |
-
return overall
|
790 |
-
}
|
791 |
-
}
|
792 |
-
return ''
|
793 |
-
}
|
794 |
-
|
795 |
-
const overallA = getOverallMetricGroup(a)
|
796 |
-
const overallB = getOverallMetricGroup(b)
|
797 |
-
|
798 |
-
// Extract the strength (last part before the overall metric)
|
799 |
-
const stripOverall = (
|
800 |
-
metric: string,
|
801 |
-
overall: string
|
802 |
-
) => {
|
803 |
-
if (metric.endsWith(`_${overall}`)) {
|
804 |
-
// Remove the overall metric group and any preceding underscore
|
805 |
-
const stripped = metric.slice(
|
806 |
-
0,
|
807 |
-
metric.length - overall.length - 1
|
808 |
-
)
|
809 |
-
const parts = stripped.split('_')
|
810 |
-
return parts.length > 0 ? parts[parts.length - 1] : ''
|
811 |
-
}
|
812 |
-
return metric
|
813 |
-
}
|
814 |
-
|
815 |
-
// Extract the category (what remains after removing strength and overall_metric_name)
|
816 |
-
const getCategory = (metric: string, overall: string) => {
|
817 |
-
if (metric.endsWith(`_${overall}`)) {
|
818 |
-
const stripped = metric.slice(
|
819 |
-
0,
|
820 |
-
metric.length - overall.length - 1
|
821 |
-
)
|
822 |
-
const parts = stripped.split('_')
|
823 |
-
// Remove the last part (strength) and join the rest (category)
|
824 |
-
return parts.length > 1
|
825 |
-
? parts.slice(0, parts.length - 1).join('_')
|
826 |
-
: ''
|
827 |
-
}
|
828 |
-
return metric
|
829 |
-
}
|
830 |
-
|
831 |
-
const categoryA = getCategory(a, overallA)
|
832 |
-
const categoryB = getCategory(b, overallB)
|
833 |
-
|
834 |
-
// First sort by category
|
835 |
-
if (categoryA !== categoryB) {
|
836 |
-
return categoryA.localeCompare(categoryB)
|
837 |
-
}
|
838 |
-
|
839 |
-
// Then sort by overall metric name
|
840 |
-
if (overallA !== overallB) {
|
841 |
-
return overallA.localeCompare(overallB)
|
842 |
-
}
|
843 |
-
|
844 |
-
// Finally sort by strength
|
845 |
-
const subA = stripOverall(a, overallA)
|
846 |
-
const subB = stripOverall(b, overallB)
|
847 |
-
|
848 |
-
// Try to parse subA and subB as numbers, handling k/m/b suffixes
|
849 |
-
const parseNumber = (str: string) => {
|
850 |
-
const match = str.match(/^\d+(?:\.\d+)?([kKmMbB]?)$/)
|
851 |
-
if (!match) return NaN
|
852 |
-
let [_, suffix] = match
|
853 |
-
let value = parseFloat(str)
|
854 |
-
switch (suffix?.toLowerCase()) {
|
855 |
-
case 'k':
|
856 |
-
value *= 1e3
|
857 |
-
break
|
858 |
-
case 'm':
|
859 |
-
value *= 1e6
|
860 |
-
break
|
861 |
-
case 'b':
|
862 |
-
value *= 1e9
|
863 |
-
break
|
864 |
-
}
|
865 |
-
return value
|
866 |
-
}
|
867 |
-
|
868 |
-
const numA = parseNumber(subA)
|
869 |
-
const numB = parseNumber(subB)
|
870 |
-
|
871 |
-
if (!isNaN(numA) && !isNaN(numB)) {
|
872 |
-
return numA - numB
|
873 |
-
}
|
874 |
-
// Fallback to string comparison if not both numbers
|
875 |
-
return subA.localeCompare(subB)
|
876 |
-
})
|
877 |
-
}
|
878 |
-
return sortedMetrics.map((metric) => {
|
879 |
-
const row = tableRows.find((r) => r.metric === metric)
|
880 |
-
if (!row) return null
|
881 |
-
|
882 |
-
// Extract the metric name (after the underscore)
|
883 |
-
const metricName = metric.includes('_')
|
884 |
-
? metric.split('_').slice(1).join('_')
|
885 |
-
: metric
|
886 |
-
|
887 |
-
return (
|
888 |
-
<tr key={metric} className="hover:bg-base-100">
|
889 |
-
<td className="sticky left-0 bg-base-100 z-10 pl-10 border-gray-700 border cursor-pointer select-none flex items-center gap-1">
|
890 |
-
<span className="flex-1">{metric}</span>
|
891 |
-
<span
|
892 |
-
className="ml-1 cursor-pointer"
|
893 |
-
onClick={(e) => {
|
894 |
-
e.stopPropagation()
|
895 |
-
handleColumnSort(group, subGroup, metric)
|
896 |
-
}}
|
897 |
-
title={
|
898 |
-
getRowColumnSort(group, subGroup, metric)
|
899 |
-
? getRowColumnSort(group, subGroup, metric)
|
900 |
-
?.direction === 'asc'
|
901 |
-
? 'Sort descending'
|
902 |
-
: 'Clear sort'
|
903 |
-
: 'Sort by this row'
|
904 |
-
}
|
905 |
-
>
|
906 |
-
{getRowColumnSort(group, subGroup, metric)
|
907 |
-
? getRowColumnSort(group, subGroup, metric)
|
908 |
-
?.direction === 'asc'
|
909 |
-
? '▲'
|
910 |
-
: '▼'
|
911 |
-
: '⇅'}
|
912 |
-
</span>
|
913 |
-
</td>
|
914 |
-
{overallMetrics
|
915 |
-
.filter((oMetric) =>
|
916 |
-
selectedOverallMetrics.has(oMetric)
|
917 |
-
)
|
918 |
-
.map((oMetric) => {
|
919 |
-
const isMatchingMetric =
|
920 |
-
findAllMetricsForName(oMetric).includes(metric)
|
921 |
-
if (!isMatchingMetric) {
|
922 |
-
return (
|
923 |
-
<React.Fragment key={`${metric}-${oMetric}`}>
|
924 |
-
{modelOrderByOverallMetric[oMetric].map(
|
925 |
-
(col) => (
|
926 |
-
<td
|
927 |
-
key={`${metric}-${oMetric}-${col}`}
|
928 |
-
className="text-center border-gray-700 border"
|
929 |
-
></td>
|
930 |
-
)
|
931 |
-
)}
|
932 |
-
</React.Fragment>
|
933 |
-
)
|
934 |
-
}
|
935 |
-
return (
|
936 |
-
<React.Fragment key={`${metric}-${oMetric}`}>
|
937 |
-
{modelOrderByOverallMetric[oMetric].map(
|
938 |
-
(col) => {
|
939 |
-
const cell = row[col]
|
940 |
-
return (
|
941 |
-
<td
|
942 |
-
key={`${metric}-${oMetric}-${col}`}
|
943 |
-
className="text-center border-gray-700 border"
|
944 |
-
>
|
945 |
-
{!isNaN(Number(cell))
|
946 |
-
? Number(Number(cell).toFixed(3))
|
947 |
-
: cell}
|
948 |
-
</td>
|
949 |
-
)
|
950 |
-
}
|
951 |
-
)}
|
952 |
-
</React.Fragment>
|
953 |
-
)
|
954 |
-
})}
|
955 |
-
</tr>
|
956 |
-
)
|
957 |
-
})
|
958 |
-
})()}
|
959 |
</React.Fragment>
|
960 |
)
|
961 |
})}
|
|
|
1 |
import React, { useEffect, useState } from 'react'
|
2 |
+
import { ArrowDownTrayIcon } from '@heroicons/react/24/solid'
|
3 |
import LeaderboardFilter from './LeaderboardFilter'
|
4 |
import LoadingSpinner from './LoadingSpinner'
|
5 |
+
import QualityMetricsTable from './QualityMetricsTable'
|
6 |
|
7 |
interface LeaderboardTableProps {
|
8 |
benchmarkData: any
|
|
|
214 |
|
215 |
const getSortConfig = () => {
|
216 |
// Find the first sorted column (overallMetric, model)
|
|
|
217 |
for (const overallMetric of overallMetrics) {
|
218 |
if (!selectedOverallMetrics.has(overallMetric)) continue
|
219 |
const models = tableHeader.filter((model) => selectedModels.has(model))
|
|
|
253 |
const sortModelColumns = (models: string[], overallMetric: string): string[] => {
|
254 |
// Column sort takes precedence; if no column sort, return models in default order
|
255 |
const columnSortConfig = getColumnSortConfig()
|
|
|
256 |
if (columnSortConfig && columnSortConfig.overallMetric === overallMetric) {
|
257 |
// Sort by average value for each model in this overallMetric
|
258 |
return [...models].sort((a, b) => {
|
|
|
310 |
}
|
311 |
|
312 |
// Identify metrics that don't belong to any overall metric group
|
313 |
+
const findQualityMetrics = (): string[] => {
|
314 |
// Get all metrics from the table rows
|
315 |
const allMetrics = tableRows.map((row) => row.metric as string)
|
316 |
|
|
|
468 |
)
|
469 |
})
|
470 |
|
|
|
|
|
471 |
return (
|
472 |
<div className="rounded">
|
473 |
{error && <div className="text-red-500">{error}</div>}
|
|
|
479 |
selectedOverallMetrics={selectedOverallMetrics}
|
480 |
setSelectedOverallMetrics={setSelectedOverallMetrics}
|
481 |
/>
|
482 |
+
{/* <LeaderboardFilter
|
483 |
groups={groupRows}
|
484 |
selectedMetrics={selectedMetrics}
|
485 |
setSelectedMetrics={setSelectedMetrics}
|
486 |
+
/> */}
|
487 |
</div>
|
488 |
|
489 |
{selectedModels.size === 0 || selectedMetrics.size === 0 ? (
|
|
|
492 |
</div>
|
493 |
) : (
|
494 |
<>
|
495 |
+
{/* Quality metrics table */}
|
496 |
+
<QualityMetricsTable
|
497 |
+
qualityMetrics={findQualityMetrics()}
|
498 |
tableHeader={tableHeader}
|
499 |
selectedModels={selectedModels}
|
500 |
tableRows={tableRows}
|
501 |
/>
|
502 |
|
503 |
{/* Main metrics table */}
|
504 |
+
<div className="relative flex justify-end mb-2">
|
505 |
+
<button
|
506 |
+
className="absolute top-0 right-0 btn btn-ghost btn-circle"
|
507 |
+
title="Export CSV"
|
508 |
+
onClick={() => {
|
509 |
+
// Export the main metrics table as displayed
|
510 |
+
// Build header row
|
511 |
+
const visibleMetrics = overallMetrics.filter((metric) =>
|
512 |
+
selectedOverallMetrics.has(metric)
|
513 |
+
)
|
514 |
+
const header = [
|
515 |
+
'Attack Categories',
|
516 |
+
...visibleMetrics.flatMap((metric) => modelOrderByOverallMetric[metric]),
|
517 |
+
]
|
518 |
+
// Build data rows
|
519 |
+
const rows: (string | number)[][] = []
|
520 |
+
groupEntries.forEach(([group, subGroups]) => {
|
521 |
+
// Group row
|
522 |
+
const allGroupMetrics = Object.values(subGroups).flat()
|
523 |
+
const visibleGroupMetrics = filterMetricsByGroupAndSubgroup(
|
524 |
+
allGroupMetrics,
|
525 |
+
group
|
526 |
+
)
|
527 |
+
if (visibleGroupMetrics.length === 0) return
|
528 |
+
// Group row label
|
529 |
+
const groupRow: (string | number)[] = [group]
|
530 |
+
visibleMetrics.forEach((metric) => {
|
531 |
+
modelOrderByOverallMetric[metric].forEach((col) => {
|
532 |
+
const allMetricsWithName = findAllMetricsForName(metric)
|
533 |
+
const metricsInGroupForThisMetric = visibleGroupMetrics.filter((m) =>
|
534 |
+
allMetricsWithName.includes(m)
|
535 |
+
)
|
536 |
+
const stats = calculateStats(metricsInGroupForThisMetric, col)
|
537 |
+
groupRow.push(
|
538 |
+
!isNaN(stats.avg)
|
539 |
+
? `${stats.avg.toFixed(3)} ± ${stats.stdDev.toFixed(3)}`
|
540 |
+
: 'N/A'
|
541 |
+
)
|
542 |
+
})
|
543 |
+
})
|
544 |
+
rows.push(groupRow)
|
545 |
+
// Subgroup rows
|
546 |
+
let subGroupEntries = Object.entries(subGroups)
|
547 |
+
subGroupEntries.forEach(([subGroup, metrics]) => {
|
548 |
+
const visibleSubgroupMetrics = filterMetricsByGroupAndSubgroup(
|
549 |
+
metrics,
|
550 |
+
group,
|
551 |
+
subGroup
|
552 |
+
)
|
553 |
+
if (visibleSubgroupMetrics.length === 0) return
|
554 |
+
const subGroupRow: (string | number)[] = [' ' + subGroup] // Indent subgroup
|
555 |
+
visibleMetrics.forEach((metric) => {
|
556 |
+
modelOrderByOverallMetric[metric].forEach((col) => {
|
557 |
+
const allMetricsWithName = findAllMetricsForName(metric)
|
558 |
+
const metricsInSubgroupForThisMetric = visibleSubgroupMetrics.filter(
|
559 |
+
(m) => allMetricsWithName.includes(m)
|
560 |
+
)
|
561 |
+
const stats = calculateStats(metricsInSubgroupForThisMetric, col)
|
562 |
+
subGroupRow.push(
|
563 |
+
!isNaN(stats.avg)
|
564 |
+
? `${stats.avg.toFixed(3)} ± ${stats.stdDev.toFixed(3)}`
|
565 |
+
: 'N/A'
|
566 |
+
)
|
567 |
+
})
|
568 |
+
})
|
569 |
+
rows.push(subGroupRow)
|
570 |
+
// Individual metric rows
|
571 |
+
visibleSubgroupMetrics.forEach((metric) => {
|
572 |
+
const row = tableRows.find((r) => r.metric === metric)
|
573 |
+
if (!row) return
|
574 |
+
const metricRow: (string | number)[] = [' ' + metric] // Indent metric
|
575 |
+
visibleMetrics.forEach((oMetric) => {
|
576 |
+
if (!findAllMetricsForName(oMetric).includes(metric)) {
|
577 |
+
modelOrderByOverallMetric[oMetric].forEach(() => metricRow.push(''))
|
578 |
+
} else {
|
579 |
+
modelOrderByOverallMetric[oMetric].forEach((col) => {
|
580 |
+
const cell = row[col]
|
581 |
+
metricRow.push(
|
582 |
+
!isNaN(Number(cell)) ? Number(Number(cell).toFixed(3)) : cell
|
583 |
+
)
|
584 |
+
})
|
585 |
+
}
|
586 |
+
})
|
587 |
+
rows.push(metricRow)
|
588 |
+
})
|
589 |
+
})
|
590 |
+
})
|
591 |
+
// CSV encode
|
592 |
+
const csv = [header, ...rows]
|
593 |
+
.map((row) =>
|
594 |
+
row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')
|
595 |
+
)
|
596 |
+
.join('\n')
|
597 |
+
// Download
|
598 |
+
const blob = new Blob([csv], { type: 'text/csv' })
|
599 |
+
const url = URL.createObjectURL(blob)
|
600 |
+
const a = document.createElement('a')
|
601 |
+
a.href = url
|
602 |
+
a.download = 'leaderboard_metrics.csv'
|
603 |
+
document.body.appendChild(a)
|
604 |
+
a.click()
|
605 |
+
document.body.removeChild(a)
|
606 |
+
URL.revokeObjectURL(url)
|
607 |
+
}}
|
608 |
+
>
|
609 |
+
<ArrowDownTrayIcon className="h-6 w-6" />
|
610 |
+
</button>
|
611 |
+
</div>
|
612 |
<div className="overflow-x-auto max-h-[80vh] overflow-y-auto">
|
613 |
+
<table className="table w-full min-w-max border-separate border-spacing-0 border-gray-700 border">
|
614 |
<thead>
|
615 |
<tr>
|
616 |
+
<th className="sticky left-0 top-0 bg-base-100 z-20 border border-gray-700">
|
617 |
+
Attack Categories
|
618 |
</th>
|
619 |
{overallMetrics
|
620 |
.filter((metric) => selectedOverallMetrics.has(metric))
|
621 |
.map((metric) => (
|
622 |
<th
|
623 |
key={`header-metric-${metric}`}
|
624 |
+
className="sticky top-0 bg-base-100 z-10 text-center text-xs border border-gray-700 select-none"
|
625 |
colSpan={modelOrderByOverallMetric[metric].length}
|
626 |
>
|
627 |
{metric}
|
|
|
629 |
))}
|
630 |
</tr>
|
631 |
<tr>
|
632 |
+
<th className="sticky left-0 top-12 bg-base-100 z-30 border border-gray-700"></th>
|
633 |
{overallMetrics
|
634 |
.filter((metric) => selectedOverallMetrics.has(metric))
|
635 |
.map((metric) => (
|
|
|
640 |
return (
|
641 |
<th
|
642 |
key={`${metric}-${model}`}
|
643 |
+
className="sticky top-12 bg-base-100 z-10 text-center text-xs border border-gray-700 cursor-pointer select-none"
|
644 |
onClick={() => handleSort(metric, model)}
|
645 |
>
|
646 |
{model}
|
|
|
704 |
className="bg-base-200 cursor-pointer hover:bg-base-300"
|
705 |
onClick={() => toggleGroup(group)}
|
706 |
>
|
707 |
+
<td className="sticky left-0 bg-base-200 z-10 font-medium cursor-pointer select-none flex items-center">
|
708 |
<span>{openGroupRows[group] ? '▼ ' : '▶ '}</span>
|
709 |
<span className="flex-1">{group}</span>
|
710 |
{/* Sort icon: only this triggers sort, and shows default if unsorted */}
|
|
|
776 |
<React.Fragment key={`${group}-${subGroup}`}>
|
777 |
{/* Subgroup row with average stats for the subgroup */}
|
778 |
<tr
|
779 |
+
className="bg-base-100 hover:bg-base-200"
|
780 |
+
// onClick={() => toggleSubGroup(group, subGroup)}
|
781 |
>
|
782 |
+
<td className="sticky left-0 bg-base-100 z-10 pl-6 font-medium flex items-center gap-1">
|
783 |
+
{/* <span>
|
784 |
{openSubGroupRows[group]?.[subGroup] ? '▼ ' : '▶ '}
|
785 |
+
</span> */}
|
786 |
<span className="flex-1">{subGroup}</span>
|
787 |
<span
|
788 |
className="ml-1 cursor-pointer"
|
|
|
844 |
</tr>
|
845 |
|
846 |
{/* Individual metric rows */}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
</React.Fragment>
|
848 |
)
|
849 |
})}
|
frontend/src/components/LeaderboardTabs.tsx
ADDED
File without changes
|
frontend/src/components/QualityMetricsTable.tsx
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState } from 'react'
|
2 |
+
import { ArrowDownTrayIcon } from '@heroicons/react/24/outline'
|
3 |
+
|
4 |
+
interface Row {
|
5 |
+
metric: string
|
6 |
+
[key: string]: string | number
|
7 |
+
}
|
8 |
+
|
9 |
+
interface QualityMetricsTableProps {
|
10 |
+
qualityMetrics: string[]
|
11 |
+
tableHeader: string[]
|
12 |
+
selectedModels: Set<string>
|
13 |
+
tableRows: Row[]
|
14 |
+
}
|
15 |
+
|
16 |
+
const QualityMetricsTable: React.FC<QualityMetricsTableProps> = ({
|
17 |
+
qualityMetrics,
|
18 |
+
tableHeader,
|
19 |
+
selectedModels,
|
20 |
+
tableRows,
|
21 |
+
}) => {
|
22 |
+
// Sorting state
|
23 |
+
const [rowSort, setRowSort] = useState<{ metric: string; direction: 'asc' | 'desc' } | null>(null)
|
24 |
+
const [columnSort, setColumnSort] = useState<{ model: string; direction: 'asc' | 'desc' } | null>(
|
25 |
+
null
|
26 |
+
)
|
27 |
+
|
28 |
+
// Handle row sort (sort columns by this metric)
|
29 |
+
const handleRowSort = (metric: string) => {
|
30 |
+
setColumnSort(null) // Only one sort active at a time
|
31 |
+
setRowSort((prev) => {
|
32 |
+
if (!prev || prev.metric !== metric) return { metric, direction: 'asc' }
|
33 |
+
if (prev.direction === 'asc') return { metric, direction: 'desc' }
|
34 |
+
return null // Remove sort
|
35 |
+
})
|
36 |
+
}
|
37 |
+
|
38 |
+
// Handle column sort (sort rows by this model)
|
39 |
+
const handleColumnSort = (model: string) => {
|
40 |
+
setRowSort(null) // Only one sort active at a time
|
41 |
+
setColumnSort((prev) => {
|
42 |
+
if (!prev || prev.model !== model) return { model, direction: 'asc' }
|
43 |
+
if (prev.direction === 'asc') return { model, direction: 'desc' }
|
44 |
+
return null // Remove sort
|
45 |
+
})
|
46 |
+
}
|
47 |
+
|
48 |
+
// Sort models (columns)
|
49 |
+
let sortedModels = tableHeader.filter((model) => selectedModels.has(model))
|
50 |
+
if (rowSort) {
|
51 |
+
// Sort columns by the value in the selected metric row
|
52 |
+
sortedModels = [...sortedModels].sort((a, b) => {
|
53 |
+
const row = tableRows.find((r) => r.metric === rowSort.metric)
|
54 |
+
if (!row) return 0
|
55 |
+
const valA = Number(row[a])
|
56 |
+
const valB = Number(row[b])
|
57 |
+
if (isNaN(valA) && isNaN(valB)) return 0
|
58 |
+
if (isNaN(valA)) return 1
|
59 |
+
if (isNaN(valB)) return -1
|
60 |
+
return rowSort.direction === 'asc' ? valA - valB : valB - valA
|
61 |
+
})
|
62 |
+
}
|
63 |
+
|
64 |
+
// Sort metrics (rows)
|
65 |
+
let sortedMetrics = [...qualityMetrics]
|
66 |
+
if (columnSort) {
|
67 |
+
// Sort rows by the value in the selected model column
|
68 |
+
sortedMetrics = [...sortedMetrics].sort((a, b) => {
|
69 |
+
const rowA = tableRows.find((r) => r.metric === a)
|
70 |
+
const rowB = tableRows.find((r) => r.metric === b)
|
71 |
+
if (!rowA || !rowB) return 0
|
72 |
+
const valA = Number(rowA[columnSort.model])
|
73 |
+
const valB = Number(rowB[columnSort.model])
|
74 |
+
if (isNaN(valA) && isNaN(valB)) return 0
|
75 |
+
if (isNaN(valA)) return 1
|
76 |
+
if (isNaN(valB)) return -1
|
77 |
+
return columnSort.direction === 'asc' ? valA - valB : valB - valA
|
78 |
+
})
|
79 |
+
}
|
80 |
+
|
81 |
+
// CSV export logic
|
82 |
+
function exportToCSV() {
|
83 |
+
// Build header row
|
84 |
+
const header = ['Metric', ...sortedModels]
|
85 |
+
// Build data rows
|
86 |
+
const rows = sortedMetrics
|
87 |
+
.map((metric) => {
|
88 |
+
const row = tableRows.find((r) => r.metric === metric)
|
89 |
+
if (!row) return null
|
90 |
+
return [
|
91 |
+
metric,
|
92 |
+
...sortedModels.map((col) => {
|
93 |
+
const cell = row[col]
|
94 |
+
// Format as displayed
|
95 |
+
return !isNaN(Number(cell)) ? Number(Number(cell).toFixed(3)) : cell
|
96 |
+
}),
|
97 |
+
]
|
98 |
+
})
|
99 |
+
.filter((row): row is (string | number)[] => !!row)
|
100 |
+
// Combine
|
101 |
+
const csv = [header, ...rows]
|
102 |
+
.map((row) => row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(','))
|
103 |
+
.join('\n')
|
104 |
+
// Download
|
105 |
+
const blob = new Blob([csv], { type: 'text/csv' })
|
106 |
+
const url = URL.createObjectURL(blob)
|
107 |
+
const a = document.createElement('a')
|
108 |
+
a.href = url
|
109 |
+
a.download = 'quality_metrics.csv'
|
110 |
+
document.body.appendChild(a)
|
111 |
+
a.click()
|
112 |
+
document.body.removeChild(a)
|
113 |
+
URL.revokeObjectURL(url)
|
114 |
+
}
|
115 |
+
|
116 |
+
if (qualityMetrics.length === 0) return null
|
117 |
+
return (
|
118 |
+
<div className="overflow-x-auto max-h-[80vh] overflow-y-auto">
|
119 |
+
<div className="flex justify-end mb-2">
|
120 |
+
<button className="btn btn-ghost btn-circle" title="Export CSV" onClick={exportToCSV}>
|
121 |
+
<ArrowDownTrayIcon className="h-6 w-6" />
|
122 |
+
</button>
|
123 |
+
</div>
|
124 |
+
<table className="table w-full min-w-max border-gray-700 border">
|
125 |
+
<thead>
|
126 |
+
<tr>
|
127 |
+
<th className="sticky left-0 top-0 bg-base-100 z-20 border-gray-700 border">Metric</th>
|
128 |
+
{sortedModels.map((model) => {
|
129 |
+
const isSorted = columnSort && columnSort.model === model
|
130 |
+
const direction = isSorted ? columnSort.direction : undefined
|
131 |
+
return (
|
132 |
+
<th
|
133 |
+
key={`quality-${model}`}
|
134 |
+
className="sticky top-0 bg-base-100 z-10 text-center text-xs border-gray-700 border cursor-pointer select-none"
|
135 |
+
onClick={() => handleColumnSort(model)}
|
136 |
+
title={
|
137 |
+
isSorted
|
138 |
+
? direction === 'asc'
|
139 |
+
? 'Sort descending'
|
140 |
+
: 'Clear sort'
|
141 |
+
: 'Sort by this column'
|
142 |
+
}
|
143 |
+
>
|
144 |
+
{model}
|
145 |
+
<span className="ml-1">{isSorted ? (direction === 'asc' ? '↑' : '↓') : '⇅'}</span>
|
146 |
+
</th>
|
147 |
+
)
|
148 |
+
})}
|
149 |
+
</tr>
|
150 |
+
</thead>
|
151 |
+
<tbody>
|
152 |
+
{sortedMetrics.map((metric) => {
|
153 |
+
const row = tableRows.find((r) => r.metric === metric)
|
154 |
+
if (!row) return null
|
155 |
+
const isSorted = rowSort && rowSort.metric === metric
|
156 |
+
const direction = isSorted ? rowSort.direction : undefined
|
157 |
+
return (
|
158 |
+
<tr key={`quality-${metric}`} className="hover:bg-base-100">
|
159 |
+
<td
|
160 |
+
className="sticky left-0 bg-base-100 z-10 border-gray-700 border cursor-pointer select-none"
|
161 |
+
onClick={() => handleRowSort(metric)}
|
162 |
+
title={
|
163 |
+
isSorted
|
164 |
+
? direction === 'asc'
|
165 |
+
? 'Sort descending'
|
166 |
+
: 'Clear sort'
|
167 |
+
: 'Sort by this row (sorts columns)'
|
168 |
+
}
|
169 |
+
>
|
170 |
+
{metric}
|
171 |
+
<span className="ml-1">{isSorted ? (direction === 'asc' ? '↑' : '↓') : '⇅'}</span>
|
172 |
+
</td>
|
173 |
+
{sortedModels.map((col) => {
|
174 |
+
const cell = row[col]
|
175 |
+
return (
|
176 |
+
<td
|
177 |
+
key={`quality-${metric}-${col}`}
|
178 |
+
className="text-center border-gray-700 border"
|
179 |
+
>
|
180 |
+
{!isNaN(Number(cell)) ? Number(Number(cell).toFixed(3)) : cell}
|
181 |
+
</td>
|
182 |
+
)
|
183 |
+
})}
|
184 |
+
</tr>
|
185 |
+
)
|
186 |
+
})}
|
187 |
+
</tbody>
|
188 |
+
</table>
|
189 |
+
</div>
|
190 |
+
)
|
191 |
+
}
|
192 |
+
|
193 |
+
export default QualityMetricsTable
|
tests/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Unit Tests for OmniSealBench
|
2 |
+
|
3 |
+
This directory contains unit tests for the OmniSealBench application.
|
4 |
+
|
5 |
+
## Setup
|
6 |
+
|
7 |
+
Before running the tests, make sure you have installed the required dependencies:
|
8 |
+
|
9 |
+
```bash
|
10 |
+
# Install pytest and other testing dependencies
|
11 |
+
pip install pytest pytest-cov
|
12 |
+
|
13 |
+
# If you're using the environment.yml file
|
14 |
+
conda env update -f backend/environment.yml
|
15 |
+
```
|
16 |
+
|
17 |
+
## Running Tests
|
18 |
+
|
19 |
+
To run all tests:
|
20 |
+
|
21 |
+
```bash
|
22 |
+
# From the project root directory
|
23 |
+
pytest tests/
|
24 |
+
|
25 |
+
# With coverage report
|
26 |
+
pytest tests/ --cov=backend
|
27 |
+
```
|
28 |
+
|
29 |
+
To run a specific test file:
|
30 |
+
|
31 |
+
```bash
|
32 |
+
pytest tests/test_app.py
|
33 |
+
```
|
34 |
+
|
35 |
+
To run a specific test function:
|
36 |
+
|
37 |
+
```bash
|
38 |
+
pytest tests/test_app.py::test_index_route
|
39 |
+
```
|
40 |
+
|
41 |
+
## Test Structure
|
42 |
+
|
43 |
+
- `test_app.py`: Tests for the Flask application routes and helper functions
|
44 |
+
- `conftest.py`: Shared pytest fixtures for all test files
|
45 |
+
- `__init__.py`: Makes the tests directory a Python package for better test discovery
|
46 |
+
|
47 |
+
## Mocking
|
48 |
+
|
49 |
+
The tests use `unittest.mock` to mock external dependencies like:
|
50 |
+
- File operations (reading CSV files)
|
51 |
+
- API calls (requests.get)
|
52 |
+
- Database connections
|
53 |
+
|
54 |
+
This ensures tests are isolated and don't depend on external services.
|
55 |
+
|
56 |
+
## Adding New Tests
|
57 |
+
|
58 |
+
When adding new tests:
|
59 |
+
|
60 |
+
1. Create a new test file if testing a new module
|
61 |
+
2. Use descriptive test function names (e.g., `test_data_files_benchmark`)
|
62 |
+
3. Add docstrings to explain what each test is checking
|
63 |
+
4. Use fixtures from `conftest.py` when appropriate
|
64 |
+
5. Mock external dependencies to ensure tests are isolated
|
tests/__init__.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
# This file makes the tests directory a Python package
|
2 |
+
# It allows for better test discovery and organization
|
tests/conftest.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
This file contains shared pytest fixtures for all test files.
|
3 |
+
Fixtures defined here are automatically available to all test files.
|
4 |
+
"""
|
5 |
+
|
6 |
+
import pytest
|
7 |
+
import os
|
8 |
+
import sys
|
9 |
+
from flask import Flask
|
10 |
+
|
11 |
+
# Add the parent directory to sys.path to allow importing from the backend package
|
12 |
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
13 |
+
|
14 |
+
# Import the Flask app for testing
|
15 |
+
from backend.app import app
|
16 |
+
|
17 |
+
|
18 |
+
@pytest.fixture
|
19 |
+
def client():
|
20 |
+
"""Create a test client for the Flask app."""
|
21 |
+
app.config['TESTING'] = True
|
22 |
+
with app.test_client() as client:
|
23 |
+
yield client
|
24 |
+
|
25 |
+
|
26 |
+
@pytest.fixture
|
27 |
+
def app_context():
|
28 |
+
"""Create an application context for the Flask app."""
|
29 |
+
with app.app_context():
|
30 |
+
yield
|
tests/test_app.py
ADDED
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import os
|
3 |
+
import pytest
|
4 |
+
from unittest.mock import patch, MagicMock, mock_open
|
5 |
+
import pandas as pd
|
6 |
+
from io import StringIO
|
7 |
+
from flask import Flask
|
8 |
+
|
9 |
+
# Import the Flask app and other necessary modules
|
10 |
+
from backend.app import app, get_leaderboard, get_chart
|
11 |
+
|
12 |
+
|
13 |
+
@pytest.fixture
|
14 |
+
def client():
|
15 |
+
"""Create a test client for the Flask app."""
|
16 |
+
app.config['TESTING'] = True
|
17 |
+
with app.test_client() as client:
|
18 |
+
yield client
|
19 |
+
|
20 |
+
|
21 |
+
def test_index_route(client):
|
22 |
+
"""Test the index route returns the index.html file."""
|
23 |
+
with patch('backend.app.send_from_directory') as mock_send:
|
24 |
+
mock_send.return_value = "index content"
|
25 |
+
response = client.get('/')
|
26 |
+
assert response.status_code == 200
|
27 |
+
mock_send.assert_called_once_with(app.static_folder, "index.html")
|
28 |
+
|
29 |
+
|
30 |
+
@patch('backend.app.pd.read_csv')
|
31 |
+
@patch('backend.app.get_dataset_config')
|
32 |
+
@patch('backend.app.get_leaderboard')
|
33 |
+
def test_data_files_benchmark(mock_get_leaderboard, mock_get_config, mock_read_csv, client):
|
34 |
+
"""Test the data_files route with benchmark dataset type."""
|
35 |
+
# Mock the DataFrame and config
|
36 |
+
mock_df = pd.DataFrame({'model': ['model1', 'model2'], 'score': [0.9, 0.8]})
|
37 |
+
mock_read_csv.return_value = mock_df
|
38 |
+
mock_config = {'name': 'test_dataset'}
|
39 |
+
mock_get_config.return_value = mock_config
|
40 |
+
mock_get_leaderboard.return_value = "leaderboard data"
|
41 |
+
|
42 |
+
# Make the request
|
43 |
+
response = client.get('/data/test_dataset?dataset_type=benchmark')
|
44 |
+
|
45 |
+
# Assertions
|
46 |
+
mock_read_csv.assert_called_once()
|
47 |
+
mock_get_config.assert_called_once_with('test_dataset')
|
48 |
+
mock_get_leaderboard.assert_called_once_with(mock_config, mock_df)
|
49 |
+
assert response == "leaderboard data"
|
50 |
+
|
51 |
+
|
52 |
+
@patch('backend.app.pd.read_csv')
|
53 |
+
@patch('backend.app.get_dataset_config')
|
54 |
+
@patch('backend.app.get_chart')
|
55 |
+
def test_data_files_attacks_variations(mock_get_chart, mock_get_config, mock_read_csv, client):
|
56 |
+
"""Test the data_files route with attacks_variations dataset type."""
|
57 |
+
# Mock the DataFrame and config
|
58 |
+
mock_df = pd.DataFrame({'model': ['model1', 'model2'], 'attack': ['a1', 'a2']})
|
59 |
+
mock_read_csv.return_value = mock_df
|
60 |
+
mock_config = {'name': 'test_dataset'}
|
61 |
+
mock_get_config.return_value = mock_config
|
62 |
+
mock_get_chart.return_value = "chart data"
|
63 |
+
|
64 |
+
# Make the request
|
65 |
+
response = client.get('/data/test_dataset?dataset_type=attacks_variations')
|
66 |
+
|
67 |
+
# Assertions
|
68 |
+
mock_read_csv.assert_called_once()
|
69 |
+
mock_get_config.assert_called_once_with('test_dataset')
|
70 |
+
mock_get_chart.assert_called_once_with(mock_config, mock_df)
|
71 |
+
assert response == "chart data"
|
72 |
+
|
73 |
+
|
74 |
+
def test_data_files_missing_dataset_type(client):
|
75 |
+
"""Test the data_files route with missing dataset_type."""
|
76 |
+
response = client.get('/data/test_dataset')
|
77 |
+
assert response.status_code == 400
|
78 |
+
assert b"Dataset type not specified" in response.data
|
79 |
+
|
80 |
+
|
81 |
+
@patch('backend.app.pd.read_csv')
|
82 |
+
def test_data_files_file_not_found(mock_read_csv, client):
|
83 |
+
"""Test the data_files route when file is not found."""
|
84 |
+
mock_read_csv.side_effect = FileNotFoundError()
|
85 |
+
|
86 |
+
response = client.get('/data/test_dataset?dataset_type=benchmark')
|
87 |
+
|
88 |
+
assert response.status_code == 404
|
89 |
+
assert b"File not found" in response.data
|
90 |
+
|
91 |
+
|
92 |
+
@patch('backend.app.image_examples_tab')
|
93 |
+
def test_example_files_image(mock_image_examples, client):
|
94 |
+
"""Test the example_files route with image type."""
|
95 |
+
mock_image_examples.return_value = {"examples": ["image1", "image2"]}
|
96 |
+
|
97 |
+
response = client.get('/examples/image')
|
98 |
+
|
99 |
+
assert response.status_code == 200
|
100 |
+
data = json.loads(response.data)
|
101 |
+
assert "examples" in data
|
102 |
+
mock_image_examples.assert_called_once()
|
103 |
+
|
104 |
+
|
105 |
+
@patch('backend.app.audio_examples_tab')
|
106 |
+
def test_example_files_audio(mock_audio_examples, client):
|
107 |
+
"""Test the example_files route with audio type."""
|
108 |
+
mock_audio_examples.return_value = {"examples": ["audio1", "audio2"]}
|
109 |
+
|
110 |
+
response = client.get('/examples/audio')
|
111 |
+
|
112 |
+
assert response.status_code == 200
|
113 |
+
data = json.loads(response.data)
|
114 |
+
assert "examples" in data
|
115 |
+
mock_audio_examples.assert_called_once()
|
116 |
+
|
117 |
+
|
118 |
+
@patch('backend.app.video_examples_tab')
|
119 |
+
def test_example_files_video(mock_video_examples, client):
|
120 |
+
"""Test the example_files route with video type."""
|
121 |
+
mock_video_examples.return_value = {"examples": ["video1", "video2"]}
|
122 |
+
|
123 |
+
response = client.get('/examples/video')
|
124 |
+
|
125 |
+
assert response.status_code == 200
|
126 |
+
data = json.loads(response.data)
|
127 |
+
assert "examples" in data
|
128 |
+
mock_video_examples.assert_called_once()
|
129 |
+
|
130 |
+
|
131 |
+
def test_example_files_invalid_type(client):
|
132 |
+
"""Test the example_files route with invalid type."""
|
133 |
+
response = client.get('/examples/invalid')
|
134 |
+
|
135 |
+
assert response.status_code == 400
|
136 |
+
assert b"Invalid example type" in response.data
|
137 |
+
|
138 |
+
|
139 |
+
@patch('backend.app.requests.get')
|
140 |
+
def test_proxy_valid_url(mock_requests_get, client):
|
141 |
+
"""Test the proxy route with a valid URL."""
|
142 |
+
# Create a mock response
|
143 |
+
mock_response = MagicMock()
|
144 |
+
mock_response.status_code = 200
|
145 |
+
mock_response.content = b"test content"
|
146 |
+
mock_response.headers = {"Content-Type": "text/plain"}
|
147 |
+
mock_requests_get.return_value = mock_response
|
148 |
+
|
149 |
+
# Mock the ABS_DATASET_DOMAIN constant
|
150 |
+
with patch('backend.app.ABS_DATASET_DOMAIN', 'https://example.com'):
|
151 |
+
response = client.get('/proxy/https%3A%2F%2Fexample.com%2Ftest.txt')
|
152 |
+
|
153 |
+
assert response.status_code == 200
|
154 |
+
assert response.data == b"test content"
|
155 |
+
mock_requests_get.assert_called_once()
|
156 |
+
|
157 |
+
|
158 |
+
@patch('backend.app.requests.get')
|
159 |
+
def test_proxy_invalid_domain(mock_requests_get, client):
|
160 |
+
"""Test the proxy route with an invalid domain."""
|
161 |
+
# Mock the ABS_DATASET_DOMAIN constant
|
162 |
+
with patch('backend.app.ABS_DATASET_DOMAIN', 'https://example.com'):
|
163 |
+
response = client.get('/proxy/https%3A%2F%2Fmalicious.com%2Ftest.txt')
|
164 |
+
|
165 |
+
assert response.status_code == 403
|
166 |
+
data = json.loads(response.data)
|
167 |
+
assert "error" in data
|
168 |
+
mock_requests_get.assert_not_called()
|
169 |
+
|
170 |
+
|
171 |
+
@patch('backend.app.requests.get')
|
172 |
+
def test_proxy_request_error(mock_requests_get, client):
|
173 |
+
"""Test the proxy route when the request fails."""
|
174 |
+
mock_requests_get.side_effect = Exception("Connection error")
|
175 |
+
|
176 |
+
# Mock the ABS_DATASET_DOMAIN constant
|
177 |
+
with patch('backend.app.ABS_DATASET_DOMAIN', 'https://example.com'):
|
178 |
+
response = client.get('/proxy/https%3A%2F%2Fexample.com%2Ftest.txt')
|
179 |
+
|
180 |
+
assert response.status_code == 500
|
181 |
+
data = json.loads(response.data)
|
182 |
+
assert "error" in data
|
183 |
+
|
184 |
+
|
185 |
+
@patch('backend.app.get_old_format_dataframe')
|
186 |
+
@patch('backend.app.get_leaderboard_filters')
|
187 |
+
def test_get_leaderboard(mock_get_filters, mock_get_old_format):
|
188 |
+
"""Test the get_leaderboard function."""
|
189 |
+
# Mock the input data
|
190 |
+
df = pd.DataFrame({'model': ['model1', 'model2'], 'score': [0.9, 0.8]})
|
191 |
+
config = {
|
192 |
+
'first_cols': ['model'],
|
193 |
+
'attack_scores': ['score'],
|
194 |
+
'categories': ['category1']
|
195 |
+
}
|
196 |
+
|
197 |
+
# Mock the function returns
|
198 |
+
mock_get_old_format.return_value = df
|
199 |
+
mock_get_filters.return_value = (
|
200 |
+
{'group1': ['metric1', 'metric2']},
|
201 |
+
['metric1']
|
202 |
+
)
|
203 |
+
|
204 |
+
# Call the function
|
205 |
+
response = get_leaderboard(config, df)
|
206 |
+
|
207 |
+
# Assertions
|
208 |
+
assert response.status_code == 200
|
209 |
+
data = json.loads(response.data)
|
210 |
+
assert 'groups' in data
|
211 |
+
assert 'default_selected_metrics' in data
|
212 |
+
assert 'rows' in data
|
213 |
+
mock_get_old_format.assert_called_once_with(df, config['first_cols'], config['attack_scores'])
|
214 |
+
mock_get_filters.assert_called_once_with(df, config['categories'])
|
215 |
+
|
216 |
+
|
217 |
+
@patch('backend.app.mk_variations')
|
218 |
+
def test_get_chart(mock_mk_variations):
|
219 |
+
"""Test the get_chart function."""
|
220 |
+
# Mock the input data
|
221 |
+
df = pd.DataFrame({'model': ['model1', 'model2'], 'attack': ['a1', 'a2']})
|
222 |
+
config = {
|
223 |
+
'attacks_with_variations': ['attack1', 'attack2']
|
224 |
+
}
|
225 |
+
|
226 |
+
# Mock the function return
|
227 |
+
mock_chart_data = {'chart': 'data'}
|
228 |
+
mock_mk_variations.return_value = mock_chart_data
|
229 |
+
|
230 |
+
# Call the function
|
231 |
+
response = get_chart(config, df)
|
232 |
+
|
233 |
+
# Assertions
|
234 |
+
assert response.status_code == 200
|
235 |
+
data = json.loads(response.data)
|
236 |
+
assert data == mock_chart_data
|
237 |
+
mock_mk_variations.assert_called_once_with(df, config['attacks_with_variations'])
|
238 |
+
|
239 |
+
|
240 |
+
# Add a test for the main function
|
241 |
+
def test_main():
|
242 |
+
"""Test the main function."""
|
243 |
+
with patch('backend.app.app.run') as mock_run:
|
244 |
+
# We can't directly test __main__ block, but we can test the app.run call
|
245 |
+
# by importing and calling it in a test context
|
246 |
+
import backend.app
|
247 |
+
if hasattr(backend.app, 'main'): # If main function exists
|
248 |
+
backend.app.main()
|
249 |
+
mock_run.assert_called_once_with(host="0.0.0.0", port=7860, debug=True, use_reloader=True)
|