From 82931328f8539d94cb951cfcdacd95cd2a2f9eab Mon Sep 17 00:00:00 2001 From: James Brooks Date: Wed, 17 Jan 2024 16:29:09 +0000 Subject: [PATCH] Begin implementing Filament as the dashboard system --- composer.json | 4 +- config/cachet.php | 5 - public/build/assets/theme.c49c6bb2.css | 1 + public/build/manifest.json | 5 + resources/css/dashboard/tailwind.config.js | 9 + resources/css/dashboard/theme.css | 3 + resources/svg/clock.svg | 3 + .../component-major-outage.svg} | 2 +- .../component-operational.svg} | 2 +- .../component-partial-outage.svg} | 2 +- .../component-performance-issues.svg} | 2 +- resources/svg/components.svg | 3 + resources/svg/dashboard.svg | 3 + resources/svg/incident-fixed.svg | 3 + resources/svg/incident-identified.svg | 3 + resources/svg/incident-investigating.svg | 3 + resources/svg/incident-templates.svg | 3 + resources/svg/incident-updates.svg | 3 + resources/svg/incident-watching.svg | 3 + resources/svg/incident.svg | 3 + resources/svg/maintenance.svg | 3 + resources/svg/metrics.svg | 3 + resources/svg/settings.svg | 3 + resources/svg/subscribers.svg | 3 + .../unknown.blade.php => svg/unknown.svg} | 2 +- resources/views/components/badge.blade.php | 2 +- .../components/component-group.blade.php | 6 +- .../components/icons/chevron-up.blade.php | 1 - .../views/components/icons/clock.blade.php | 1 - .../views/components/icons/info.blade.php | 1 - .../components/icons/operational.blade.php | 3 - resources/views/components/incident.blade.php | 4 +- .../views/components/incidents.blade.php | 1 + resources/views/components/logo.blade.php | 2 +- .../views/components/maintenance.blade.php | 2 +- .../manage-application-settings.blade.php | 9 + .../filament/widgets/components.blade.php | 7 + .../views/filament/widgets/support.blade.php | 10 + src/CachetCoreServiceProvider.php | 9 +- src/CachetDashboardServiceProvider.php | 72 ++++++++ src/CachetServiceProvider.php | 86 +++++++-- src/Enums/ComponentGroupVisibilityEnum.php | 9 +- src/Enums/ComponentStatusEnum.php | 43 ++++- src/Enums/IncidentStatusEnum.php | 41 ++++- src/Enums/IncidentTemplateEngineEnum.php | 22 ++- src/Enums/MetricTypeEnum.php | 21 ++- src/Enums/MetricViewEnum.php | 6 +- src/Enums/ResourceVisibilityEnum.php | 33 +++- src/Enums/ScheduleStatusEnum.php | 45 +++-- src/Enums/UserLevelEnum.php | 5 +- src/Filament/Pages/Dashboard.php | 8 + .../Settings/ManageApplicationSettings.php | 44 +++++ .../Resources/ComponentGroupResource.php | 90 +++++++++ .../Pages/CreateComponentGroup.php | 11 ++ .../Pages/EditComponentGroup.php | 19 ++ .../Pages/ListComponentGroups.php | 19 ++ src/Filament/Resources/ComponentResource.php | 114 ++++++++++++ .../Pages/CreateComponent.php | 11 ++ .../ComponentResource/Pages/EditComponent.php | 19 ++ .../Pages/ListComponents.php | 19 ++ src/Filament/Resources/IncidentResource.php | 172 ++++++++++++++++++ .../IncidentResource/Pages/CreateIncident.php | 11 ++ .../IncidentResource/Pages/EditIncident.php | 19 ++ .../IncidentResource/Pages/ListIncidents.php | 19 ++ .../IncidentUpdatesRelationManager.php | 69 +++++++ .../Resources/IncidentTemplateResource.php | 102 +++++++++++ .../Pages/CreateIncidentTemplate.php | 11 ++ .../Pages/EditIncidentTemplate.php | 19 ++ .../Pages/ListIncidentTemplates.php | 19 ++ .../Pages/CreateIncidentUpdate.php | 12 ++ .../Pages/EditIncidentUpdate.php | 19 ++ .../Pages/ListIncidentUpdates.php | 19 ++ src/Filament/Resources/MetricResource.php | 139 ++++++++++++++ .../MetricResource/Pages/CreateMetric.php | 11 ++ .../MetricResource/Pages/EditMetric.php | 19 ++ .../MetricResource/Pages/ListMetrics.php | 19 ++ src/Filament/Resources/ScheduleResource.php | 107 +++++++++++ .../ScheduleResource/Pages/CreateSchedule.php | 11 ++ .../ScheduleResource/Pages/EditSchedule.php | 19 ++ .../ScheduleResource/Pages/ListSchedules.php | 19 ++ src/Filament/Resources/SubscriberResource.php | 106 +++++++++++ .../Pages/CreateSubscriber.php | 11 ++ .../Pages/EditSubscriber.php | 19 ++ .../Pages/ListSubscribers.php | 19 ++ src/Filament/Widgets/Components.php | 12 ++ src/Filament/Widgets/Overview.php | 34 ++++ src/Filament/Widgets/Support.php | 12 ++ src/Http/Resources/Incident.php | 2 +- src/Http/Resources/IncidentUpdate.php | 2 +- src/Http/Resources/Schedule.php | 2 +- src/Models/ComponentGroup.php | 4 +- src/Models/Incident.php | 9 +- testbench.yaml | 1 + vite.config.js | 18 +- 94 files changed, 1858 insertions(+), 102 deletions(-) create mode 100644 public/build/assets/theme.c49c6bb2.css create mode 100644 resources/css/dashboard/tailwind.config.js create mode 100644 resources/css/dashboard/theme.css create mode 100644 resources/svg/clock.svg rename resources/{views/components/icons/major-outage.blade.php => svg/component-major-outage.svg} (97%) rename resources/{views/components/icons/check-circle.blade.php => svg/component-operational.svg} (95%) rename resources/{views/components/icons/partial-outage.blade.php => svg/component-partial-outage.svg} (98%) rename resources/{views/components/icons/performance-issues.blade.php => svg/component-performance-issues.svg} (98%) create mode 100644 resources/svg/components.svg create mode 100644 resources/svg/dashboard.svg create mode 100644 resources/svg/incident-fixed.svg create mode 100644 resources/svg/incident-identified.svg create mode 100644 resources/svg/incident-investigating.svg create mode 100644 resources/svg/incident-templates.svg create mode 100644 resources/svg/incident-updates.svg create mode 100644 resources/svg/incident-watching.svg create mode 100644 resources/svg/incident.svg create mode 100644 resources/svg/maintenance.svg create mode 100644 resources/svg/metrics.svg create mode 100644 resources/svg/settings.svg create mode 100644 resources/svg/subscribers.svg rename resources/{views/components/icons/unknown.blade.php => svg/unknown.svg} (97%) delete mode 100644 resources/views/components/icons/chevron-up.blade.php delete mode 100644 resources/views/components/icons/clock.blade.php delete mode 100644 resources/views/components/icons/info.blade.php delete mode 100644 resources/views/components/icons/operational.blade.php create mode 100644 resources/views/filament/pages/settings/manage-application-settings.blade.php create mode 100644 resources/views/filament/widgets/components.blade.php create mode 100644 resources/views/filament/widgets/support.blade.php create mode 100644 src/CachetDashboardServiceProvider.php create mode 100644 src/Filament/Pages/Dashboard.php create mode 100644 src/Filament/Pages/Settings/ManageApplicationSettings.php create mode 100644 src/Filament/Resources/ComponentGroupResource.php create mode 100644 src/Filament/Resources/ComponentGroupResource/Pages/CreateComponentGroup.php create mode 100644 src/Filament/Resources/ComponentGroupResource/Pages/EditComponentGroup.php create mode 100644 src/Filament/Resources/ComponentGroupResource/Pages/ListComponentGroups.php create mode 100644 src/Filament/Resources/ComponentResource.php create mode 100644 src/Filament/Resources/ComponentResource/Pages/CreateComponent.php create mode 100644 src/Filament/Resources/ComponentResource/Pages/EditComponent.php create mode 100644 src/Filament/Resources/ComponentResource/Pages/ListComponents.php create mode 100644 src/Filament/Resources/IncidentResource.php create mode 100644 src/Filament/Resources/IncidentResource/Pages/CreateIncident.php create mode 100644 src/Filament/Resources/IncidentResource/Pages/EditIncident.php create mode 100644 src/Filament/Resources/IncidentResource/Pages/ListIncidents.php create mode 100644 src/Filament/Resources/IncidentResource/RelationManagers/IncidentUpdatesRelationManager.php create mode 100644 src/Filament/Resources/IncidentTemplateResource.php create mode 100644 src/Filament/Resources/IncidentTemplateResource/Pages/CreateIncidentTemplate.php create mode 100644 src/Filament/Resources/IncidentTemplateResource/Pages/EditIncidentTemplate.php create mode 100644 src/Filament/Resources/IncidentTemplateResource/Pages/ListIncidentTemplates.php create mode 100644 src/Filament/Resources/IncidentUpdateResource/Pages/CreateIncidentUpdate.php create mode 100644 src/Filament/Resources/IncidentUpdateResource/Pages/EditIncidentUpdate.php create mode 100644 src/Filament/Resources/IncidentUpdateResource/Pages/ListIncidentUpdates.php create mode 100644 src/Filament/Resources/MetricResource.php create mode 100644 src/Filament/Resources/MetricResource/Pages/CreateMetric.php create mode 100644 src/Filament/Resources/MetricResource/Pages/EditMetric.php create mode 100644 src/Filament/Resources/MetricResource/Pages/ListMetrics.php create mode 100644 src/Filament/Resources/ScheduleResource.php create mode 100644 src/Filament/Resources/ScheduleResource/Pages/CreateSchedule.php create mode 100644 src/Filament/Resources/ScheduleResource/Pages/EditSchedule.php create mode 100644 src/Filament/Resources/ScheduleResource/Pages/ListSchedules.php create mode 100644 src/Filament/Resources/SubscriberResource.php create mode 100644 src/Filament/Resources/SubscriberResource/Pages/CreateSubscriber.php create mode 100644 src/Filament/Resources/SubscriberResource/Pages/EditSubscriber.php create mode 100644 src/Filament/Resources/SubscriberResource/Pages/ListSubscribers.php create mode 100644 src/Filament/Widgets/Components.php create mode 100644 src/Filament/Widgets/Overview.php create mode 100644 src/Filament/Widgets/Support.php diff --git a/composer.json b/composer.json index 8e11782f..24e6e601 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "require": { "php": "^8.1", "doctrine/dbal": "^3.6", + "filament/filament": "^3.2", "guzzlehttp/guzzle": "^7.8", "illuminate/console": "^10.0", "illuminate/database": "^10.0", @@ -83,7 +84,8 @@ }, "laravel": { "providers": [ - "Cachet\\CachetCoreServiceProvider" + "Cachet\\CachetCoreServiceProvider", + "Cachet\\CachetDashboardServiceProvider" ] } }, diff --git a/config/cachet.php b/config/cachet.php index de98b760..28c643f5 100644 --- a/config/cachet.php +++ b/config/cachet.php @@ -68,11 +68,6 @@ 'api', ], - 'dashboard_middleware' => [ - 'cachet', - Authenticate::class, - ], - /* |-------------------------------------------------------------------------- | Cachet Major Outage Threshold diff --git a/public/build/assets/theme.c49c6bb2.css b/public/build/assets/theme.c49c6bb2.css new file mode 100644 index 00000000..9442966a --- /dev/null +++ b/public/build/assets/theme.c49c6bb2.css @@ -0,0 +1 @@ +*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:rgba(var(--gray-200),1)}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-family),ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:rgba(var(--gray-400),1)}input::placeholder,textarea::placeholder{opacity:1;color:rgba(var(--gray-400),1)}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[type=text],input:where(:not([type])),[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:rgba(var(--gray-500),var(--tw-border-opacity, 1));border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,input:where(:not([type])):focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:rgba(var(--gray-500),var(--tw-text-opacity, 1));opacity:1}input::placeholder,textarea::placeholder{color:rgba(var(--gray-500),var(--tw-text-opacity, 1));opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='rgba(var(--gray-500)%2c var(--tw-stroke-opacity%2c 1))' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:rgba(var(--gray-500),var(--tw-border-opacity, 1));border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}:root.dark{color-scheme:dark}[data-field-wrapper]{scroll-margin-top:8rem}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~="not-prose"] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~="lead"]):not(:where([class~="not-prose"] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~="not-prose"] *)){color:var(--tw-prose-links);text-decoration:underline;font-weight:500}.prose :where(strong):not(:where([class~="not-prose"] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(thead th strong):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(ol):not(:where([class~="not-prose"] *)){list-style-type:decimal;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol[type="A"]):not(:where([class~="not-prose"] *)){list-style-type:upper-alpha}.prose :where(ol[type="a"]):not(:where([class~="not-prose"] *)){list-style-type:lower-alpha}.prose :where(ol[type="A" s]):not(:where([class~="not-prose"] *)){list-style-type:upper-alpha}.prose :where(ol[type="a" s]):not(:where([class~="not-prose"] *)){list-style-type:lower-alpha}.prose :where(ol[type="I"]):not(:where([class~="not-prose"] *)){list-style-type:upper-roman}.prose :where(ol[type="i"]):not(:where([class~="not-prose"] *)){list-style-type:lower-roman}.prose :where(ol[type="I" s]):not(:where([class~="not-prose"] *)){list-style-type:upper-roman}.prose :where(ol[type="i" s]):not(:where([class~="not-prose"] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~="not-prose"] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~="not-prose"] *)){list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol > li):not(:where([class~="not-prose"] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul > li):not(:where([class~="not-prose"] *))::marker{color:var(--tw-prose-bullets)}.prose :where(hr):not(:where([class~="not-prose"] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~="not-prose"] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-left-width:.25rem;border-left-color:var(--tw-prose-quote-borders);quotes:"\201c""\201d""\2018""\2019";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose :where(blockquote p:first-of-type):not(:where([class~="not-prose"] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~="not-prose"] *)):after{content:close-quote}.prose :where(h1):not(:where([class~="not-prose"] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~="not-prose"] *)){font-weight:900;color:inherit}.prose :where(h2):not(:where([class~="not-prose"] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~="not-prose"] *)){font-weight:800;color:inherit}.prose :where(h3):not(:where([class~="not-prose"] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~="not-prose"] *)){font-weight:700;color:inherit}.prose :where(h4):not(:where([class~="not-prose"] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~="not-prose"] *)){font-weight:700;color:inherit}.prose :where(img):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose :where(figure > *):not(:where([class~="not-prose"] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~="not-prose"] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose :where(code):not(:where([class~="not-prose"] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em}.prose :where(code):not(:where([class~="not-prose"] *)):before{content:"`"}.prose :where(code):not(:where([class~="not-prose"] *)):after{content:"`"}.prose :where(a code):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(h1 code):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(h2 code):not(:where([class~="not-prose"] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~="not-prose"] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(blockquote code):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(thead th code):not(:where([class~="not-prose"] *)){color:inherit}.prose :where(pre):not(:where([class~="not-prose"] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose :where(pre code):not(:where([class~="not-prose"] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~="not-prose"] *)):before{content:none}.prose :where(pre code):not(:where([class~="not-prose"] *)):after{content:none}.prose :where(table):not(:where([class~="not-prose"] *)){width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~="not-prose"] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~="not-prose"] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose :where(tbody tr):not(:where([class~="not-prose"] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~="not-prose"] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~="not-prose"] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~="not-prose"] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~="not-prose"] *)){vertical-align:top}.prose{--tw-prose-body: #374151;--tw-prose-headings: #111827;--tw-prose-lead: #4b5563;--tw-prose-links: #111827;--tw-prose-bold: #111827;--tw-prose-counters: #6b7280;--tw-prose-bullets: #d1d5db;--tw-prose-hr: #e5e7eb;--tw-prose-quotes: #111827;--tw-prose-quote-borders: #e5e7eb;--tw-prose-captions: #6b7280;--tw-prose-code: #111827;--tw-prose-pre-code: #e5e7eb;--tw-prose-pre-bg: #1f2937;--tw-prose-th-borders: #d1d5db;--tw-prose-td-borders: #e5e7eb;--tw-prose-invert-body: #d1d5db;--tw-prose-invert-headings: #fff;--tw-prose-invert-lead: #9ca3af;--tw-prose-invert-links: #fff;--tw-prose-invert-bold: #fff;--tw-prose-invert-counters: #9ca3af;--tw-prose-invert-bullets: #4b5563;--tw-prose-invert-hr: #374151;--tw-prose-invert-quotes: #f3f4f6;--tw-prose-invert-quote-borders: #374151;--tw-prose-invert-captions: #9ca3af;--tw-prose-invert-code: #fff;--tw-prose-invert-pre-code: #d1d5db;--tw-prose-invert-pre-bg: rgb(0 0 0 / 50%);--tw-prose-invert-th-borders: #4b5563;--tw-prose-invert-td-borders: #374151;font-size:1rem;line-height:1.75}.prose :where(video):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose :where(figure):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose :where(li):not(:where([class~="not-prose"] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol > li):not(:where([class~="not-prose"] *)){padding-left:.375em}.prose :where(ul > li):not(:where([class~="not-prose"] *)){padding-left:.375em}.prose :where(.prose > ul > li p):not(:where([class~="not-prose"] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose > ul > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.25em}.prose :where(.prose > ul > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.25em}.prose :where(.prose > ol > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.25em}.prose :where(.prose > ol > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~="not-prose"] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(hr + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose :where(h2 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose :where(h3 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose :where(h4 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose :where(tbody td,tfoot td):not(:where([class~="not-prose"] *)){padding:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose :where(.prose > :first-child):not(:where([class~="not-prose"] *)){margin-top:0}.prose :where(.prose > :last-child):not(:where([class~="not-prose"] *)){margin-bottom:0}.prose-sm{font-size:.875rem;line-height:1.7142857}.prose-sm :where(p):not(:where([class~="not-prose"] *)){margin-top:1.1428571em;margin-bottom:1.1428571em}.prose-sm :where([class~="lead"]):not(:where([class~="not-prose"] *)){font-size:1.2857143em;line-height:1.5555556;margin-top:.8888889em;margin-bottom:.8888889em}.prose-sm :where(blockquote):not(:where([class~="not-prose"] *)){margin-top:1.3333333em;margin-bottom:1.3333333em;padding-left:1.1111111em}.prose-sm :where(h1):not(:where([class~="not-prose"] *)){font-size:2.1428571em;margin-top:0;margin-bottom:.8em;line-height:1.2}.prose-sm :where(h2):not(:where([class~="not-prose"] *)){font-size:1.4285714em;margin-top:1.6em;margin-bottom:.8em;line-height:1.4}.prose-sm :where(h3):not(:where([class~="not-prose"] *)){font-size:1.2857143em;margin-top:1.5555556em;margin-bottom:.4444444em;line-height:1.5555556}.prose-sm :where(h4):not(:where([class~="not-prose"] *)){margin-top:1.4285714em;margin-bottom:.5714286em;line-height:1.4285714}.prose-sm :where(img):not(:where([class~="not-prose"] *)){margin-top:1.7142857em;margin-bottom:1.7142857em}.prose-sm :where(video):not(:where([class~="not-prose"] *)){margin-top:1.7142857em;margin-bottom:1.7142857em}.prose-sm :where(figure):not(:where([class~="not-prose"] *)){margin-top:1.7142857em;margin-bottom:1.7142857em}.prose-sm :where(figure > *):not(:where([class~="not-prose"] *)){margin-top:0;margin-bottom:0}.prose-sm :where(figcaption):not(:where([class~="not-prose"] *)){font-size:.8571429em;line-height:1.3333333;margin-top:.6666667em}.prose-sm :where(code):not(:where([class~="not-prose"] *)){font-size:.8571429em}.prose-sm :where(h2 code):not(:where([class~="not-prose"] *)){font-size:.9em}.prose-sm :where(h3 code):not(:where([class~="not-prose"] *)){font-size:.8888889em}.prose-sm :where(pre):not(:where([class~="not-prose"] *)){font-size:.8571429em;line-height:1.6666667;margin-top:1.6666667em;margin-bottom:1.6666667em;border-radius:.25rem;padding:.6666667em 1em}.prose-sm :where(ol):not(:where([class~="not-prose"] *)){margin-top:1.1428571em;margin-bottom:1.1428571em;padding-left:1.5714286em}.prose-sm :where(ul):not(:where([class~="not-prose"] *)){margin-top:1.1428571em;margin-bottom:1.1428571em;padding-left:1.5714286em}.prose-sm :where(li):not(:where([class~="not-prose"] *)){margin-top:.2857143em;margin-bottom:.2857143em}.prose-sm :where(ol > li):not(:where([class~="not-prose"] *)){padding-left:.4285714em}.prose-sm :where(ul > li):not(:where([class~="not-prose"] *)){padding-left:.4285714em}.prose-sm :where(.prose-sm > ul > li p):not(:where([class~="not-prose"] *)){margin-top:.5714286em;margin-bottom:.5714286em}.prose-sm :where(.prose-sm > ul > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.1428571em}.prose-sm :where(.prose-sm > ul > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.1428571em}.prose-sm :where(.prose-sm > ol > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.1428571em}.prose-sm :where(.prose-sm > ol > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.1428571em}.prose-sm :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~="not-prose"] *)){margin-top:.5714286em;margin-bottom:.5714286em}.prose-sm :where(hr):not(:where([class~="not-prose"] *)){margin-top:2.8571429em;margin-bottom:2.8571429em}.prose-sm :where(hr + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-sm :where(h2 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-sm :where(h3 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-sm :where(h4 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-sm :where(table):not(:where([class~="not-prose"] *)){font-size:.8571429em;line-height:1.5}.prose-sm :where(thead th):not(:where([class~="not-prose"] *)){padding-right:1em;padding-bottom:.6666667em;padding-left:1em}.prose-sm :where(thead th:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-sm :where(thead th:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-sm :where(tbody td,tfoot td):not(:where([class~="not-prose"] *)){padding:.6666667em 1em}.prose-sm :where(tbody td:first-child,tfoot td:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-sm :where(tbody td:last-child,tfoot td:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-sm :where(.prose-sm > :first-child):not(:where([class~="not-prose"] *)){margin-top:0}.prose-sm :where(.prose-sm > :last-child):not(:where([class~="not-prose"] *)){margin-bottom:0}.prose-base{font-size:1rem;line-height:1.75}.prose-base :where(p):not(:where([class~="not-prose"] *)){margin-top:1.25em;margin-bottom:1.25em}.prose-base :where([class~="lead"]):not(:where([class~="not-prose"] *)){font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose-base :where(blockquote):not(:where([class~="not-prose"] *)){margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose-base :where(h1):not(:where([class~="not-prose"] *)){font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose-base :where(h2):not(:where([class~="not-prose"] *)){font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose-base :where(h3):not(:where([class~="not-prose"] *)){font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose-base :where(h4):not(:where([class~="not-prose"] *)){margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose-base :where(img):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose-base :where(video):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose-base :where(figure):not(:where([class~="not-prose"] *)){margin-top:2em;margin-bottom:2em}.prose-base :where(figure > *):not(:where([class~="not-prose"] *)){margin-top:0;margin-bottom:0}.prose-base :where(figcaption):not(:where([class~="not-prose"] *)){font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose-base :where(code):not(:where([class~="not-prose"] *)){font-size:.875em}.prose-base :where(h2 code):not(:where([class~="not-prose"] *)){font-size:.875em}.prose-base :where(h3 code):not(:where([class~="not-prose"] *)){font-size:.9em}.prose-base :where(pre):not(:where([class~="not-prose"] *)){font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose-base :where(ol):not(:where([class~="not-prose"] *)){margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose-base :where(ul):not(:where([class~="not-prose"] *)){margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose-base :where(li):not(:where([class~="not-prose"] *)){margin-top:.5em;margin-bottom:.5em}.prose-base :where(ol > li):not(:where([class~="not-prose"] *)){padding-left:.375em}.prose-base :where(ul > li):not(:where([class~="not-prose"] *)){padding-left:.375em}.prose-base :where(.prose-base > ul > li p):not(:where([class~="not-prose"] *)){margin-top:.75em;margin-bottom:.75em}.prose-base :where(.prose-base > ul > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.25em}.prose-base :where(.prose-base > ul > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.25em}.prose-base :where(.prose-base > ol > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.25em}.prose-base :where(.prose-base > ol > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.25em}.prose-base :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~="not-prose"] *)){margin-top:.75em;margin-bottom:.75em}.prose-base :where(hr):not(:where([class~="not-prose"] *)){margin-top:3em;margin-bottom:3em}.prose-base :where(hr + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-base :where(h2 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-base :where(h3 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-base :where(h4 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-base :where(table):not(:where([class~="not-prose"] *)){font-size:.875em;line-height:1.7142857}.prose-base :where(thead th):not(:where([class~="not-prose"] *)){padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose-base :where(thead th:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-base :where(thead th:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-base :where(tbody td,tfoot td):not(:where([class~="not-prose"] *)){padding:.5714286em}.prose-base :where(tbody td:first-child,tfoot td:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-base :where(tbody td:last-child,tfoot td:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-base :where(.prose-base > :first-child):not(:where([class~="not-prose"] *)){margin-top:0}.prose-base :where(.prose-base > :last-child):not(:where([class~="not-prose"] *)){margin-bottom:0}.prose-lg{font-size:1.125rem;line-height:1.7777778}.prose-lg :where(p):not(:where([class~="not-prose"] *)){margin-top:1.3333333em;margin-bottom:1.3333333em}.prose-lg :where([class~="lead"]):not(:where([class~="not-prose"] *)){font-size:1.2222222em;line-height:1.4545455;margin-top:1.0909091em;margin-bottom:1.0909091em}.prose-lg :where(blockquote):not(:where([class~="not-prose"] *)){margin-top:1.6666667em;margin-bottom:1.6666667em;padding-left:1em}.prose-lg :where(h1):not(:where([class~="not-prose"] *)){font-size:2.6666667em;margin-top:0;margin-bottom:.8333333em;line-height:1}.prose-lg :where(h2):not(:where([class~="not-prose"] *)){font-size:1.6666667em;margin-top:1.8666667em;margin-bottom:1.0666667em;line-height:1.3333333}.prose-lg :where(h3):not(:where([class~="not-prose"] *)){font-size:1.3333333em;margin-top:1.6666667em;margin-bottom:.6666667em;line-height:1.5}.prose-lg :where(h4):not(:where([class~="not-prose"] *)){margin-top:1.7777778em;margin-bottom:.4444444em;line-height:1.5555556}.prose-lg :where(img):not(:where([class~="not-prose"] *)){margin-top:1.7777778em;margin-bottom:1.7777778em}.prose-lg :where(video):not(:where([class~="not-prose"] *)){margin-top:1.7777778em;margin-bottom:1.7777778em}.prose-lg :where(figure):not(:where([class~="not-prose"] *)){margin-top:1.7777778em;margin-bottom:1.7777778em}.prose-lg :where(figure > *):not(:where([class~="not-prose"] *)){margin-top:0;margin-bottom:0}.prose-lg :where(figcaption):not(:where([class~="not-prose"] *)){font-size:.8888889em;line-height:1.5;margin-top:1em}.prose-lg :where(code):not(:where([class~="not-prose"] *)){font-size:.8888889em}.prose-lg :where(h2 code):not(:where([class~="not-prose"] *)){font-size:.8666667em}.prose-lg :where(h3 code):not(:where([class~="not-prose"] *)){font-size:.875em}.prose-lg :where(pre):not(:where([class~="not-prose"] *)){font-size:.8888889em;line-height:1.75;margin-top:2em;margin-bottom:2em;border-radius:.375rem;padding:1em 1.5em}.prose-lg :where(ol):not(:where([class~="not-prose"] *)){margin-top:1.3333333em;margin-bottom:1.3333333em;padding-left:1.5555556em}.prose-lg :where(ul):not(:where([class~="not-prose"] *)){margin-top:1.3333333em;margin-bottom:1.3333333em;padding-left:1.5555556em}.prose-lg :where(li):not(:where([class~="not-prose"] *)){margin-top:.6666667em;margin-bottom:.6666667em}.prose-lg :where(ol > li):not(:where([class~="not-prose"] *)){padding-left:.4444444em}.prose-lg :where(ul > li):not(:where([class~="not-prose"] *)){padding-left:.4444444em}.prose-lg :where(.prose-lg > ul > li p):not(:where([class~="not-prose"] *)){margin-top:.8888889em;margin-bottom:.8888889em}.prose-lg :where(.prose-lg > ul > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.3333333em}.prose-lg :where(.prose-lg > ul > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.3333333em}.prose-lg :where(.prose-lg > ol > li > *:first-child):not(:where([class~="not-prose"] *)){margin-top:1.3333333em}.prose-lg :where(.prose-lg > ol > li > *:last-child):not(:where([class~="not-prose"] *)){margin-bottom:1.3333333em}.prose-lg :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~="not-prose"] *)){margin-top:.8888889em;margin-bottom:.8888889em}.prose-lg :where(hr):not(:where([class~="not-prose"] *)){margin-top:3.1111111em;margin-bottom:3.1111111em}.prose-lg :where(hr + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-lg :where(h2 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-lg :where(h3 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-lg :where(h4 + *):not(:where([class~="not-prose"] *)){margin-top:0}.prose-lg :where(table):not(:where([class~="not-prose"] *)){font-size:.8888889em;line-height:1.5}.prose-lg :where(thead th):not(:where([class~="not-prose"] *)){padding-right:.75em;padding-bottom:.75em;padding-left:.75em}.prose-lg :where(thead th:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-lg :where(thead th:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-lg :where(tbody td,tfoot td):not(:where([class~="not-prose"] *)){padding:.75em}.prose-lg :where(tbody td:first-child,tfoot td:first-child):not(:where([class~="not-prose"] *)){padding-left:0}.prose-lg :where(tbody td:last-child,tfoot td:last-child):not(:where([class~="not-prose"] *)){padding-right:0}.prose-lg :where(.prose-lg > :first-child):not(:where([class~="not-prose"] *)){margin-top:0}.prose-lg :where(.prose-lg > :last-child):not(:where([class~="not-prose"] *)){margin-bottom:0}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0px}.inset-4{inset:1rem}.inset-x-0{left:0px;right:0px}.inset-x-4{left:1rem;right:1rem}.inset-y-0{top:0px;bottom:0px}.-bottom-1\/2{bottom:-50%}.-top-1{top:-.25rem}.-top-1\/2{top:-50%}.-top-2{top:-.5rem}.-top-3{top:-.75rem}.bottom-0{bottom:0px}.bottom-1\/2{bottom:50%}.end-0{inset-inline-end:0px}.end-4{inset-inline-end:1rem}.end-6{inset-inline-end:1.5rem}.left-3{left:.75rem}.start-0{inset-inline-start:0px}.start-full{inset-inline-start:100%}.top-0{top:0px}.top-1\/2{top:50%}.top-4{top:1rem}.top-6{top:1.5rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[1\]{z-index:1}.col-\[--col-span-default\]{grid-column:var(--col-span-default)}.col-span-full{grid-column:1 / -1}.col-start-2{grid-column-start:2}.col-start-3{grid-column-start:3}.col-start-\[--col-start-default\]{grid-column-start:var(--col-start-default)}.-m-0{margin:-0px}.-m-0\.5{margin:-.125rem}.-m-1{margin:-.25rem}.-m-1\.5{margin:-.375rem}.-m-2{margin:-.5rem}.-m-2\.5{margin:-.625rem}.-m-3{margin:-.75rem}.-m-3\.5{margin:-.875rem}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.-mx-4{margin-left:-1rem;margin-right:-1rem}.-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.-my-1{margin-top:-.25rem;margin-bottom:-.25rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.mx-auto{margin-left:auto;margin-right:auto}.my-16{margin-top:4rem;margin-bottom:4rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-auto{margin-top:auto;margin-bottom:auto}.\!mt-0{margin-top:0!important}.-mb-4{margin-bottom:-1rem}.-mb-6{margin-bottom:-1.5rem}.-me-2{margin-inline-end:-.5rem}.-ms-0{margin-inline-start:-0px}.-ms-0\.5{margin-inline-start:-.125rem}.-ms-1{margin-inline-start:-.25rem}.-ms-2{margin-inline-start:-.5rem}.-mt-3{margin-top:-.75rem}.-mt-4{margin-top:-1rem}.-mt-6{margin-top:-1.5rem}.-mt-7{margin-top:-1.75rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.me-1{margin-inline-end:.25rem}.me-4{margin-inline-end:1rem}.me-6{margin-inline-end:1.5rem}.ml-auto{margin-left:auto}.ms-1{margin-inline-start:.25rem}.ms-auto{margin-inline-start:auto}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-6{margin-top:1.5rem}.mt-auto{margin-top:auto}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.inline-grid{display:inline-grid}.hidden{display:none}.h-0{height:0px}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-16{height:4rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.min-h-\[theme\(spacing\.48\)\]{min-height:12rem}.min-h-full{min-height:100%}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-1\/2{width:50%}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-16{width:4rem}.w-20{width:5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[--sidebar-width\]{width:var(--sidebar-width)}.w-\[calc\(100\%\+2rem\)\]{width:calc(100% + 2rem)}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-px{width:1px}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[theme\(spacing\.4\)\]{min-width:1rem}.min-w-\[theme\(spacing\.5\)\]{min-width:1.25rem}.min-w-\[theme\(spacing\.6\)\]{min-width:1.5rem}.min-w-\[theme\(spacing\.8\)\]{min-width:2rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[14rem\]{max-width:14rem}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-max{max-width:-moz-max-content;max-width:max-content}.max-w-md{max-width:28rem}.max-w-min{max-width:-moz-min-content;max-width:min-content}.max-w-none{max-width:none}.max-w-prose{max-width:65ch}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.max-w-screen-md{max-width:768px}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.table-auto{table-layout:auto}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-12{--tw-translate-x: -3rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-5{--tw-translate-x: -1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-12{--tw-translate-y: -3rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-12{--tw-translate-x: 3rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-5{--tw-translate-x: 1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-12{--tw-translate-y: 3rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-180{--tw-rotate: -180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x: 1;--tw-scale-y: 1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-95{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-move{cursor:move}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.scroll-mt-9{scroll-margin-top:2.25rem}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.columns-\[--cols-default\]{-moz-columns:var(--cols-default);columns:var(--cols-default)}.break-inside-avoid{-moz-column-break-inside:avoid;break-inside:avoid}.auto-cols-fr{grid-auto-columns:minmax(0,1fr)}.grid-flow-col{grid-auto-flow:column}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.grid-cols-\[--cols-default\]{grid-template-columns:var(--cols-default)}.grid-cols-\[1fr_auto_1fr\]{grid-template-columns:1fr auto 1fr}.grid-cols-\[repeat\(7\,minmax\(theme\(spacing\.7\)\,1fr\)\)\]{grid-template-columns:repeat(7,minmax(1.75rem,1fr))}.grid-cols-\[repeat\(auto-fit\,minmax\(0\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-start{justify-items:start}.justify-items-center{justify-items:center}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-x-2\.5{-moz-column-gap:.625rem;column-gap:.625rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-1{row-gap:.25rem}.gap-y-1\.5{row-gap:.375rem}.gap-y-2{row-gap:.5rem}.gap-y-3{row-gap:.75rem}.gap-y-4{row-gap:1rem}.gap-y-6{row-gap:1.5rem}.gap-y-7{row-gap:1.75rem}.gap-y-8{row-gap:2rem}.gap-y-px{row-gap:1px}.-space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-.25rem * var(--tw-space-x-reverse));margin-left:calc(-.25rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-.5rem * var(--tw-space-x-reverse));margin-left:calc(-.5rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-.75rem * var(--tw-space-x-reverse));margin-left:calc(-.75rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-1rem * var(--tw-space-x-reverse));margin-left:calc(-1rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-1.25rem * var(--tw-space-x-reverse));margin-left:calc(-1.25rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-1.5rem * var(--tw-space-x-reverse));margin-left:calc(-1.5rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-7>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-1.75rem * var(--tw-space-x-reverse));margin-left:calc(-1.75rem * calc(1 - var(--tw-space-x-reverse)))}.-space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(-2rem * var(--tw-space-x-reverse));margin-left:calc(-2rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-x>:not([hidden])~:not([hidden]){--tw-divide-x-reverse: 0;border-right-width:calc(1px * var(--tw-divide-x-reverse));border-left-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgba(var(--gray-100),var(--tw-divide-opacity))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgba(var(--gray-200),var(--tw-divide-opacity))}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.justify-self-center{justify-self:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.overflow-x-clip{overflow-x:clip}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-x-\[0\.5px\]{border-left-width:.5px;border-right-width:.5px}.border-y{border-top-width:1px;border-bottom-width:1px}.\!border-t-0{border-top-width:0px!important}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0px}.border-e{border-inline-end-width:1px}.border-s{border-inline-start-width:1px}.border-t{border-top-width:1px}.\!border-none{border-style:none!important}.border-none{border-style:none}.border-gray-100{--tw-border-opacity: 1;border-color:rgba(var(--gray-100),var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgba(var(--gray-200),var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity: 1;border-color:rgba(var(--gray-300),var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity: 1;border-color:rgba(var(--gray-600),var(--tw-border-opacity))}.border-primary-500{--tw-border-opacity: 1;border-color:rgba(var(--primary-500),var(--tw-border-opacity))}.border-primary-600{--tw-border-opacity: 1;border-color:rgba(var(--primary-600),var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-t-gray-200{--tw-border-opacity: 1;border-top-color:rgba(var(--gray-200),var(--tw-border-opacity))}.\!bg-gray-50{--tw-bg-opacity: 1 !important;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))!important}.\!bg-gray-700{--tw-bg-opacity: 1 !important;background-color:rgba(var(--gray-700),var(--tw-bg-opacity))!important}.bg-black\/50{background-color:#00000080}.bg-custom-100{--tw-bg-opacity: 1;background-color:rgba(var(--c-100),var(--tw-bg-opacity))}.bg-custom-50{--tw-bg-opacity: 1;background-color:rgba(var(--c-50),var(--tw-bg-opacity))}.bg-custom-600{--tw-bg-opacity: 1;background-color:rgba(var(--c-600),var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgba(var(--gray-200),var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgba(var(--gray-300),var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgba(var(--gray-400),var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.bg-gray-950\/50{background-color:rgba(var(--gray-950),.5)}.bg-primary-500{--tw-bg-opacity: 1;background-color:rgba(var(--primary-500),var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity: 1;background-color:rgba(var(--primary-600),var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-white\/0{background-color:#fff0}.bg-white\/5{background-color:#ffffff0d}.bg-cover{background-size:cover}.bg-center{background-position:center}.object-cover{-o-object-fit:cover;object-fit:cover}.object-center{-o-object-position:center;object-position:center}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-0{padding-left:0;padding-right:0}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pe-0{padding-inline-end:0px}.pe-1{padding-inline-end:.25rem}.pe-2{padding-inline-end:.5rem}.pe-3{padding-inline-end:.75rem}.pe-4{padding-inline-end:1rem}.pe-6{padding-inline-end:1.5rem}.pe-8{padding-inline-end:2rem}.ps-0{padding-inline-start:0px}.ps-1{padding-inline-start:.25rem}.ps-2{padding-inline-start:.5rem}.ps-3{padding-inline-start:.75rem}.ps-4{padding-inline-start:1rem}.ps-\[5\.25rem\]{padding-inline-start:5.25rem}.pt-0{padding-top:0}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-justify{text-align:justify}.text-start{text-align:start}.text-end{text-align:end}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:var(--font-family),ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}.font-serif{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-extralight{font-weight:200}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-thin{font-weight:100}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-loose{line-height:2}.tracking-tight{letter-spacing:-.025em}.tracking-tighter{letter-spacing:-.05em}.text-custom-400{--tw-text-opacity: 1;color:rgba(var(--c-400),var(--tw-text-opacity))}.text-custom-50{--tw-text-opacity: 1;color:rgba(var(--c-50),var(--tw-text-opacity))}.text-custom-500{--tw-text-opacity: 1;color:rgba(var(--c-500),var(--tw-text-opacity))}.text-custom-600{--tw-text-opacity: 1;color:rgba(var(--c-600),var(--tw-text-opacity))}.text-custom-700\/50{color:rgba(var(--c-700),.5)}.text-danger-600{--tw-text-opacity: 1;color:rgba(var(--danger-600),var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity: 1;color:rgba(var(--gray-100),var(--tw-text-opacity))}.text-gray-200{--tw-text-opacity: 1;color:rgba(var(--gray-200),var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgba(var(--gray-600),var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgba(var(--gray-700),var(--tw-text-opacity))}.text-gray-700\/50{color:rgba(var(--gray-700),.5)}.text-gray-950{--tw-text-opacity: 1;color:rgba(var(--gray-950),var(--tw-text-opacity))}.text-primary-400{--tw-text-opacity: 1;color:rgba(var(--primary-400),var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity: 1;color:rgba(var(--primary-500),var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity: 1;color:rgba(var(--primary-600),var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-4{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-custom-600{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--c-600), var(--tw-ring-opacity))}.ring-custom-600\/10{--tw-ring-color: rgba(var(--c-600), .1)}.ring-custom-600\/20{--tw-ring-color: rgba(var(--c-600), .2)}.ring-danger-600{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-600), var(--tw-ring-opacity))}.ring-gray-200{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--gray-200), var(--tw-ring-opacity))}.ring-gray-300{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--gray-300), var(--tw-ring-opacity))}.ring-gray-600\/10{--tw-ring-color: rgba(var(--gray-600), .1)}.ring-gray-900\/10{--tw-ring-color: rgba(var(--gray-900), .1)}.ring-gray-950\/10{--tw-ring-color: rgba(var(--gray-950), .1)}.ring-gray-950\/5{--tw-ring-color: rgba(var(--gray-950), .05)}.ring-white{--tw-ring-opacity: 1;--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity))}.ring-white\/10{--tw-ring-color: rgb(255 255 255 / .1)}.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)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.delay-100{transition-delay:.1s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[transform\:translateZ\(0\)\]{transform:translateZ(0)}.text-link{--tw-text-opacity: 1;color:rgba(var(--primary-600),var(--tw-text-opacity))}:is(.dark .text-link){--tw-text-opacity: 1;color:rgba(var(--primary-400),var(--tw-text-opacity))}:is(.dark .dark\:prose-invert){--tw-prose-body: var(--tw-prose-invert-body);--tw-prose-headings: var(--tw-prose-invert-headings);--tw-prose-lead: var(--tw-prose-invert-lead);--tw-prose-links: var(--tw-prose-invert-links);--tw-prose-bold: var(--tw-prose-invert-bold);--tw-prose-counters: var(--tw-prose-invert-counters);--tw-prose-bullets: var(--tw-prose-invert-bullets);--tw-prose-hr: var(--tw-prose-invert-hr);--tw-prose-quotes: var(--tw-prose-invert-quotes);--tw-prose-quote-borders: var(--tw-prose-invert-quote-borders);--tw-prose-captions: var(--tw-prose-invert-captions);--tw-prose-code: var(--tw-prose-invert-code);--tw-prose-pre-code: var(--tw-prose-invert-pre-code);--tw-prose-pre-bg: var(--tw-prose-invert-pre-bg);--tw-prose-th-borders: var(--tw-prose-invert-th-borders);--tw-prose-td-borders: var(--tw-prose-invert-td-borders)}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:inset-y-0:before{content:var(--tw-content);top:0px;bottom:0px}.before\:start-0:before{content:var(--tw-content);inset-inline-start:0px}.before\:h-full:before{content:var(--tw-content);height:100%}.before\:w-0:before{content:var(--tw-content);width:0px}.before\:w-0\.5:before{content:var(--tw-content);width:.125rem}.before\:bg-primary-600:before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgba(var(--primary-600),var(--tw-bg-opacity))}.first\:border-s-0:first-child{border-inline-start-width:0px}.first\:border-t-0:first-child{border-top-width:0px}.last\:border-e-0:last-child{border-inline-end-width:0px}.first-of-type\:ps-1:first-of-type{padding-inline-start:.25rem}.last-of-type\:pe-1:last-of-type{padding-inline-end:.25rem}.checked\:ring-0:checked{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-within\:bg-gray-50:focus-within{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.focus-within\:ring-2:focus-within{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-within\:ring-danger-600:focus-within{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-600), var(--tw-ring-opacity))}.focus-within\:ring-primary-600:focus-within{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-600), var(--tw-ring-opacity))}.hover\:bg-custom-400\/10:hover{background-color:rgba(var(--c-400),.1)}.hover\:bg-custom-50:hover{--tw-bg-opacity: 1;background-color:rgba(var(--c-50),var(--tw-bg-opacity))}.hover\:bg-custom-500:hover{--tw-bg-opacity: 1;background-color:rgba(var(--c-500),var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}.hover\:bg-gray-400\/10:hover{background-color:rgba(var(--gray-400),.1)}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.hover\:text-custom-600:hover{--tw-text-opacity: 1;color:rgba(var(--c-600),var(--tw-text-opacity))}.hover\:text-custom-700\/75:hover{color:rgba(var(--c-700),.75)}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgba(var(--gray-700),var(--tw-text-opacity))}.hover\:text-gray-700\/75:hover{color:rgba(var(--gray-700),.75)}.hover\:opacity-100:hover{opacity:1}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-danger-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-600), var(--tw-ring-opacity))}.focus\:ring-primary-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-600), var(--tw-ring-opacity))}.focus\:ring-offset-0:focus{--tw-ring-offset-width: 0px}.checked\:focus\:ring-danger-500\/50:focus:checked{--tw-ring-color: rgba(var(--danger-500), .5)}.checked\:focus\:ring-primary-500\/50:focus:checked{--tw-ring-color: rgba(var(--primary-500), .5)}.focus-visible\:z-10:focus-visible{z-index:10}.focus-visible\:border-primary-500:focus-visible{--tw-border-opacity: 1;border-color:rgba(var(--primary-500),var(--tw-border-opacity))}.focus-visible\:bg-custom-50:focus-visible{--tw-bg-opacity: 1;background-color:rgba(var(--c-50),var(--tw-bg-opacity))}.focus-visible\:bg-gray-100:focus-visible{--tw-bg-opacity: 1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}.focus-visible\:bg-gray-50:focus-visible{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.focus-visible\:text-custom-700\/75:focus-visible{color:rgba(var(--c-700),.75)}.focus-visible\:text-gray-500:focus-visible{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.focus-visible\:text-gray-700\/75:focus-visible{color:rgba(var(--gray-700),.75)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-1:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-inset:focus-visible{--tw-ring-inset: inset}.focus-visible\:ring-custom-500\/50:focus-visible{--tw-ring-color: rgba(var(--c-500), .5)}.focus-visible\:ring-custom-600:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--c-600), var(--tw-ring-opacity))}.focus-visible\:ring-gray-400\/40:focus-visible{--tw-ring-color: rgba(var(--gray-400), .4)}.focus-visible\:ring-primary-500:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-500), var(--tw-ring-opacity))}.focus-visible\:ring-primary-600:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-600), var(--tw-ring-opacity))}.enabled\:cursor-wait:enabled{cursor:wait}.enabled\:opacity-70:enabled{opacity:.7}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.disabled\:text-gray-50:disabled{--tw-text-opacity: 1;color:rgba(var(--gray-50),var(--tw-text-opacity))}.disabled\:text-gray-500:disabled{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.disabled\:opacity-70:disabled{opacity:.7}.disabled\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled{-webkit-text-fill-color:rgba(var(--gray-500),1)}.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::-moz-placeholder{-webkit-text-fill-color:rgba(var(--gray-400),1)}.disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled::placeholder{-webkit-text-fill-color:rgba(var(--gray-400),1)}.disabled\:checked\:bg-current:checked:disabled{background-color:currentColor}.disabled\:checked\:text-gray-400:checked:disabled{--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}.group\/item:first-child .group-first\/item\:rounded-s-lg{border-start-start-radius:.5rem;border-end-start-radius:.5rem}.group\/item:last-child .group-last\/item\:rounded-e-lg{border-start-end-radius:.5rem;border-end-end-radius:.5rem}.group\/button:hover .group-hover\/button\:text-gray-500,.group:hover .group-hover\:text-gray-500{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-700{--tw-text-opacity: 1;color:rgba(var(--gray-700),var(--tw-text-opacity))}.group\/item:hover .group-hover\/item\:underline,.group\/link:hover .group-hover\/link\:underline{text-decoration-line:underline}.group:focus-visible .group-focus-visible\:text-gray-500{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}.group:focus-visible .group-focus-visible\:text-gray-700{--tw-text-opacity: 1;color:rgba(var(--gray-700),var(--tw-text-opacity))}.group\/item:focus-visible .group-focus-visible\/item\:underline{text-decoration-line:underline}.group\/link:focus-visible .group-focus-visible\/link\:underline{text-decoration-line:underline}:is([dir="ltr"] .ltr\:hidden){display:none}:is([dir="rtl"] .rtl\:hidden){display:none}:is([dir="rtl"] .rtl\:-translate-x-0){--tw-translate-x: -0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:-translate-x-5){--tw-translate-x: -1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:-translate-x-full){--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:translate-x-1\/2){--tw-translate-x: 50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:translate-x-full){--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:rotate-180){--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:flex-row-reverse){flex-direction:row-reverse}:is([dir="rtl"] .rtl\:divide-x-reverse)>:not([hidden])~:not([hidden]){--tw-divide-x-reverse: 1}:is(.dark .dark\:inline-flex){display:inline-flex}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-white\/10)>:not([hidden])~:not([hidden]){border-color:#ffffff1a}:is(.dark .dark\:divide-white\/5)>:not([hidden])~:not([hidden]){border-color:#ffffff0d}:is(.dark .dark\:border-gray-600){--tw-border-opacity: 1;border-color:rgba(var(--gray-600),var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity: 1;border-color:rgba(var(--gray-700),var(--tw-border-opacity))}:is(.dark .dark\:border-primary-500){--tw-border-opacity: 1;border-color:rgba(var(--primary-500),var(--tw-border-opacity))}:is(.dark .dark\:border-white\/10){border-color:#ffffff1a}:is(.dark .dark\:border-white\/5){border-color:#ffffff0d}:is(.dark .dark\:border-t-white\/10){border-top-color:#ffffff1a}:is(.dark .dark\:\!bg-gray-700){--tw-bg-opacity: 1 !important;background-color:rgba(var(--gray-700),var(--tw-bg-opacity))!important}:is(.dark .dark\:bg-custom-400\/10){background-color:rgba(var(--c-400),.1)}:is(.dark .dark\:bg-custom-500){--tw-bg-opacity: 1;background-color:rgba(var(--c-500),var(--tw-bg-opacity))}:is(.dark .dark\:bg-custom-500\/20){background-color:rgba(var(--c-500),.2)}:is(.dark .dark\:bg-gray-400\/10){background-color:rgba(var(--gray-400),.1)}:is(.dark .dark\:bg-gray-500){--tw-bg-opacity: 1;background-color:rgba(var(--gray-500),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-500\/20){background-color:rgba(var(--gray-500),.2)}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity: 1;background-color:rgba(var(--gray-600),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity: 1;background-color:rgba(var(--gray-700),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity: 1;background-color:rgba(var(--gray-800),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity: 1;background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-900\/30){background-color:rgba(var(--gray-900),.3)}:is(.dark .dark\:bg-gray-950){--tw-bg-opacity: 1;background-color:rgba(var(--gray-950),var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-950\/75){background-color:rgba(var(--gray-950),.75)}:is(.dark .dark\:bg-primary-400){--tw-bg-opacity: 1;background-color:rgba(var(--primary-400),var(--tw-bg-opacity))}:is(.dark .dark\:bg-primary-500){--tw-bg-opacity: 1;background-color:rgba(var(--primary-500),var(--tw-bg-opacity))}:is(.dark .dark\:bg-transparent){background-color:transparent}:is(.dark .dark\:bg-white\/10){background-color:#ffffff1a}:is(.dark .dark\:bg-white\/5){background-color:#ffffff0d}:is(.dark .dark\:fill-current){fill:currentColor}:is(.dark .dark\:text-custom-300\/50){color:rgba(var(--c-300),.5)}:is(.dark .dark\:text-custom-400){--tw-text-opacity: 1;color:rgba(var(--c-400),var(--tw-text-opacity))}:is(.dark .dark\:text-custom-400\/10){color:rgba(var(--c-400),.1)}:is(.dark .dark\:text-danger-400){--tw-text-opacity: 1;color:rgba(var(--danger-400),var(--tw-text-opacity))}:is(.dark .dark\:text-danger-500){--tw-text-opacity: 1;color:rgba(var(--danger-500),var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity: 1;color:rgba(var(--gray-200),var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300\/50){color:rgba(var(--gray-300),.5)}:is(.dark .dark\:text-gray-400){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}:is(.dark .dark\:text-gray-700){--tw-text-opacity: 1;color:rgba(var(--gray-700),var(--tw-text-opacity))}:is(.dark .dark\:text-gray-800){--tw-text-opacity: 1;color:rgba(var(--gray-800),var(--tw-text-opacity))}:is(.dark .dark\:text-primary-400){--tw-text-opacity: 1;color:rgba(var(--primary-400),var(--tw-text-opacity))}:is(.dark .dark\:text-primary-500){--tw-text-opacity: 1;color:rgba(var(--primary-500),var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}:is(.dark .dark\:text-white\/5){color:#ffffff0d}:is(.dark .dark\:ring-custom-400\/30){--tw-ring-color: rgba(var(--c-400), .3)}:is(.dark .dark\:ring-custom-500){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--c-500), var(--tw-ring-opacity))}:is(.dark .dark\:ring-danger-500){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-500), var(--tw-ring-opacity))}:is(.dark .dark\:ring-gray-400\/20){--tw-ring-color: rgba(var(--gray-400), .2)}:is(.dark .dark\:ring-gray-50\/10){--tw-ring-color: rgba(var(--gray-50), .1)}:is(.dark .dark\:ring-gray-700){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--gray-700), var(--tw-ring-opacity))}:is(.dark .dark\:ring-gray-900){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--gray-900), var(--tw-ring-opacity))}:is(.dark .dark\:ring-white\/10){--tw-ring-color: rgb(255 255 255 / .1)}:is(.dark .dark\:ring-white\/20){--tw-ring-color: rgb(255 255 255 / .2)}:is(.dark .dark\:placeholder\:text-gray-500)::-moz-placeholder{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}:is(.dark .dark\:placeholder\:text-gray-500)::placeholder{--tw-text-opacity: 1;color:rgba(var(--gray-500),var(--tw-text-opacity))}:is(.dark .dark\:before\:bg-primary-500):before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgba(var(--primary-500),var(--tw-bg-opacity))}:is(.dark .dark\:checked\:bg-danger-500:checked){--tw-bg-opacity: 1;background-color:rgba(var(--danger-500),var(--tw-bg-opacity))}:is(.dark .dark\:checked\:bg-primary-500:checked){--tw-bg-opacity: 1;background-color:rgba(var(--primary-500),var(--tw-bg-opacity))}:is(.dark .dark\:focus-within\:bg-white\/5:focus-within){background-color:#ffffff0d}:is(.dark .dark\:focus-within\:ring-danger-500:focus-within){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-500), var(--tw-ring-opacity))}:is(.dark .dark\:focus-within\:ring-primary-500:focus-within){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-500), var(--tw-ring-opacity))}:is(.dark .dark\:hover\:bg-custom-400:hover){--tw-bg-opacity: 1;background-color:rgba(var(--c-400),var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-custom-400\/10:hover){background-color:rgba(var(--c-400),.1)}:is(.dark .dark\:hover\:bg-white\/10:hover){background-color:#ffffff1a}:is(.dark .dark\:hover\:bg-white\/5:hover){background-color:#ffffff0d}:is(.dark .dark\:hover\:text-custom-300:hover){--tw-text-opacity: 1;color:rgba(var(--c-300),var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-custom-300\/75:hover){color:rgba(var(--c-300),.75)}:is(.dark .dark\:hover\:text-gray-200:hover){--tw-text-opacity: 1;color:rgba(var(--gray-200),var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300\/75:hover){color:rgba(var(--gray-300),.75)}:is(.dark .dark\:hover\:text-gray-400:hover){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .dark\:hover\:ring-white\/20:hover){--tw-ring-color: rgb(255 255 255 / .2)}:is(.dark .dark\:focus\:ring-danger-500:focus){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--danger-500), var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-500), var(--tw-ring-opacity))}:is(.dark .dark\:checked\:focus\:ring-danger-400\/50:focus:checked){--tw-ring-color: rgba(var(--danger-400), .5)}:is(.dark .dark\:checked\:focus\:ring-primary-400\/50:focus:checked){--tw-ring-color: rgba(var(--primary-400), .5)}:is(.dark .dark\:focus-visible\:border-primary-500:focus-visible){--tw-border-opacity: 1;border-color:rgba(var(--primary-500),var(--tw-border-opacity))}:is(.dark .dark\:focus-visible\:bg-custom-400\/10:focus-visible){background-color:rgba(var(--c-400),.1)}:is(.dark .dark\:focus-visible\:bg-white\/5:focus-visible){background-color:#ffffff0d}:is(.dark .dark\:focus-visible\:text-custom-300\/75:focus-visible){color:rgba(var(--c-300),.75)}:is(.dark .dark\:focus-visible\:text-gray-300\/75:focus-visible){color:rgba(var(--gray-300),.75)}:is(.dark .dark\:focus-visible\:text-gray-400:focus-visible){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .dark\:focus-visible\:ring-custom-400\/50:focus-visible){--tw-ring-color: rgba(var(--c-400), .5)}:is(.dark .dark\:focus-visible\:ring-custom-500:focus-visible){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--c-500), var(--tw-ring-opacity))}:is(.dark .dark\:focus-visible\:ring-primary-500:focus-visible){--tw-ring-opacity: 1;--tw-ring-color: rgba(var(--primary-500), var(--tw-ring-opacity))}:is(.dark .dark\:disabled\:bg-transparent:disabled){background-color:transparent}:is(.dark .dark\:disabled\:text-gray-400:disabled){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .dark\:disabled\:ring-white\/10:disabled){--tw-ring-color: rgb(255 255 255 / .1)}:is(.dark .dark\:disabled\:\[-webkit-text-fill-color\:theme\(colors\.gray\.400\)\]:disabled){-webkit-text-fill-color:rgba(var(--gray-400),1)}:is(.dark .dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled)::-moz-placeholder{-webkit-text-fill-color:rgba(var(--gray-500),1)}:is(.dark .dark\:disabled\:placeholder\:\[-webkit-text-fill-color\:theme\(colors\.gray\.500\)\]:disabled)::placeholder{-webkit-text-fill-color:rgba(var(--gray-500),1)}:is(.dark .dark\:disabled\:checked\:bg-gray-600:checked:disabled){--tw-bg-opacity: 1;background-color:rgba(var(--gray-600),var(--tw-bg-opacity))}:is(.dark .group\/button:hover .dark\:group-hover\/button\:text-gray-400){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .group:hover .dark\:group-hover\:text-gray-200){--tw-text-opacity: 1;color:rgba(var(--gray-200),var(--tw-text-opacity))}:is(.dark .group:hover .dark\:group-hover\:text-gray-400){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}:is(.dark .group:focus-visible .dark\:group-focus-visible\:text-gray-200){--tw-text-opacity: 1;color:rgba(var(--gray-200),var(--tw-text-opacity))}:is(.dark .group:focus-visible .dark\:group-focus-visible\:text-gray-400){--tw-text-opacity: 1;color:rgba(var(--gray-400),var(--tw-text-opacity))}@media (min-width: 640px){.sm\:relative{position:relative}.sm\:inset-x-auto{left:auto;right:auto}.sm\:end-0{inset-inline-end:0px}.sm\:col-\[--col-span-sm\]{grid-column:var(--col-span-sm)}.sm\:col-span-2{grid-column:span 2 / span 2}.sm\:col-start-\[--col-start-sm\]{grid-column-start:var(--col-start-sm)}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.sm\:ms-auto{margin-inline-start:auto}.sm\:mt-7{margin-top:1.75rem}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:table-cell{display:table-cell}.sm\:grid{display:grid}.sm\:inline-grid{display:inline-grid}.sm\:hidden{display:none}.sm\:w-\[calc\(100\%\+3rem\)\]{width:calc(100% + 3rem)}.sm\:w-screen{width:100vw}.sm\:max-w-2xl{max-width:42rem}.sm\:max-w-3xl{max-width:48rem}.sm\:max-w-4xl{max-width:56rem}.sm\:max-w-5xl{max-width:64rem}.sm\:max-w-6xl{max-width:72rem}.sm\:max-w-7xl{max-width:80rem}.sm\:max-w-lg{max-width:32rem}.sm\:max-w-md{max-width:28rem}.sm\:max-w-sm{max-width:24rem}.sm\:max-w-xl{max-width:36rem}.sm\:max-w-xs{max-width:20rem}.sm\:columns-\[--cols-sm\]{-moz-columns:var(--cols-sm);columns:var(--cols-sm)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-\[--cols-sm\]{grid-template-columns:var(--cols-sm)}.sm\:grid-cols-\[repeat\(auto-fit\,minmax\(0\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-end{align-items:flex-end}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-1{gap:.25rem}.sm\:gap-3{gap:.75rem}.sm\:gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.sm\:rounded-xl{border-radius:.75rem}.sm\:p-10{padding:2.5rem}.sm\:px-12{padding-left:3rem;padding-right:3rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-1{padding-top:.25rem;padding-bottom:.25rem}.sm\:py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.sm\:pe-3{padding-inline-end:.75rem}.sm\:pe-6{padding-inline-end:1.5rem}.sm\:ps-3{padding-inline-start:.75rem}.sm\:ps-6{padding-inline-start:1.5rem}.sm\:pt-1{padding-top:.25rem}.sm\:pt-1\.5{padding-top:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:leading-6{line-height:1.5rem}.sm\:first-of-type\:ps-3:first-of-type{padding-inline-start:.75rem}.sm\:first-of-type\:ps-6:first-of-type{padding-inline-start:1.5rem}.sm\:last-of-type\:pe-3:last-of-type{padding-inline-end:.75rem}.sm\:last-of-type\:pe-6:last-of-type{padding-inline-end:1.5rem}}@media (min-width: 768px){.md\:bottom-4{bottom:1rem}.md\:order-first{order:-9999}.md\:col-\[--col-span-md\]{grid-column:var(--col-span-md)}.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-start-\[--col-start-md\]{grid-column-start:var(--col-start-md)}.md\:block{display:block}.md\:flex{display:flex}.md\:table-cell{display:table-cell}.md\:inline-grid{display:inline-grid}.md\:hidden{display:none}.md\:columns-\[--cols-md\]{-moz-columns:var(--cols-md);columns:var(--cols-md)}.md\:grid-flow-col{grid-auto-flow:column}.md\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-\[--cols-md\]{grid-template-columns:var(--cols-md)}.md\:flex-row{flex-direction:row}.md\:items-start{align-items:flex-start}.md\:items-end{align-items:flex-end}.md\:items-center{align-items:center}.md\:justify-end{justify-content:flex-end}.md\:gap-1{gap:.25rem}.md\:gap-3{gap:.75rem}.md\:divide-y-0>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(0px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(0px * var(--tw-divide-y-reverse))}.md\:rounded-xl{border-radius:.75rem}.md\:p-20{padding:5rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:pe-3{padding-inline-end:.75rem}.md\:pe-6{padding-inline-end:1.5rem}.md\:ps-3{padding-inline-start:.75rem}}@media (min-width: 1024px){.lg\:sticky{position:sticky}.lg\:z-0{z-index:0}.lg\:col-\[--col-span-lg\]{grid-column:var(--col-span-lg)}.lg\:col-start-\[--col-start-lg\]{grid-column-start:var(--col-start-lg)}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:inline-grid{display:inline-grid}.lg\:hidden{display:none}.lg\:h-full{height:100%}.lg\:max-w-xs{max-width:20rem}.lg\:-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.lg\:columns-\[--cols-lg\]{-moz-columns:var(--cols-lg);columns:var(--cols-lg)}.lg\:grid-cols-\[--cols-lg\]{grid-template-columns:var(--cols-lg)}.lg\:flex-row{flex-direction:row}.lg\:items-start{align-items:flex-start}.lg\:items-end{align-items:flex-end}.lg\:items-center{align-items:center}.lg\:gap-1{gap:.25rem}.lg\:gap-3{gap:.75rem}.lg\:bg-transparent{background-color:transparent}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:pe-8{padding-inline-end:2rem}.lg\:shadow-none{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.lg\:shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.lg\:ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.lg\:transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.lg\:transition-none{transition-property:none}.lg\:delay-100{transition-delay:.1s}:is([dir="rtl"] .rtl\:lg\:-translate-x-0){--tw-translate-x: -0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is([dir="rtl"] .rtl\:lg\:translate-x-full){--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:is(.dark .dark\:lg\:bg-transparent){background-color:transparent}}@media (min-width: 1280px){.xl\:col-\[--col-span-xl\]{grid-column:var(--col-span-xl)}.xl\:col-start-\[--col-start-xl\]{grid-column-start:var(--col-start-xl)}.xl\:block{display:block}.xl\:table-cell{display:table-cell}.xl\:inline-grid{display:inline-grid}.xl\:hidden{display:none}.xl\:columns-\[--cols-xl\]{-moz-columns:var(--cols-xl);columns:var(--cols-xl)}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-\[--cols-xl\]{grid-template-columns:var(--cols-xl)}.xl\:flex-row{flex-direction:row}.xl\:items-start{align-items:flex-start}.xl\:items-end{align-items:flex-end}.xl\:items-center{align-items:center}.xl\:gap-1{gap:.25rem}.xl\:gap-3{gap:.75rem}}@media (min-width: 1536px){.\32xl\:col-\[--col-span-2xl\]{grid-column:var(--col-span-2xl)}.\32xl\:col-start-\[--col-start-2xl\]{grid-column-start:var(--col-start-2xl)}.\32xl\:block{display:block}.\32xl\:table-cell{display:table-cell}.\32xl\:inline-grid{display:inline-grid}.\32xl\:hidden{display:none}.\32xl\:columns-\[--cols-2xl\]{-moz-columns:var(--cols-2xl);columns:var(--cols-2xl)}.\32xl\:grid-cols-\[--cols-2xl\]{grid-template-columns:var(--cols-2xl)}.\32xl\:flex-row{flex-direction:row}.\32xl\:items-start{align-items:flex-start}.\32xl\:items-end{align-items:flex-end}.\32xl\:items-center{align-items:center}.\32xl\:gap-1{gap:.25rem}.\32xl\:gap-3{gap:.75rem}}.\[\&\.trix-active\]\:bg-gray-50.trix-active{--tw-bg-opacity: 1;background-color:rgba(var(--gray-50),var(--tw-bg-opacity))}.\[\&\.trix-active\]\:text-primary-600.trix-active{--tw-text-opacity: 1;color:rgba(var(--primary-600),var(--tw-text-opacity))}:is(.dark .dark\:\[\&\.trix-active\]\:bg-white\/5.trix-active){background-color:#ffffff0d}:is(.dark .dark\:\[\&\.trix-active\]\:text-primary-400.trix-active){--tw-text-opacity: 1;color:rgba(var(--primary-400),var(--tw-text-opacity))}.\[\&\:not\(\:first-of-type\)\]\:border-s:not(:first-of-type){border-inline-start-width:1px}.\[\&\:not\(\:last-of-type\)\]\:border-e:not(:last-of-type){border-inline-end-width:1px}.\[\&\:not\(\:nth-child\(1_of_\.fi-btn\)\)\]\:shadow-\[-1px_0_0_0_theme\(colors\.gray\.200\)\]:not(:nth-child(1 of .fi-btn)){--tw-shadow: -1px 0 0 0 rgba(var(--gray-200), 1);--tw-shadow-colored: -1px 0 0 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}:is(.dark .dark\:\[\&\:not\(\:nth-child\(1_of_\.fi-btn\)\)\]\:shadow-\[-1px_0_0_0_theme\(colors\.white\/20\%\)\]:not(:nth-child(1 of .fi-btn))){--tw-shadow: -1px 0 0 0 rgb(255 255 255 / 20%);--tw-shadow-colored: -1px 0 0 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.\[\&\:not\(\:nth-last-child\(1_of_\.fi-btn\)\)\]\:me-px:not(:nth-last-child(1 of .fi-btn)){margin-inline-end:1px}.\[\&\:nth-child\(1_of_\.fi-btn\)\]\:rounded-s-lg:nth-child(1 of .fi-btn){border-start-start-radius:.5rem;border-end-start-radius:.5rem}.\[\&\:nth-last-child\(1_of_\.fi-btn\)\]\:rounded-e-lg:nth-last-child(1 of .fi-btn){border-start-end-radius:.5rem;border-end-end-radius:.5rem}.\[\&\>\*\:first-child\]\:relative>*:first-child{position:relative}.\[\&\>\*\:first-child\]\:mt-0>*:first-child{margin-top:0}.\[\&\>\*\:first-child\]\:before\:absolute>*:first-child:before{content:var(--tw-content);position:absolute}.\[\&\>\*\:first-child\]\:before\:inset-y-0>*:first-child:before{content:var(--tw-content);top:0px;bottom:0px}.\[\&\>\*\:first-child\]\:before\:start-0>*:first-child:before{content:var(--tw-content);inset-inline-start:0px}.\[\&\>\*\:first-child\]\:before\:w-0\.5>*:first-child:before{content:var(--tw-content);width:.125rem}.\[\&\>\*\:first-child\]\:before\:bg-primary-600>*:first-child:before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgba(var(--primary-600),var(--tw-bg-opacity))}:is(.dark .\[\&\>\*\:first-child\]\:dark\:before\:bg-primary-500)>*:first-child:before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:rgba(var(--primary-500),var(--tw-bg-opacity))}.\[\&\>\*\:last-child\]\:mb-0>*:last-child{margin-bottom:0}.\[\&_\.choices\\_\\_inner\]\:ps-0 .choices__inner{padding-inline-start:0px}.\[\&_\.fi-badge-delete-button\]\:hidden .fi-badge-delete-button{display:none}.\[\&_\.filepond--root\]\:font-sans .filepond--root{font-family:var(--font-family),ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}.\[\&_optgroup\]\:bg-white optgroup{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}:is(.dark .\[\&_optgroup\]\:dark\:bg-gray-900) optgroup{--tw-bg-opacity: 1;background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}.\[\&_option\]\:bg-white option{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}:is(.dark .\[\&_option\]\:dark\:bg-gray-900) option{--tw-bg-opacity: 1;background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}:checked+*>.\[\:checked\+\*\>\&\]\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}@media (hover:hover){.\[\@media\(hover\:hover\)\]\:transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.\[\@media\(hover\:hover\)\]\:duration-75{transition-duration:75ms}}input:checked+.\[input\:checked\+\&\]\:bg-custom-600{--tw-bg-opacity: 1;background-color:rgba(var(--c-600),var(--tw-bg-opacity))}input:checked+.\[input\:checked\+\&\]\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}input:checked+.\[input\:checked\+\&\]\:ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input:checked+.\[input\:checked\+\&\]\:hover\:bg-custom-500:hover{--tw-bg-opacity: 1;background-color:rgba(var(--c-500),var(--tw-bg-opacity))}:is(.dark input:checked+.dark\:\[input\:checked\+\&\]\:bg-custom-500){--tw-bg-opacity: 1;background-color:rgba(var(--c-500),var(--tw-bg-opacity))}:is(.dark input:checked+.dark\:\[input\:checked\+\&\]\:hover\:bg-custom-400:hover){--tw-bg-opacity: 1;background-color:rgba(var(--c-400),var(--tw-bg-opacity))}input:checked:focus-visible+.\[input\:checked\:focus-visible\+\&\]\:ring-custom-500\/50{--tw-ring-color: rgba(var(--c-500), .5)}:is(.dark input:checked:focus-visible+.dark\:\[input\:checked\:focus-visible\+\&\]\:ring-custom-400\/50){--tw-ring-color: rgba(var(--c-400), .5)}input:focus-visible+.\[input\:focus-visible\+\&\]\:z-10{z-index:10}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}input:focus-visible+.\[input\:focus-visible\+\&\]\:ring-gray-950\/10{--tw-ring-color: rgba(var(--gray-950), .1)}:is(.dark input:focus-visible+.dark\:\[input\:focus-visible\+\&\]\:ring-white\/20){--tw-ring-color: rgb(255 255 255 / .2)} diff --git a/public/build/manifest.json b/public/build/manifest.json index 3cf47eb2..4d4438ff 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -8,5 +8,10 @@ "file": "assets/cachet.6977faaa.css", "src": "resources/css/cachet.css", "isEntry": true + }, + "resources/css/dashboard/theme.css": { + "file": "assets/theme.c49c6bb2.css", + "src": "resources/css/dashboard/theme.css", + "isEntry": true } } \ No newline at end of file diff --git a/resources/css/dashboard/tailwind.config.js b/resources/css/dashboard/tailwind.config.js new file mode 100644 index 00000000..315b666b --- /dev/null +++ b/resources/css/dashboard/tailwind.config.js @@ -0,0 +1,9 @@ +import preset from '../../../vendor/filament/filament/tailwind.config.preset' + +export default { + presets: [preset], + content: [ + './resources/views/filament/**/*.blade.php', + './vendor/filament/**/*.blade.php', + ], +} diff --git a/resources/css/dashboard/theme.css b/resources/css/dashboard/theme.css new file mode 100644 index 00000000..c3a62491 --- /dev/null +++ b/resources/css/dashboard/theme.css @@ -0,0 +1,3 @@ +@import '/vendor/filament/filament/resources/css/theme.css'; + +@config 'tailwind.config.js'; diff --git a/resources/svg/clock.svg b/resources/svg/clock.svg new file mode 100644 index 00000000..266730ee --- /dev/null +++ b/resources/svg/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/views/components/icons/major-outage.blade.php b/resources/svg/component-major-outage.svg similarity index 97% rename from resources/views/components/icons/major-outage.blade.php rename to resources/svg/component-major-outage.svg index 1e70f211..d48476a2 100644 --- a/resources/views/components/icons/major-outage.blade.php +++ b/resources/svg/component-major-outage.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/views/components/icons/check-circle.blade.php b/resources/svg/component-operational.svg similarity index 95% rename from resources/views/components/icons/check-circle.blade.php rename to resources/svg/component-operational.svg index 416abb22..446ad634 100644 --- a/resources/views/components/icons/check-circle.blade.php +++ b/resources/svg/component-operational.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/views/components/icons/partial-outage.blade.php b/resources/svg/component-partial-outage.svg similarity index 98% rename from resources/views/components/icons/partial-outage.blade.php rename to resources/svg/component-partial-outage.svg index 8e4673bf..a548f31d 100644 --- a/resources/views/components/icons/partial-outage.blade.php +++ b/resources/svg/component-partial-outage.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/views/components/icons/performance-issues.blade.php b/resources/svg/component-performance-issues.svg similarity index 98% rename from resources/views/components/icons/performance-issues.blade.php rename to resources/svg/component-performance-issues.svg index cc424e8e..3e88cb16 100644 --- a/resources/views/components/icons/performance-issues.blade.php +++ b/resources/svg/component-performance-issues.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/svg/components.svg b/resources/svg/components.svg new file mode 100644 index 00000000..16c1d73c --- /dev/null +++ b/resources/svg/components.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/dashboard.svg b/resources/svg/dashboard.svg new file mode 100644 index 00000000..037b6ccf --- /dev/null +++ b/resources/svg/dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-fixed.svg b/resources/svg/incident-fixed.svg new file mode 100644 index 00000000..970f79ae --- /dev/null +++ b/resources/svg/incident-fixed.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-identified.svg b/resources/svg/incident-identified.svg new file mode 100644 index 00000000..1a82af53 --- /dev/null +++ b/resources/svg/incident-identified.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-investigating.svg b/resources/svg/incident-investigating.svg new file mode 100644 index 00000000..58e16a7c --- /dev/null +++ b/resources/svg/incident-investigating.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-templates.svg b/resources/svg/incident-templates.svg new file mode 100644 index 00000000..2db997a0 --- /dev/null +++ b/resources/svg/incident-templates.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-updates.svg b/resources/svg/incident-updates.svg new file mode 100644 index 00000000..2db997a0 --- /dev/null +++ b/resources/svg/incident-updates.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident-watching.svg b/resources/svg/incident-watching.svg new file mode 100644 index 00000000..9dde4e68 --- /dev/null +++ b/resources/svg/incident-watching.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/incident.svg b/resources/svg/incident.svg new file mode 100644 index 00000000..970f79ae --- /dev/null +++ b/resources/svg/incident.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/maintenance.svg b/resources/svg/maintenance.svg new file mode 100644 index 00000000..1d21fa76 --- /dev/null +++ b/resources/svg/maintenance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/metrics.svg b/resources/svg/metrics.svg new file mode 100644 index 00000000..cc4a49dc --- /dev/null +++ b/resources/svg/metrics.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/settings.svg b/resources/svg/settings.svg new file mode 100644 index 00000000..8011e42a --- /dev/null +++ b/resources/svg/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/svg/subscribers.svg b/resources/svg/subscribers.svg new file mode 100644 index 00000000..43e39682 --- /dev/null +++ b/resources/svg/subscribers.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/views/components/icons/unknown.blade.php b/resources/svg/unknown.svg similarity index 97% rename from resources/views/components/icons/unknown.blade.php rename to resources/svg/unknown.svg index 13cac34a..2b60afe7 100644 --- a/resources/views/components/icons/unknown.blade.php +++ b/resources/svg/unknown.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/views/components/badge.blade.php b/resources/views/components/badge.blade.php index 7b578b53..b691f34d 100644 --- a/resources/views/components/badge.blade.php +++ b/resources/views/components/badge.blade.php @@ -7,7 +7,7 @@ 'unknown' => 'bg-blue-200', ][$type] }} flex items-center gap-1 rounded-full px-2 py-1 text-sm font-semibold leading-tight"> - + @svg('cachet-component-'.$type, 'h-6 w-6')
{{ str($type)->title() }}
diff --git a/resources/views/components/component-group.blade.php b/resources/views/components/component-group.blade.php index a74df20e..4bbdfb8d 100644 --- a/resources/views/components/component-group.blade.php +++ b/resources/views/components/component-group.blade.php @@ -6,7 +6,7 @@

{{ $title }}

- + 4 incidents @@ -20,11 +20,11 @@
Envoyer
-

Updated Thursday 7th September 2023 13:30:03

+

Updated Monday 1st January 2024 13:30:03

diff --git a/resources/views/components/icons/chevron-up.blade.php b/resources/views/components/icons/chevron-up.blade.php deleted file mode 100644 index 63b1d63f..00000000 --- a/resources/views/components/icons/chevron-up.blade.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/views/components/icons/clock.blade.php b/resources/views/components/icons/clock.blade.php deleted file mode 100644 index 5cc96066..00000000 --- a/resources/views/components/icons/clock.blade.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/views/components/icons/info.blade.php b/resources/views/components/icons/info.blade.php deleted file mode 100644 index 1e490d33..00000000 --- a/resources/views/components/icons/info.blade.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/views/components/icons/operational.blade.php b/resources/views/components/icons/operational.blade.php deleted file mode 100644 index 496e82a5..00000000 --- a/resources/views/components/icons/operational.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/views/components/incident.blade.php b/resources/views/components/incident.blade.php index e9a2f5db..ceeb091b 100644 --- a/resources/views/components/incident.blade.php +++ b/resources/views/components/incident.blade.php @@ -23,7 +23,7 @@
- + @svg('cachet-unknown', 'h-5 w-5')

Incident Update Title

3 Days Ago — Friday 1st December 2023, 14:00 @@ -32,7 +32,7 @@
- + @svg('cachet-incident-investigating', 'h-5 w-5')

Incident Update Title

3 Days Ago — Friday 1st December 2023, 14:00 diff --git a/resources/views/components/incidents.blade.php b/resources/views/components/incidents.blade.php index 0c30cfc4..1101573e 100644 --- a/resources/views/components/incidents.blade.php +++ b/resources/views/components/incidents.blade.php @@ -5,6 +5,7 @@
+
diff --git a/resources/views/components/logo.blade.php b/resources/views/components/logo.blade.php index f2898eda..71c4d97b 100644 --- a/resources/views/components/logo.blade.php +++ b/resources/views/components/logo.blade.php @@ -1,4 +1,4 @@ -merge(['class']) }}> +merge(['class']) }}>
- + @svg('cachet-clock', 'h-5 w-5') 2 minutes ago · diff --git a/resources/views/filament/pages/settings/manage-application-settings.blade.php b/resources/views/filament/pages/settings/manage-application-settings.blade.php new file mode 100644 index 00000000..3525e16b --- /dev/null +++ b/resources/views/filament/pages/settings/manage-application-settings.blade.php @@ -0,0 +1,9 @@ + + + {{ $this->form }} + +
+ Save +
+
+
diff --git a/resources/views/filament/widgets/components.blade.php b/resources/views/filament/widgets/components.blade.php new file mode 100644 index 00000000..d605593e --- /dev/null +++ b/resources/views/filament/widgets/components.blade.php @@ -0,0 +1,7 @@ + + +
+

Component Manager

+
+
+
diff --git a/resources/views/filament/widgets/support.blade.php b/resources/views/filament/widgets/support.blade.php new file mode 100644 index 00000000..178726cd --- /dev/null +++ b/resources/views/filament/widgets/support.blade.php @@ -0,0 +1,10 @@ + + +
+

Support Cachet

+

+ Please consider supporting Cachet via GitHub Sponsors. +

+
+
+
diff --git a/src/CachetCoreServiceProvider.php b/src/CachetCoreServiceProvider.php index e9de8e25..0da40cd4 100644 --- a/src/CachetCoreServiceProvider.php +++ b/src/CachetCoreServiceProvider.php @@ -2,6 +2,7 @@ namespace Cachet; +use BladeUI\Icons\Factory; use Illuminate\Foundation\Console\AboutCommand; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Http; @@ -18,6 +19,13 @@ public function register(): void if (! defined('CACHET_PATH')) { define('CACHET_PATH', realpath(__DIR__.'/../')); } + + $this->callAfterResolving(Factory::class, function (Factory $factory) { + $factory->add('cachet', [ + 'path' => __DIR__.'/../resources/svg', + 'prefix' => 'cachet', + ]); + }); } /** @@ -35,7 +43,6 @@ public function boot(): void Route::middlewareGroup('cachet', config('cachet.middleware', [])); Route::middlewareGroup('cachet:api', config('cachet.api_middleware', [])); - Route::middlewareGroup('cachet:dashboard', config('cachet.dashboard_middleware', [])); $this->registerResources(); $this->registerPublishing(); diff --git a/src/CachetDashboardServiceProvider.php b/src/CachetDashboardServiceProvider.php new file mode 100644 index 00000000..a95b35c1 --- /dev/null +++ b/src/CachetDashboardServiceProvider.php @@ -0,0 +1,72 @@ +id('cachet') + ->font('switzer', 'https://fonts.cdnfonts.com/css/switzer') + ->default() + ->login() + ->passwordReset() + ->brandLogo(fn () => view('cachet::components.logo')) + ->colors([ + 'primary' => Color::rgb('rgb(4, 193, 71)'), + ]) + ->viteTheme('resources/css/dashboard/theme.css', 'vendor/cachethq/cachet') + ->discoverResources(__DIR__.'/Filament/Resources', 'Cachet\\Filament\\Resources') + ->discoverPages(__DIR__.'/Filament/Pages', 'Cachet\\Filament\\Pages') + ->discoverWidgets(__DIR__.'/Filament/Widgets', 'Cachet\\Filament\\Widgets') + ->navigationGroups([ + NavigationGroup::make('Settings') + ->collapsed() + ->icon('cachet-settings'), + NavigationGroup::make('Resources') + ->collapsible(false), + ]) + ->navigationItems([ + NavigationItem::make('Status Page') +// ->url(route('cachet.status-page')) + ->group('Resources') + ->icon('cachet-component-performance-issues'), + NavigationItem::make('Documentation') + ->url('https://docs.cachethq.io') + ->group('Resources') + ->icon('heroicon-o-book-open'), + ]) + ->middleware([ + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + AuthenticateSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, + DisableBladeIconComponents::class, + DispatchServingFilamentEvent::class, + ]) + ->authMiddleware([ + Authenticate::class, + ]) + ->path('/status/dashboard'); + } +} diff --git a/src/CachetServiceProvider.php b/src/CachetServiceProvider.php index f0d00d7e..6d205cb4 100644 --- a/src/CachetServiceProvider.php +++ b/src/CachetServiceProvider.php @@ -2,18 +2,65 @@ namespace Cachet; +use Composer\InstalledVersions; +use Doctrine\Common\Cache\Cache; +use Illuminate\Foundation\Application; +use Illuminate\Foundation\Console\AboutCommand; +use Illuminate\Routing\Router; +use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; class CachetServiceProvider extends ServiceProvider { + /** + * Register any package services. + */ + public function register(): void + { + $this->mergeConfigFrom( + __DIR__.'/../config/cachet.php', 'cachet' + ); + + $this->app->singleton(Cachet::class); + } + /** * Bootstrap any application services. */ public function boot(): void { - if ($this->app->runningInConsole()) { - $this->registerPublishing(); - } + $this->registerRoutes(); + $this->registerResources(); + $this->registerPublishing(); + $this->registerCommands(); + } + + /** + * Register the package's routes. + */ + private function registerRoutes() + { + $this->callAfterResolving('router', function (Router $router, Application $application) { + $router->group([ + 'domain' => config('cachet.domain', null), + 'as' => 'cachet.api.', + 'prefix' => Cachet::path().'/api', + 'middleware' => 'cachet:api', + ], function (Router $router) { + $this->loadRoutesFrom(__DIR__.'/../routes/api.php'); + }); + + Cachet::routes() + ->register(); + }); + } + + /** + * Register the package's resources. + */ + private function registerResources(): void + { + $this->loadViewsFrom(__DIR__.'/../resources/views', 'cachet'); } /** @@ -21,16 +68,31 @@ public function boot(): void */ private function registerPublishing(): void { - $this->publishes([ - __DIR__.'/../config/cachet.php' => config_path('cachet.php'), - ], 'cachet-config'); + if ($this->app->runningInConsole()) { + $this->publishes([ + __DIR__.'/../config/cachet.php' => config_path('cachet.php'), + ], ['cachet', 'cachet-config']); + + $this->publishes([ + __DIR__.'/../resources/views/status-page/index.blade.php' => resource_path('views/vendor/cachet/status-page/index.blade.php'), + ], ['cachet', 'cachet-views']); - $this->publishes([ - __DIR__.'/../resources/views/status-page/index.blade.php' => resource_path('views/vendor/cachet/status-page/index.blade.php'), - ], 'cachet-views'); + $this->publishes([ + __DIR__.'/../public/build/' => public_path('vendor/cachethq/cachet'), + ], ['cachet', 'cachet-assets']); + } + } - $this->publishes([ - __DIR__.'/../public/build/' => public_path('vendor/cachethq/cachet'), - ], 'cachet-assets'); + /** + * Register the package's commands. + */ + private function registerCommands(): void + { + if ($this->app->runningInConsole()) { + AboutCommand::add('Cache', fn () => [ + 'Version' => app(Cachet::class)->version(), + 'Enabled' => AboutCommand::format(config('cachet.enabled'), console: fn ($value) => $value ? 'ENABLED' : 'OFF'), + ]); + } } } diff --git a/src/Enums/ComponentGroupVisibilityEnum.php b/src/Enums/ComponentGroupVisibilityEnum.php index 5ff363d7..47840b9e 100644 --- a/src/Enums/ComponentGroupVisibilityEnum.php +++ b/src/Enums/ComponentGroupVisibilityEnum.php @@ -2,16 +2,15 @@ namespace Cachet\Enums; -enum ComponentGroupVisibilityEnum: int +use Filament\Support\Contracts\HasLabel; + +enum ComponentGroupVisibilityEnum: int implements HasLabel { case expanded = 0; case collapsed = 1; case collapsed_unless_incident = 2; - /** - * Get the human-readable name of the enum value. - */ - public function getName(): string + public function getLabel(): string { return match ($this->value) { self::expanded->value => __('Always expanded'), diff --git a/src/Enums/ComponentStatusEnum.php b/src/Enums/ComponentStatusEnum.php index dcbebffb..455abe9d 100644 --- a/src/Enums/ComponentStatusEnum.php +++ b/src/Enums/ComponentStatusEnum.php @@ -2,24 +2,47 @@ namespace Cachet\Enums; -enum ComponentStatusEnum: int +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum ComponentStatusEnum: int implements HasColor, HasIcon, HasLabel { case operational = 1; case performance_issues = 2; case partial_outage = 3; case major_outage = 4; - /** - * Get the human-readable name of the enum value. - */ - public function getName(): string + public function getLabel(): string { - return match ($this->value) { - self::operational->value => __('Operational'), - self::performance_issues->value => __('Performance Issues'), - self::partial_outage->value => __('Partial Outage'), - self::major_outage->value => __('Major Outage'), + return match ($this) { + self::operational => __('Operational'), + self::performance_issues => __('Performance Issues'), + self::partial_outage => __('Partial Outage'), + self::major_outage => __('Major Outage'), default => __('Unknown Component Status'), }; } + + public function getIcon(): ?string + { + return match ($this) { + self::operational => 'cachet-component-operational', + self::performance_issues => 'cachet-component-performance-issues', + self::partial_outage => 'cachet-component-partial-outage', + self::major_outage => 'cachet-component-major-outage', + default => 'cachet-unknown', + }; + } + + public function getColor(): string|array|null + { + return match ($this) { + self::operational => 'success', + self::performance_issues => 'info', + self::partial_outage => 'warning', + self::major_outage => 'danger', + default => 'secondary', + }; + } } diff --git a/src/Enums/IncidentStatusEnum.php b/src/Enums/IncidentStatusEnum.php index ff666fc6..2b1c9d52 100644 --- a/src/Enums/IncidentStatusEnum.php +++ b/src/Enums/IncidentStatusEnum.php @@ -2,23 +2,44 @@ namespace Cachet\Enums; -enum IncidentStatusEnum: int +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum IncidentStatusEnum: int implements HasColor, HasIcon, HasLabel { case investigating = 1; case identified = 2; case watching = 3; case fixed = 4; - /** - * Get the human-readable name of the enum value. - */ - public function getName(): string + public function getLabel(): string + { + return match ($this) { + self::investigating => __('Investigating'), + self::identified => __('Identified'), + self::watching => __('Watching'), + self::fixed => __('Fixed'), + }; + } + + public function getIcon(): ?string + { + return match ($this) { + self::investigating => 'cachet-incident-investigating', + self::identified => 'cachet-incident-identified', + self::watching => 'cachet-incident-watching', + self::fixed => 'cachet-incident-fixed', + }; + } + + public function getColor(): string|array|null { - return match ($this->value) { - self::investigating->value => __('Investigating'), - self::identified->value => __('Identified'), - self::watching->value => __('Watching'), - self::fixed->value => __('Fixed'), + return match ($this) { + self::investigating => 'warning', + self::identified => 'purple', + self::watching => 'info', + self::fixed => 'success', }; } } diff --git a/src/Enums/IncidentTemplateEngineEnum.php b/src/Enums/IncidentTemplateEngineEnum.php index 8508d4d1..549c57eb 100644 --- a/src/Enums/IncidentTemplateEngineEnum.php +++ b/src/Enums/IncidentTemplateEngineEnum.php @@ -2,8 +2,24 @@ namespace Cachet\Enums; -enum IncidentTemplateEngineEnum +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum IncidentTemplateEngineEnum: string implements HasIcon, HasLabel { - case blade; - case twig; + case blade = 'blade'; + case twig = 'twig'; + + public function getLabel(): ?string + { + return match ($this) { + self::blade => __('Laravel Blade'), + self::twig => __('Twig'), + }; + } + + public function getIcon(): ?string + { + // TODO: Implement getIcon() method. + } } diff --git a/src/Enums/MetricTypeEnum.php b/src/Enums/MetricTypeEnum.php index 55176143..98e6f360 100644 --- a/src/Enums/MetricTypeEnum.php +++ b/src/Enums/MetricTypeEnum.php @@ -2,8 +2,27 @@ namespace Cachet\Enums; -enum MetricTypeEnum: int +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum MetricTypeEnum: int implements HasIcon, HasLabel { case sum = 0; case average = 1; + + public function getIcon(): ?string + { + return match ($this) { + self::sum => 'cachet-metrics', + self::average => 'cachet-metrics', + }; + } + + public function getLabel(): ?string + { + return match ($this) { + self::sum => __('Sum'), + self::average => __('Average'), + }; + } } diff --git a/src/Enums/MetricViewEnum.php b/src/Enums/MetricViewEnum.php index 3d139cfd..94d1c35e 100644 --- a/src/Enums/MetricViewEnum.php +++ b/src/Enums/MetricViewEnum.php @@ -2,7 +2,9 @@ namespace Cachet\Enums; -enum MetricViewEnum: int +use Filament\Support\Contracts\HasLabel; + +enum MetricViewEnum: int implements HasLabel { case last_hour = 0; case today = 1; @@ -12,7 +14,7 @@ enum MetricViewEnum: int /** * Get the human-readable name for the metric view. */ - public function getName(): string + public function getLabel(): string { return match ($this) { self::last_hour => __('Last Hour'), diff --git a/src/Enums/ResourceVisibilityEnum.php b/src/Enums/ResourceVisibilityEnum.php index 92349894..3503a6eb 100644 --- a/src/Enums/ResourceVisibilityEnum.php +++ b/src/Enums/ResourceVisibilityEnum.php @@ -2,9 +2,40 @@ namespace Cachet\Enums; -enum ResourceVisibilityEnum: int +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum ResourceVisibilityEnum: int implements HasColor, HasIcon, HasLabel { case authenticated = 0; case guest = 1; case hidden = 2; + + public function getIcon(): ?string + { + return match ($this) { + self::authenticated => 'heroicon-o-lock-closed', + self::guest => 'heroicon-o-eye', + self::hidden => 'heroicon-o-eye-slash', + }; + } + + public function getLabel(): ?string + { + return match ($this) { + self::authenticated => __('Users'), + self::guest => __('Guests'), + self::hidden => __('Always Hidden'), + }; + } + + public function getColor(): string|array|null + { + return match ($this) { + self::authenticated => 'danger', + self::guest => 'primary', + self::hidden => 'warning', + }; + } } diff --git a/src/Enums/ScheduleStatusEnum.php b/src/Enums/ScheduleStatusEnum.php index 9c591f3d..dd3da6c2 100644 --- a/src/Enums/ScheduleStatusEnum.php +++ b/src/Enums/ScheduleStatusEnum.php @@ -2,24 +2,16 @@ namespace Cachet\Enums; -enum ScheduleStatusEnum: int +use Filament\Support\Contracts\HasColor; +use Filament\Support\Contracts\HasIcon; +use Filament\Support\Contracts\HasLabel; + +enum ScheduleStatusEnum: int implements HasColor, HasIcon, HasLabel { case upcoming = 0; case in_progress = 1; case complete = 2; - /** - * Get the human-readable name of the enum value. - */ - public function getName(): string - { - return match ($this->value) { - self::upcoming->value => __('Upcoming'), - self::in_progress->value => __('In Progress'), - self::complete->value => __('Complete'), - }; - } - /** * Get the statuses that are incomplete. */ @@ -41,4 +33,31 @@ public static function upcoming(): array self::in_progress->value, ]; } + + public function getLabel(): string + { + return match ($this) { + self::upcoming => __('Upcoming'), + self::in_progress => __('In Progress'), + self::complete => __('Complete'), + }; + } + + public function getColor(): string|array|null + { + return match ($this) { + self::upcoming => 'info', + self::in_progress => 'warning', + self::complete => 'success', + }; + } + + public function getIcon(): ?string + { + return match ($this) { + self::upcoming => 'heroicon-m-calendar-days', + self::in_progress => 'heroicon-m-ellipsis-horizontal-circle', + self::complete => 'heroicon-m-check-circle', + }; + } } diff --git a/src/Enums/UserLevelEnum.php b/src/Enums/UserLevelEnum.php index f053b175..ed1d25b4 100644 --- a/src/Enums/UserLevelEnum.php +++ b/src/Enums/UserLevelEnum.php @@ -7,10 +7,7 @@ enum UserLevelEnum: int case admin = 1; case user = 2; - /** - * Get the human-readable name of the enum value. - */ - public function getName(): string + public function getLabel(): string { return match ($this->value) { self::admin->value => __('Admin'), diff --git a/src/Filament/Pages/Dashboard.php b/src/Filament/Pages/Dashboard.php new file mode 100644 index 00000000..8df765de --- /dev/null +++ b/src/Filament/Pages/Dashboard.php @@ -0,0 +1,8 @@ +form->fill( + Setting::pluck('value', 'name')->all() + ); + } + + public function form(Form $form): Form + { + return $form->schema([ + TextInput::make('app_name') + ->label('App Name') + ->placeholder('Cachet'), + ])->columns(2)->statePath('data'); + } + + public function save() + { + $data = collect($this->form->getState())->map(fn ($value, $name) => [ + 'value' => $value, + 'name' => $name, + ])->all(); + + // @todo Unique index. + Setting::upsert($data, 'name'); + } +} diff --git a/src/Filament/Resources/ComponentGroupResource.php b/src/Filament/Resources/ComponentGroupResource.php new file mode 100644 index 00000000..a30b3e7a --- /dev/null +++ b/src/Filament/Resources/ComponentGroupResource.php @@ -0,0 +1,90 @@ +schema([ + Forms\Components\Section::make()->columns(3)->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(255), + Forms\Components\ToggleButtons::make('visible') + ->inline() + ->options(ResourceVisibilityEnum::class) + ->default(ResourceVisibilityEnum::guest) + ->required(), + Forms\Components\Select::make('collapsed') + ->required() + ->options(ComponentGroupVisibilityEnum::class) + ->default(false), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('visible') + ->badge() + ->sortable(), + Tables\Columns\TextColumn::make('collapsed') + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListComponentGroups::route('/'), + 'create' => Pages\CreateComponentGroup::route('/create'), + 'edit' => Pages\EditComponentGroup::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/ComponentGroupResource/Pages/CreateComponentGroup.php b/src/Filament/Resources/ComponentGroupResource/Pages/CreateComponentGroup.php new file mode 100644 index 00000000..7b38828f --- /dev/null +++ b/src/Filament/Resources/ComponentGroupResource/Pages/CreateComponentGroup.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(255), + Forms\Components\ToggleButtons::make('status') + ->inline() + ->columnSpanFull() + ->options(ComponentStatusEnum::class) + ->required(), + Forms\Components\MarkdownEditor::make('description') + ->maxLength(255) + ->columnSpanFull(), + Forms\Components\Select::make('component_group_id') + ->relationship('group', 'name') + ->searchable() + ->preload() + ->label(__('Component Group')), + Forms\Components\TextInput::make('link') + ->url() + ->hint(__('An optional link to the component.')), + ]), + + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\KeyValue::make('meta') + ->columnSpanFull(), + Forms\Components\Toggle::make('enabled') + ->required(), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('status') + ->badge() + ->sortable(), + Tables\Columns\TextColumn::make('order') + ->numeric() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('group.name') + ->sortable(), + Tables\Columns\IconColumn::make('enabled') + ->boolean() + ->toggleable(isToggledHiddenByDefault: false), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListComponents::route('/'), + 'create' => Pages\CreateComponent::route('/create'), + 'edit' => Pages\EditComponent::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/ComponentResource/Pages/CreateComponent.php b/src/Filament/Resources/ComponentResource/Pages/CreateComponent.php new file mode 100644 index 00000000..9cbde860 --- /dev/null +++ b/src/Filament/Resources/ComponentResource/Pages/CreateComponent.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(255), + Forms\Components\ToggleButtons::make('status') + ->inline() + ->columnSpanFull() + ->options(IncidentStatusEnum::class) + ->required(), + Forms\Components\MarkdownEditor::make('message') + ->required() + ->columnSpanFull(), + Forms\Components\ToggleButtons::make('visible') + ->inline() + ->options(ResourceVisibilityEnum::class) + ->default(ResourceVisibilityEnum::guest) + ->required(), + Forms\Components\Toggle::make('stickied') + ->required(), + ]), + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\Select::make('component_id') + ->multiple() + ->relationship('components', 'name') + ->searchable() + ->preload(), + Forms\Components\DateTimePicker::make('occurred_at'), + Forms\Components\Select::make('user_id') + ->relationship('user', 'name') + ->searchable() + ->preload() + ->createOptionForm([ + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(255), + Forms\Components\TextInput::make('email') + ->required() + ->email() + ->maxLength(255), + Forms\Components\TextInput::make('password') + ->required() + ->password() + ->confirmed() + ->minLength(8), + ]), + Forms\Components\Toggle::make('notifications') + ->label(__('Send notifications to subscribers.')) + ->required(), + Forms\Components\TextInput::make('guid') + ->required() + ->default(fn () => (string) Str::uuid()) + ->unique(ignoreRecord: true) + ->maxLength(36) + ->hidden(), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('status') + ->sortable() + ->badge(), + Tables\Columns\TextColumn::make('visible') + ->sortable() + ->badge(), + Tables\Columns\IconColumn::make('stickied') + ->toggleable(isToggledHiddenByDefault: true) + ->boolean(), + Tables\Columns\TextColumn::make('occurred_at') + ->dateTime() + ->sortable(), + Tables\Columns\IconColumn::make('notifications') + ->label(__('Notified Subscribers')) + ->boolean() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: false), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + Tables\Filters\TrashedFilter::make(), + Tables\Filters\SelectFilter::make('status') + ->options(IncidentStatusEnum::class), + ]) + ->actions([ + Action::make('add-update') + ->label(__('Record Update')) + ->color('info') + ->action(function (Incident $record, array $data) { + // $update = $record->incidentUpdates()->create($data); + + Notification::make() + ->title('Incident Updated') + ->body('Incident was updated...') + ->success() + ->send(); + }) + ->form([ + Forms\Components\MarkdownEditor::make('message')->required(), + Forms\Components\ToggleButtons::make('Status') + ->options(IncidentStatusEnum::class) + ->inline() + ->required(), + ]), + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + IncidentUpdatesRelationManager::class, + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListIncidents::route('/'), + 'create' => Pages\CreateIncident::route('/create'), + 'edit' => Pages\EditIncident::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/IncidentResource/Pages/CreateIncident.php b/src/Filament/Resources/IncidentResource/Pages/CreateIncident.php new file mode 100644 index 00000000..b438348c --- /dev/null +++ b/src/Filament/Resources/IncidentResource/Pages/CreateIncident.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\MarkdownEditor::make('message') + ->required() + ->columnSpanFull(), + Forms\Components\ToggleButtons::make('status') + ->inline() + ->columnSpanFull() + ->options(IncidentStatusEnum::class) + ->required(), + ]); + } + + public function table(Table $table): Table + { + return $table + ->recordTitleAttribute('title') + ->columns([ + Tables\Columns\TextColumn::make('incident.name') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('status') + ->sortable(), + Tables\Columns\TextColumn::make('user_id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->headerActions([ + Tables\Actions\CreateAction::make(), + ]) + ->actions([ + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } +} diff --git a/src/Filament/Resources/IncidentTemplateResource.php b/src/Filament/Resources/IncidentTemplateResource.php new file mode 100644 index 00000000..5fe9e269 --- /dev/null +++ b/src/Filament/Resources/IncidentTemplateResource.php @@ -0,0 +1,102 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->live() + ->afterStateUpdated(fn (Set $set, ?string $state) => $set('slug', Str::slug($state))), + Forms\Components\TextInput::make('slug') + ->required(), + Forms\Components\Textarea::make('template') + ->hint(fn (Get $get) => new HtmlString(Blade::render(match ($get('engine')) { + IncidentTemplateEngineEnum::twig => 'Twig Documentation', + IncidentTemplateEngineEnum::blade => 'Laravel Blade Documentation', + }))) + ->required() + ->rows(8) + ->columnSpanFull(), + Forms\Components\Select::make('engine') + ->options(IncidentTemplateEngineEnum::class) + ->default(IncidentTemplateEngineEnum::twig) + ->live() + ->required(), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('slug') + ->searchable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListIncidentTemplates::route('/'), + 'create' => Pages\CreateIncidentTemplate::route('/create'), + 'edit' => Pages\EditIncidentTemplate::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/IncidentTemplateResource/Pages/CreateIncidentTemplate.php b/src/Filament/Resources/IncidentTemplateResource/Pages/CreateIncidentTemplate.php new file mode 100644 index 00000000..27205fe4 --- /dev/null +++ b/src/Filament/Resources/IncidentTemplateResource/Pages/CreateIncidentTemplate.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(255), + Forms\Components\TextInput::make('suffix') + ->required() + ->maxLength(255) + ->placeholder('e.g. ms, %, etc.'), + Forms\Components\MarkdownEditor::make('description') + ->maxLength(255) + ->columnSpanFull(), + Forms\Components\TextInput::make('default_value') + ->numeric(), + Forms\Components\Select::make('calc_type') + ->label(__('Metric Type')) + ->required() + ->options(MetricTypeEnum::class) + ->default(MetricTypeEnum::sum), + Forms\Components\TextInput::make('places') + ->required() + ->numeric() + ->default(2), + Forms\Components\TextInput::make('default_view') + ->required() + ->numeric() + ->default(1), + Forms\Components\TextInput::make('threshold') + ->required() + ->numeric() + ->default(5), + Forms\Components\ToggleButtons::make('visible') + ->inline() + ->options(ResourceVisibilityEnum::class) + ->default(ResourceVisibilityEnum::guest) + ->required(), + Forms\Components\Toggle::make('display_chart') + ->default(true) + ->required(), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('suffix') + ->searchable(), + Tables\Columns\TextColumn::make('default_value') + ->numeric() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('calc_type') + ->badge() + ->sortable(), + Tables\Columns\IconColumn::make('display_chart') + ->boolean(), + Tables\Columns\TextColumn::make('places') + ->numeric() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('default_view') + ->sortable(), + Tables\Columns\TextColumn::make('threshold') + ->numeric() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('order') + ->numeric() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('visible') + ->badge() + ->sortable(), + Tables\Columns\TextColumn::make('points_count')->counts('metricPoints'), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListMetrics::route('/'), + 'create' => Pages\CreateMetric::route('/create'), + 'edit' => Pages\EditMetric::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/MetricResource/Pages/CreateMetric.php b/src/Filament/Resources/MetricResource/Pages/CreateMetric.php new file mode 100644 index 00000000..5350f5d3 --- /dev/null +++ b/src/Filament/Resources/MetricResource/Pages/CreateMetric.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('name') + ->required(), + Forms\Components\Select::make('status') + ->required() + ->options(ScheduleStatusEnum::class) + ->default(ScheduleStatusEnum::upcoming) + ->live(), + Forms\Components\MarkdownEditor::make('message') + ->columnSpanFull(), + Forms\Components\DateTimePicker::make('scheduled_at') + ->required(), + Forms\Components\DateTimePicker::make('completed_at') + ->visible(fn (Forms\Get $get): bool => $get('status') === ScheduleStatusEnum::complete), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('status') + ->badge() + ->sortable(), + Tables\Columns\TextColumn::make('scheduled_at') + ->dateTime() + ->sortable(), + Tables\Columns\TextColumn::make('completed_at') + ->dateTime() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\Action::make('complete') + ->visible(fn (Schedule $record): bool => in_array($record->status->value, ScheduleStatusEnum::incomplete())) + ->label(__('Complete Maintenance')) + ->form([ + Forms\Components\DateTimePicker::make('completed_at') + ->required(), + ]) + ->color('success') + ->action(fn (Schedule $record, array $data) => $record->update(['completed_at' => $data['completed_at'], 'status' => ScheduleStatusEnum::complete])), + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListSchedules::route('/'), + 'create' => Pages\CreateSchedule::route('/create'), + 'edit' => Pages\EditSchedule::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/ScheduleResource/Pages/CreateSchedule.php b/src/Filament/Resources/ScheduleResource/Pages/CreateSchedule.php new file mode 100644 index 00000000..fb7ca138 --- /dev/null +++ b/src/Filament/Resources/ScheduleResource/Pages/CreateSchedule.php @@ -0,0 +1,11 @@ +schema([ + Forms\Components\Section::make()->columns(2)->schema([ + Forms\Components\TextInput::make('email') + ->email() + ->required() + ->maxLength(255), + Forms\Components\TextInput::make('verify_code') + ->required() + ->default(fn () => Str::random()) + ->maxLength(255), + Forms\Components\DateTimePicker::make('verified_at'), + Forms\Components\Toggle::make('global') + ->required(), + // Forms\Components\TextInput::make('phone_number') + // ->tel(), + // Forms\Components\TextInput::make('slack_webhook_url'), + ]), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('email') + ->searchable(), + Tables\Columns\TextColumn::make('verify_code') + ->fontFamily('mono') + ->searchable(), + Tables\Columns\IconColumn::make('global') + ->boolean(), + Tables\Columns\TextColumn::make('phone_number') + ->searchable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('slack_webhook_url') + ->searchable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('verified_at') + ->dateTime() + ->sortable() + ->toggleable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + Tables\Actions\Action::make('verify') + ->label(__('Verify')) + ->color('warning') + ->action(fn (Subscriber $record) => $record->verify()) + ->requiresConfirmation(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListSubscribers::route('/'), + 'create' => Pages\CreateSubscriber::route('/create'), + 'edit' => Pages\EditSubscriber::route('/{record}/edit'), + ]; + } +} diff --git a/src/Filament/Resources/SubscriberResource/Pages/CreateSubscriber.php b/src/Filament/Resources/SubscriberResource/Pages/CreateSubscriber.php new file mode 100644 index 00000000..758f9ce0 --- /dev/null +++ b/src/Filament/Resources/SubscriberResource/Pages/CreateSubscriber.php @@ -0,0 +1,11 @@ +description(__('Total number of reported incidents.')) + ->chart(DB::table('incidents')->select(DB::raw('count(*) as total'), 'created_at')->groupBy('created_at')->get()->pluck('total')->toArray()) + ->icon('cachet-incident', IconPosition::Before) + ->color('info'), + Stat::make('Total Subscribers', Subscriber::count()) + ->description(__('Total number of reported incidents.')) + ->chart([2, 3, 5, 4, 6, 8, 10, 12, 14, 16, 18, 20]) + ->icon('cachet-incident', IconPosition::Before) + ->color('info'), + ]; + } +} diff --git a/src/Filament/Widgets/Support.php b/src/Filament/Widgets/Support.php new file mode 100644 index 00000000..cf0858a9 --- /dev/null +++ b/src/Filament/Widgets/Support.php @@ -0,0 +1,12 @@ + $this->stickied, 'notifications' => $this->notifications, 'status' => [ - 'human' => $this->status->getName(), + 'human' => $this->status->getLabel(), 'value' => $this->status->value, ], 'occurred' => [ diff --git a/src/Http/Resources/IncidentUpdate.php b/src/Http/Resources/IncidentUpdate.php index 43fac3e9..5dd06efd 100644 --- a/src/Http/Resources/IncidentUpdate.php +++ b/src/Http/Resources/IncidentUpdate.php @@ -13,7 +13,7 @@ public function toAttributes(Request $request): array 'id' => $this->id, 'message' => $this->message, 'status' => [ - 'human' => $this->status->getName(), + 'human' => $this->status->getLabel(), 'value' => $this->status->value, ], 'created' => [ diff --git a/src/Http/Resources/Schedule.php b/src/Http/Resources/Schedule.php index a5c66cec..5f62a5ef 100644 --- a/src/Http/Resources/Schedule.php +++ b/src/Http/Resources/Schedule.php @@ -14,7 +14,7 @@ public function toAttributes(Request $request): array 'name' => $this->name, 'message' => $this->message, 'status' => [ - 'human' => optional($this->status)->getName(), + 'human' => optional($this->status)->getLabel(), 'value' => optional($this->status)->value, ], 'scheduled' => [ diff --git a/src/Models/ComponentGroup.php b/src/Models/ComponentGroup.php index 49997343..3030c733 100644 --- a/src/Models/ComponentGroup.php +++ b/src/Models/ComponentGroup.php @@ -3,6 +3,7 @@ namespace Cachet\Models; use Cachet\Enums\ComponentGroupVisibilityEnum; +use Cachet\Enums\ResourceVisibilityEnum; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -14,7 +15,8 @@ class ComponentGroup extends Model protected $casts = [ 'order' => 'int', - 'visible' => ComponentGroupVisibilityEnum::class, + 'collapsed' => ComponentGroupVisibilityEnum::class, + 'visible' => ResourceVisibilityEnum::class, ]; protected $fillable = [ diff --git a/src/Models/Incident.php b/src/Models/Incident.php index 8f70945b..4f7d5c69 100644 --- a/src/Models/Incident.php +++ b/src/Models/Incident.php @@ -3,15 +3,16 @@ namespace Cachet\Models; use Cachet\Enums\IncidentStatusEnum; +use Cachet\Enums\ResourceVisibilityEnum; use Cachet\Events\Incidents\IncidentCreated; use Cachet\Events\Incidents\IncidentDeleted; use Cachet\Events\Incidents\IncidentUpdated; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; class Incident extends Model @@ -20,7 +21,7 @@ class Incident extends Model protected $casts = [ 'status' => IncidentStatusEnum::class, - 'visible' => 'bool', + 'visible' => ResourceVisibilityEnum::class, 'stickied' => 'bool', 'scheduled_at' => 'datetime', 'occurred_at' => 'datetime', @@ -66,9 +67,9 @@ public function incidentUpdates(): HasMany /** * Get the user that created the incident. */ - public function user(): HasOne + public function user(): BelongsTo { - return $this->hasOne(User::class); + return $this->belongsTo(\Workbench\App\User::class); } /** diff --git a/testbench.yaml b/testbench.yaml index fe8711cf..c96289de 100644 --- a/testbench.yaml +++ b/testbench.yaml @@ -21,6 +21,7 @@ workbench: to: public/vendor/cachethq/cachet build: - asset-publish + - filament:assets - create-sqlite-db - db:wipe - migrate:refresh diff --git a/vite.config.js b/vite.config.js index 4f3e6600..9842013f 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,11 +2,15 @@ import { defineConfig } from 'vite' import laravel from 'laravel-vite-plugin' export default defineConfig({ - plugins: [ - laravel({ - input: ['resources/css/cachet.css', 'resources/js/cachet.js'], - // publicDirectory: 'vendor/orchestra/testbench-core/laravel/public/vendor/cachethq', - // buildDirectory: 'cachet', - }), - ], + plugins: [ + laravel({ + input: [ + 'resources/css/cachet.css', + 'resources/css/dashboard/theme.css', + 'resources/js/cachet.js', + ], + // publicDirectory: 'vendor/orchestra/testbench-core/laravel/public/vendor/cachethq', + // buildDirectory: 'cachet', + }), + ], })