From 2ea8d389faa8c722e14e7634b48cac33f5de38e4 Mon Sep 17 00:00:00 2001 From: Mark Rapson Date: Mon, 20 Jul 2026 23:58:27 +0100 Subject: [PATCH] This PR breaks the large web and player bootstrap files into smaller modules with clearer ownership. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Web changes: Split shared helpers, bootstrap logic, route groups, and upload-sync behavior out of web.js. Kept web.js focused on wiring and server startup. Fixed screen playlist reassignment so changing a screen’s playlist now triggers a refresh. Fixed single-slide playlist refresh behavior so updates do not get stuck behind the current slide. Player changes: Split websocket/runtime handling into runtime.js. Split playlist assembly and revision hashing into playlist.js. Split onboarding and player HTTP routes into dedicated modules. Split render utilities and template loading into render-helpers.js. Kept player.js mostly as startup/orchestration. Validation: Rebuilt both services with Docker Compose. Smoke-checked web and player routes after the refactor. Verified get_errors was clean on the touched modules. --- .gitignore | 1 + docker-compose.yml | 1 + package-lock.json | 1927 ++++++++++++ package.json | 4 +- src/common.js | 4 +- src/data/admin.js | 2 +- src/data/templates.js | 38 +- src/db.js | 16 + src/player.js | 605 +--- src/player/onboarding.js | 170 ++ src/player/player-client-name.script.html | 98 + src/player/player-onboarding-form.script.html | 88 + .../player-onboarding-landing.script.html | 141 + src/player/player-page.script.html | 20 +- src/player/player-page.template.html | 4 +- src/player/playlist.js | 162 + src/player/public/css/player.css | 173 ++ src/player/render-helpers.js | 345 +++ src/player/render.js | 391 +-- src/player/routes.js | 159 + src/player/runtime.js | 416 +++ src/web.js | 2359 +------------- src/web/bootstrap.js | 208 ++ src/web/dashboard-state.js | 112 + src/web/helpers.js | 192 ++ src/web/player-actions.js | 72 + .../css/bootstrap-icons.min.css | 5 + .../css/fonts/bootstrap-icons.woff | Bin 0 -> 176032 bytes .../css/fonts/bootstrap-icons.woff2 | Bin 0 -> 130396 bytes .../fonts/bootstrap-icons.woff | Bin 0 -> 176032 bytes .../fonts/bootstrap-icons.woff2 | Bin 0 -> 130396 bytes src/web/public/adminlte/css/adminlte.min.css | 7 + src/web/public/adminlte/js/adminlte.min.js | 7 + .../adminlte/js/bootstrap.bundle.min.js | 7 + src/web/public/css/admin.css | 2704 ----------------- src/web/public/css/theme-custom.css | 1251 ++++++++ src/web/public/js/admin-page.js | 424 +-- src/web/public/js/dashboard/dashboard-page.js | 462 +++ .../js/{ => playlists}/playlist-schedule.js | 256 +- src/web/public/js/slide-form.js | 406 ++- .../js/slides/slide-form-template-lock.js | 86 + src/web/public/js/slides/slide-form.js | 1107 +++++++ src/web/public/js/system-status.js | 6 +- src/web/public/js/table-sort.js | 46 +- src/web/public/js/template-designer.js | 269 +- .../js/templates/template-designer-utils.js | 117 + .../public/js/templates/template-designer.js | 606 ++++ src/web/public/js/theme-init.js | 14 +- src/web/public/js/theme-sidebar.js | 4 +- src/web/public/js/toast.js | 110 +- .../ckeditor5/LICENSE-ckeditor5.md | 0 .../ckeditor5/ckeditor5-content.css | 0 .../ckeditor5/ckeditor5-editor.css | 0 .../js/{ => vendor}/ckeditor5/ckeditor5.css | 0 .../{ => vendor}/ckeditor5/ckeditor5.css.map | 0 .../js/{ => vendor}/ckeditor5/ckeditor5.js | 0 .../{ => vendor}/ckeditor5/ckeditor5.js.map | 0 .../{ => vendor}/ckeditor5/ckeditor5.umd.js | 0 .../ckeditor5/ckeditor5.umd.js.map | 0 .../ckeditor5/translations/af.d.ts | 0 .../{ => vendor}/ckeditor5/translations/af.js | 0 .../ckeditor5/translations/af.umd.js | 0 .../ckeditor5/translations/ar.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ar.js | 0 .../ckeditor5/translations/ar.umd.js | 0 .../ckeditor5/translations/ast.d.ts | 0 .../ckeditor5/translations/ast.js | 0 .../ckeditor5/translations/ast.umd.js | 0 .../ckeditor5/translations/az.d.ts | 0 .../{ => vendor}/ckeditor5/translations/az.js | 0 .../ckeditor5/translations/az.umd.js | 0 .../ckeditor5/translations/be.d.ts | 0 .../{ => vendor}/ckeditor5/translations/be.js | 0 .../ckeditor5/translations/be.umd.js | 0 .../ckeditor5/translations/bg.d.ts | 0 .../{ => vendor}/ckeditor5/translations/bg.js | 0 .../ckeditor5/translations/bg.umd.js | 0 .../ckeditor5/translations/bn.d.ts | 0 .../{ => vendor}/ckeditor5/translations/bn.js | 0 .../ckeditor5/translations/bn.umd.js | 0 .../ckeditor5/translations/bs.d.ts | 0 .../{ => vendor}/ckeditor5/translations/bs.js | 0 .../ckeditor5/translations/bs.umd.js | 0 .../ckeditor5/translations/ca.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ca.js | 0 .../ckeditor5/translations/ca.umd.js | 0 .../ckeditor5/translations/cs.d.ts | 0 .../{ => vendor}/ckeditor5/translations/cs.js | 0 .../ckeditor5/translations/cs.umd.js | 0 .../ckeditor5/translations/da.d.ts | 0 .../{ => vendor}/ckeditor5/translations/da.js | 0 .../ckeditor5/translations/da.umd.js | 0 .../ckeditor5/translations/de-ch.d.ts | 0 .../ckeditor5/translations/de-ch.js | 0 .../ckeditor5/translations/de-ch.umd.js | 0 .../ckeditor5/translations/de.d.ts | 0 .../{ => vendor}/ckeditor5/translations/de.js | 0 .../ckeditor5/translations/de.umd.js | 0 .../ckeditor5/translations/el.d.ts | 0 .../{ => vendor}/ckeditor5/translations/el.js | 0 .../ckeditor5/translations/el.umd.js | 0 .../ckeditor5/translations/en-au.d.ts | 0 .../ckeditor5/translations/en-au.js | 0 .../ckeditor5/translations/en-au.umd.js | 0 .../ckeditor5/translations/en-gb.d.ts | 0 .../ckeditor5/translations/en-gb.js | 0 .../ckeditor5/translations/en-gb.umd.js | 0 .../ckeditor5/translations/en.d.ts | 0 .../{ => vendor}/ckeditor5/translations/en.js | 0 .../ckeditor5/translations/en.umd.js | 0 .../ckeditor5/translations/eo.d.ts | 0 .../{ => vendor}/ckeditor5/translations/eo.js | 0 .../ckeditor5/translations/eo.umd.js | 0 .../ckeditor5/translations/es-co.d.ts | 0 .../ckeditor5/translations/es-co.js | 0 .../ckeditor5/translations/es-co.umd.js | 0 .../ckeditor5/translations/es.d.ts | 0 .../{ => vendor}/ckeditor5/translations/es.js | 0 .../ckeditor5/translations/es.umd.js | 0 .../ckeditor5/translations/et.d.ts | 0 .../{ => vendor}/ckeditor5/translations/et.js | 0 .../ckeditor5/translations/et.umd.js | 0 .../ckeditor5/translations/eu.d.ts | 0 .../{ => vendor}/ckeditor5/translations/eu.js | 0 .../ckeditor5/translations/eu.umd.js | 0 .../ckeditor5/translations/fa.d.ts | 0 .../{ => vendor}/ckeditor5/translations/fa.js | 0 .../ckeditor5/translations/fa.umd.js | 0 .../ckeditor5/translations/fi.d.ts | 0 .../{ => vendor}/ckeditor5/translations/fi.js | 0 .../ckeditor5/translations/fi.umd.js | 0 .../ckeditor5/translations/fr.d.ts | 0 .../{ => vendor}/ckeditor5/translations/fr.js | 0 .../ckeditor5/translations/fr.umd.js | 0 .../ckeditor5/translations/gl.d.ts | 0 .../{ => vendor}/ckeditor5/translations/gl.js | 0 .../ckeditor5/translations/gl.umd.js | 0 .../ckeditor5/translations/gu.d.ts | 0 .../{ => vendor}/ckeditor5/translations/gu.js | 0 .../ckeditor5/translations/gu.umd.js | 0 .../ckeditor5/translations/he.d.ts | 0 .../{ => vendor}/ckeditor5/translations/he.js | 0 .../ckeditor5/translations/he.umd.js | 0 .../ckeditor5/translations/hi.d.ts | 0 .../{ => vendor}/ckeditor5/translations/hi.js | 0 .../ckeditor5/translations/hi.umd.js | 0 .../ckeditor5/translations/hr.d.ts | 0 .../{ => vendor}/ckeditor5/translations/hr.js | 0 .../ckeditor5/translations/hr.umd.js | 0 .../ckeditor5/translations/hu.d.ts | 0 .../{ => vendor}/ckeditor5/translations/hu.js | 0 .../ckeditor5/translations/hu.umd.js | 0 .../ckeditor5/translations/hy.d.ts | 0 .../{ => vendor}/ckeditor5/translations/hy.js | 0 .../ckeditor5/translations/hy.umd.js | 0 .../ckeditor5/translations/id.d.ts | 0 .../{ => vendor}/ckeditor5/translations/id.js | 0 .../ckeditor5/translations/id.umd.js | 0 .../ckeditor5/translations/it.d.ts | 0 .../{ => vendor}/ckeditor5/translations/it.js | 0 .../ckeditor5/translations/it.umd.js | 0 .../ckeditor5/translations/ja.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ja.js | 0 .../ckeditor5/translations/ja.umd.js | 0 .../ckeditor5/translations/jv.d.ts | 0 .../{ => vendor}/ckeditor5/translations/jv.js | 0 .../ckeditor5/translations/jv.umd.js | 0 .../ckeditor5/translations/kk.d.ts | 0 .../{ => vendor}/ckeditor5/translations/kk.js | 0 .../ckeditor5/translations/kk.umd.js | 0 .../ckeditor5/translations/km.d.ts | 0 .../{ => vendor}/ckeditor5/translations/km.js | 0 .../ckeditor5/translations/km.umd.js | 0 .../ckeditor5/translations/kn.d.ts | 0 .../{ => vendor}/ckeditor5/translations/kn.js | 0 .../ckeditor5/translations/kn.umd.js | 0 .../ckeditor5/translations/ko.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ko.js | 0 .../ckeditor5/translations/ko.umd.js | 0 .../ckeditor5/translations/ku.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ku.js | 0 .../ckeditor5/translations/ku.umd.js | 0 .../ckeditor5/translations/lt.d.ts | 0 .../{ => vendor}/ckeditor5/translations/lt.js | 0 .../ckeditor5/translations/lt.umd.js | 0 .../ckeditor5/translations/lv.d.ts | 0 .../{ => vendor}/ckeditor5/translations/lv.js | 0 .../ckeditor5/translations/lv.umd.js | 0 .../ckeditor5/translations/ms.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ms.js | 0 .../ckeditor5/translations/ms.umd.js | 0 .../ckeditor5/translations/nb.d.ts | 0 .../{ => vendor}/ckeditor5/translations/nb.js | 0 .../ckeditor5/translations/nb.umd.js | 0 .../ckeditor5/translations/ne.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ne.js | 0 .../ckeditor5/translations/ne.umd.js | 0 .../ckeditor5/translations/nl.d.ts | 0 .../{ => vendor}/ckeditor5/translations/nl.js | 0 .../ckeditor5/translations/nl.umd.js | 0 .../ckeditor5/translations/no.d.ts | 0 .../{ => vendor}/ckeditor5/translations/no.js | 0 .../ckeditor5/translations/no.umd.js | 0 .../ckeditor5/translations/oc.d.ts | 0 .../{ => vendor}/ckeditor5/translations/oc.js | 0 .../ckeditor5/translations/oc.umd.js | 0 .../ckeditor5/translations/pl.d.ts | 0 .../{ => vendor}/ckeditor5/translations/pl.js | 0 .../ckeditor5/translations/pl.umd.js | 0 .../ckeditor5/translations/pt-br.d.ts | 0 .../ckeditor5/translations/pt-br.js | 0 .../ckeditor5/translations/pt-br.umd.js | 0 .../ckeditor5/translations/pt.d.ts | 0 .../{ => vendor}/ckeditor5/translations/pt.js | 0 .../ckeditor5/translations/pt.umd.js | 0 .../ckeditor5/translations/ro.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ro.js | 0 .../ckeditor5/translations/ro.umd.js | 0 .../ckeditor5/translations/ru.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ru.js | 0 .../ckeditor5/translations/ru.umd.js | 0 .../ckeditor5/translations/si.d.ts | 0 .../{ => vendor}/ckeditor5/translations/si.js | 0 .../ckeditor5/translations/si.umd.js | 0 .../ckeditor5/translations/sk.d.ts | 0 .../{ => vendor}/ckeditor5/translations/sk.js | 0 .../ckeditor5/translations/sk.umd.js | 0 .../ckeditor5/translations/sl.d.ts | 0 .../{ => vendor}/ckeditor5/translations/sl.js | 0 .../ckeditor5/translations/sl.umd.js | 0 .../ckeditor5/translations/sq.d.ts | 0 .../{ => vendor}/ckeditor5/translations/sq.js | 0 .../ckeditor5/translations/sq.umd.js | 0 .../ckeditor5/translations/sr-latn.d.ts | 0 .../ckeditor5/translations/sr-latn.js | 0 .../ckeditor5/translations/sr-latn.umd.js | 0 .../ckeditor5/translations/sr.d.ts | 0 .../{ => vendor}/ckeditor5/translations/sr.js | 0 .../ckeditor5/translations/sr.umd.js | 0 .../ckeditor5/translations/sv.d.ts | 0 .../{ => vendor}/ckeditor5/translations/sv.js | 0 .../ckeditor5/translations/sv.umd.js | 0 .../ckeditor5/translations/th.d.ts | 0 .../{ => vendor}/ckeditor5/translations/th.js | 0 .../ckeditor5/translations/th.umd.js | 0 .../ckeditor5/translations/ti.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ti.js | 0 .../ckeditor5/translations/ti.umd.js | 0 .../ckeditor5/translations/tk.d.ts | 0 .../{ => vendor}/ckeditor5/translations/tk.js | 0 .../ckeditor5/translations/tk.umd.js | 0 .../ckeditor5/translations/tr.d.ts | 0 .../{ => vendor}/ckeditor5/translations/tr.js | 0 .../ckeditor5/translations/tr.umd.js | 0 .../ckeditor5/translations/tt.d.ts | 0 .../{ => vendor}/ckeditor5/translations/tt.js | 0 .../ckeditor5/translations/tt.umd.js | 0 .../ckeditor5/translations/ug.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ug.js | 0 .../ckeditor5/translations/ug.umd.js | 0 .../ckeditor5/translations/uk.d.ts | 0 .../{ => vendor}/ckeditor5/translations/uk.js | 0 .../ckeditor5/translations/uk.umd.js | 0 .../ckeditor5/translations/ur.d.ts | 0 .../{ => vendor}/ckeditor5/translations/ur.js | 0 .../ckeditor5/translations/ur.umd.js | 0 .../ckeditor5/translations/uz.d.ts | 0 .../{ => vendor}/ckeditor5/translations/uz.js | 0 .../ckeditor5/translations/uz.umd.js | 0 .../ckeditor5/translations/vi.d.ts | 0 .../{ => vendor}/ckeditor5/translations/vi.js | 0 .../ckeditor5/translations/vi.umd.js | 0 .../ckeditor5/translations/zh-cn.d.ts | 0 .../ckeditor5/translations/zh-cn.js | 0 .../ckeditor5/translations/zh-cn.umd.js | 0 .../ckeditor5/translations/zh.d.ts | 0 .../{ => vendor}/ckeditor5/translations/zh.js | 0 .../ckeditor5/translations/zh.umd.js | 0 .../public/js/{ => vendor}/sortable.min.js | 0 src/web/routes/account/password.js | 16 +- src/web/routes/admin-account.js | 69 + src/web/routes/admin-content.js | 392 +++ src/web/routes/admin-manage.js | 542 ++++ src/web/routes/admin-pages.js | 87 + src/web/routes/admin-screen-commands.js | 47 + src/web/routes/admin-users.js | 185 ++ src/web/routes/auth.js | 58 + src/web/routes/clients/list.js | 1 + src/web/routes/common.js | 39 +- src/web/routes/dashboard/index.js | 3 +- src/web/routes/playlists/edit.js | 2 +- src/web/routes/playlists/slide-config.js | 31 +- src/web/routes/slides/form.js | 2 + src/web/routes/templates/add.js | 9 +- src/web/session.js | 102 + src/web/upload-sync.js | 561 ++++ src/web/view.js | 36 + src/web/views/account/password.hbs | 78 +- src/web/views/canvas-sizes/add.hbs | 40 +- src/web/views/canvas-sizes/edit.hbs | 45 +- src/web/views/canvas-sizes/list.hbs | 17 +- src/web/views/clients/list.hbs | 71 +- src/web/views/dashboard/index.hbs | 147 +- src/web/views/frame-layout.hbs | 94 +- src/web/views/layout.hbs | 253 +- src/web/views/login.hbs | 42 +- src/web/views/playlists/add.hbs | 24 +- src/web/views/playlists/edit.hbs | 237 +- src/web/views/playlists/list.hbs | 18 +- src/web/views/playlists/slide-config.hbs | 110 +- src/web/views/screens/add.hbs | 50 +- src/web/views/screens/edit.hbs | 79 +- src/web/views/screens/list.hbs | 18 +- src/web/views/slides/form.hbs | 89 +- src/web/views/slides/list.hbs | 18 +- src/web/views/templates/add.hbs | 172 +- src/web/views/templates/edit.hbs | 187 +- src/web/views/templates/list.hbs | 18 +- src/web/views/users/add.hbs | 59 +- src/web/views/users/edit.hbs | 96 +- src/web/views/users/list.hbs | 21 +- 321 files changed, 12687 insertions(+), 7080 deletions(-) create mode 100644 package-lock.json create mode 100644 src/player/onboarding.js create mode 100644 src/player/player-client-name.script.html create mode 100644 src/player/player-onboarding-form.script.html create mode 100644 src/player/player-onboarding-landing.script.html create mode 100644 src/player/playlist.js create mode 100644 src/player/render-helpers.js create mode 100644 src/player/routes.js create mode 100644 src/player/runtime.js create mode 100644 src/web/bootstrap.js create mode 100644 src/web/dashboard-state.js create mode 100644 src/web/helpers.js create mode 100644 src/web/player-actions.js create mode 100644 src/web/public/adminlte/bootstrap-icons/css/bootstrap-icons.min.css create mode 100644 src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff create mode 100644 src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff2 create mode 100644 src/web/public/adminlte/bootstrap-icons/fonts/bootstrap-icons.woff create mode 100644 src/web/public/adminlte/bootstrap-icons/fonts/bootstrap-icons.woff2 create mode 100644 src/web/public/adminlte/css/adminlte.min.css create mode 100644 src/web/public/adminlte/js/adminlte.min.js create mode 100644 src/web/public/adminlte/js/bootstrap.bundle.min.js delete mode 100644 src/web/public/css/admin.css create mode 100644 src/web/public/css/theme-custom.css create mode 100644 src/web/public/js/dashboard/dashboard-page.js rename src/web/public/js/{ => playlists}/playlist-schedule.js (69%) create mode 100644 src/web/public/js/slides/slide-form-template-lock.js create mode 100644 src/web/public/js/slides/slide-form.js create mode 100644 src/web/public/js/templates/template-designer-utils.js create mode 100644 src/web/public/js/templates/template-designer.js rename src/web/public/js/{ => vendor}/ckeditor5/LICENSE-ckeditor5.md (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5-content.css (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5-editor.css (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.css (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.css.map (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.js.map (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/ckeditor5.umd.js.map (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/af.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/af.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/af.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ar.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ar.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ar.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ast.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ast.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ast.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/az.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/az.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/az.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/be.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/be.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/be.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bg.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bg.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bg.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bn.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bn.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bn.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bs.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bs.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/bs.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ca.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ca.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ca.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/cs.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/cs.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/cs.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/da.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/da.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/da.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de-ch.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de-ch.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de-ch.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/de.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/el.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/el.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/el.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-au.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-au.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-au.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-gb.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-gb.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en-gb.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/en.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eo.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eo.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eo.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es-co.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es-co.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es-co.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/es.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/et.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/et.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/et.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eu.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eu.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/eu.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fa.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fa.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fa.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fi.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fi.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fi.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fr.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fr.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/fr.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gl.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gl.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gl.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gu.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gu.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/gu.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/he.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/he.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/he.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hi.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hi.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hi.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hr.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hr.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hr.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hu.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hu.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hu.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hy.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hy.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/hy.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/id.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/id.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/id.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/it.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/it.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/it.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ja.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ja.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ja.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/jv.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/jv.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/jv.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kk.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kk.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kk.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/km.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/km.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/km.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kn.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kn.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/kn.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ko.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ko.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ko.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ku.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ku.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ku.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lt.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lt.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lt.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lv.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lv.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/lv.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ms.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ms.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ms.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nb.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nb.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nb.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ne.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ne.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ne.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nl.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nl.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/nl.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/no.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/no.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/no.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/oc.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/oc.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/oc.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pl.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pl.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pl.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt-br.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt-br.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt-br.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/pt.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ro.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ro.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ro.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ru.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ru.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ru.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/si.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/si.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/si.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sk.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sk.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sk.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sl.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sl.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sl.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sq.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sq.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sq.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr-latn.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr-latn.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr-latn.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sr.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sv.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sv.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/sv.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/th.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/th.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/th.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ti.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ti.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ti.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tk.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tk.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tk.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tr.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tr.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tr.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tt.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tt.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/tt.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ug.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ug.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ug.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uk.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uk.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uk.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ur.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ur.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/ur.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uz.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uz.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/uz.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/vi.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/vi.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/vi.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh-cn.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh-cn.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh-cn.umd.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh.d.ts (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh.js (100%) rename src/web/public/js/{ => vendor}/ckeditor5/translations/zh.umd.js (100%) rename src/web/public/js/{ => vendor}/sortable.min.js (100%) create mode 100644 src/web/routes/admin-account.js create mode 100644 src/web/routes/admin-content.js create mode 100644 src/web/routes/admin-manage.js create mode 100644 src/web/routes/admin-pages.js create mode 100644 src/web/routes/admin-screen-commands.js create mode 100644 src/web/routes/admin-users.js create mode 100644 src/web/routes/auth.js create mode 100644 src/web/session.js create mode 100644 src/web/upload-sync.js diff --git a/.gitignore b/.gitignore index ef1f633..c97245e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules/ uploads/ docker-compose.dev.yml +.vscode/ .env npm-debug.log* yarn-debug.log* diff --git a/docker-compose.yml b/docker-compose.yml index 4c950a5..a06abbc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,6 +39,7 @@ services: environment: NODE_ENV: ${NODE_ENV:-production} PLAYER_PORT: ${PLAYER_PORT:-3001} + PLAYER_PUBLIC_BASE_URL: ${PLAYER_PUBLIC_BASE_URL:-http://localhost:3001} DB_HOST: ${DB_HOST:-mysql} DB_PORT: ${DB_PORT:-3306} DB_NAME: ${DB_NAME:-signage} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c15ab9d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1927 @@ +{ + "name": "pulse-signage", + "version": "1.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pulse-signage", + "version": "1.2.0", + "dependencies": { + "bootstrap-icons": "1.11.3", + "dotenv": "^17.4.2", + "express": "^4.21.2", + "handlebars": "^4.7.8", + "multer": "^1.4.5-lts.1", + "mysql2": "^3.14.3", + "qrcode": "^1.5.4", + "ws": "^8.21.0" + }, + "devDependencies": { + "nodemon": "^3.1.10" + } + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz", + "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", + "deprecated": "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mysql2": { + "version": "3.22.6", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.22.6.tgz", + "integrity": "sha512-fPKmeDGUzvFP7bMD5SASlJ5zIgvCC4hbanTmhbUlEmhyrY1hR4Hi3xLOWgTd3luYjLVifx6uGvMNJ2m/LlqEpg==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.2", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.2", + "long": "^5.3.2", + "lru.min": "^1.1.4", + "named-placeholders": "^1.1.6", + "sql-escaper": "^1.4.0" + }, + "engines": { + "node": ">= 8.0" + }, + "peerDependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "license": "MIT", + "dependencies": { + "lru.min": "^1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sql-escaper": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.5.0.tgz", + "integrity": "sha512-JCY91/D1lVq7p6RzuHg9XFQH9vT9L22bljsk+uTdMWke4ZqPCCE+iIMNPmJPUUTywn6eW2nncaWc+MizKZgF4A==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=2.0.0", + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/mysqljs/sql-escaper?sponsor=1" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT", + "peer": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json index b8227e1..91e6f8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pulse-signage", - "version": "1.1.5", + "version": "1.4.0", "private": false, "description": "Pulse Signage application with MySQL and media uploads", "repository": { @@ -16,11 +16,13 @@ "dev:player": "nodemon -r dotenv/config src/player.js" }, "dependencies": { + "bootstrap-icons": "1.11.3", "dotenv": "^17.4.2", "express": "^4.21.2", "handlebars": "^4.7.8", "multer": "^1.4.5-lts.1", "mysql2": "^3.14.3", + "qrcode": "^1.5.4", "ws": "^8.21.0" }, "devDependencies": { diff --git a/src/common.js b/src/common.js index 01ab94f..bae30af 100644 --- a/src/common.js +++ b/src/common.js @@ -22,5 +22,7 @@ module.exports = { extractTemplateRegions: data.extractTemplateRegions, buildTemplatePayload: data.buildTemplatePayload, mediaKind: player.mediaKind, - renderPlayerPage: player.renderPlayerPage + renderPlayerPage: player.renderPlayerPage, + renderPlayerOnboardingLandingPage: player.renderPlayerOnboardingLandingPage, + renderPlayerOnboardingFormPage: player.renderPlayerOnboardingFormPage }; diff --git a/src/data/admin.js b/src/data/admin.js index ca3a4e0..723f32e 100644 --- a/src/data/admin.js +++ b/src/data/admin.js @@ -2,7 +2,7 @@ async function fetchAdminData(pool) { const [playlists] = await pool.query('SELECT id, name, fade_between_slides, created_at, modified_at, created_by, modified_by FROM playlists ORDER BY id DESC'); const [canvasSizes] = await pool.query('SELECT id, name, width, height, created_at, modified_at, created_by, modified_by FROM canvas_sizes ORDER BY width ASC, height ASC, name ASC'); const [templates] = await pool.query(` - SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.created_at, st.modified_at, + SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height FROM slide_templates st LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id diff --git a/src/data/templates.js b/src/data/templates.js index 26f1a0a..63e5792 100644 --- a/src/data/templates.js +++ b/src/data/templates.js @@ -2,14 +2,44 @@ const { parseJsonSafe, readFormArray } = require('./utils'); const ALLOWED_TEMPLATE_REGION_TYPES = ['text', 'image', 'webpage', 'html']; +function sanitizeBackgroundColor(value) { + const raw = String(value || '').trim(); + if (/^#[0-9a-fA-F]{6}$/.test(raw) || /^#[0-9a-fA-F]{3}$/.test(raw)) { + return raw; + } + return '#111111'; +} + function normalizeTemplateRegionType(value) { const rawType = String(value || 'text').trim(); return ALLOWED_TEMPLATE_REGION_TYPES.includes(rawType) ? rawType : 'text'; } +function normalizeTemplateRegionName(value) { + return String(value || '').trim(); +} + +function ensureUniqueTemplateRegionNames(regions) { + const seen = new Map(); + for (let i = 0; i < regions.length; i += 1) { + const region = regions[i]; + const regionName = normalizeTemplateRegionName(region.region_key || region.label); + if (!regionName) { + continue; + } + const normalized = regionName.toLowerCase(); + if (seen.has(normalized)) { + const error = new Error('Region names must be unique on this template.'); + error.statusCode = 400; + throw error; + } + seen.set(normalized, true); + } +} + async function fetchTemplateById(pool, id) { const [templates] = await pool.query(` - SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.created_at, st.modified_at, + SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height FROM slide_templates st LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id @@ -26,7 +56,7 @@ async function fetchTemplateById(pool, id) { async function fetchTemplatesData(pool) { const [templates] = await pool.query(` - SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.created_at, st.modified_at, + SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height FROM slide_templates st LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id @@ -107,6 +137,7 @@ async function buildTemplatePayload(pool, req, existingTemplate) { const filesByField = getFilesByField(req.files || []); const backgroundImage = filesByField.background_image; const removeBackgroundImage = Boolean(req.body.remove_background_image); + const backgroundColor = sanitizeBackgroundColor(req.body.background_color || (existingTemplate && existingTemplate.background_color)); const backgroundImagePath = backgroundImage ? `/uploads/${backgroundImage.filename}` : removeBackgroundImage @@ -153,12 +184,15 @@ async function buildTemplatePayload(pool, req, existingTemplate) { }]; } + ensureUniqueTemplateRegionNames(regions); + return { name, canvasSizeId: resolvedCanvasSizeId, canvasSizeWidth: canvasWidth, canvasSizeHeight: canvasHeight, backgroundImagePath, + backgroundColor, regions }; } diff --git a/src/db.js b/src/db.js index a43982a..641aa4c 100644 --- a/src/db.js +++ b/src/db.js @@ -67,6 +67,7 @@ async function ensureSchema(pool) { name VARCHAR(255) NOT NULL, canvas_size_id INT NULL, background_image_path VARCHAR(512) NULL, + background_color VARCHAR(32) NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci @@ -74,6 +75,7 @@ async function ensureSchema(pool) { await addColumnIfMissing(pool, 'slide_templates', 'canvas_size_id', 'INT NULL'); await addColumnIfMissing(pool, 'slide_templates', 'background_image_path', 'VARCHAR(512) NULL'); + await addColumnIfMissing(pool, 'slide_templates', 'background_color', 'VARCHAR(32) NULL'); await addColumnIfMissing(pool, 'slide_templates', 'modified_at', 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'); await addColumnIfMissing(pool, 'slide_templates', 'created_by', 'INT NULL'); await addColumnIfMissing(pool, 'slide_templates', 'modified_by', 'INT NULL'); @@ -196,6 +198,20 @@ async function ensureSchema(pool) { await addColumnIfMissing(pool, 'screens', 'created_by', 'INT NULL'); await addColumnIfMissing(pool, 'screens', 'modified_by', 'INT NULL'); + await pool.query(` + CREATE TABLE IF NOT EXISTS player_onboarding_devices ( + device_id VARCHAR(128) PRIMARY KEY, + client_name VARCHAR(255) NULL, + screen_id INT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + CONSTRAINT fk_player_onboarding_devices_screen FOREIGN KEY (screen_id) REFERENCES screens(id) ON DELETE SET NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); + await addColumnIfMissing(pool, 'player_onboarding_devices', 'client_name', 'VARCHAR(255) NULL'); + await addColumnIfMissing(pool, 'player_onboarding_devices', 'screen_id', 'INT NULL'); + await addColumnIfMissing(pool, 'player_onboarding_devices', 'modified_at', 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'); + await pool.query(` CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, diff --git a/src/player.js b/src/player.js index 4683e17..835d481 100644 --- a/src/player.js +++ b/src/player.js @@ -1,151 +1,12 @@ const express = require('express'); const fs = require('fs'); const http = require('http'); -const crypto = require('crypto'); const path = require('path'); -const { WebSocketServer, WebSocket } = require('ws'); const common = require('./common'); - -// Playlist assembly and revision helpers. -async function buildScreenPlaylist(pool, slug) { - const [screenRows] = await pool.query('SELECT id, name, slug, playlist_id, created_at, modified_at, created_by, modified_by FROM screens WHERE slug = ?', [slug]); - if (!screenRows.length) { - return { screen: null, playlist: null, slides: [] }; - } - - const screen = screenRows[0]; - if (!screen.playlist_id) { - return { - screen, - playlist: null, - slides: [], - revision: getPlaylistRevision(screen, null, [], [], []) - }; - } - - const [playlistRows] = await pool.query('SELECT id, name, fade_between_slides, created_at, modified_at, created_by, modified_by FROM playlists WHERE id = ?', [screen.playlist_id]); - const playlist = playlistRows[0] || null; - const [slideRows] = await pool.query(` - SELECT sl.id, sl.title, sl.body, sl.template_id, sl.content_json, sl.media_path, sl.media_type, sl.created_at, sl.modified_at, - ps.position, ps.duration_seconds AS duration_seconds, ps.schedule_mode, ps.schedule_start_datetime, ps.schedule_end_datetime, ps.schedule_start_time, ps.schedule_end_time, ps.schedule_days_json, - st.name AS template_name, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height, cs.width AS canvas_width, cs.height AS canvas_height - FROM playlist_slides ps - JOIN slides sl ON sl.id = ps.slide_id - LEFT JOIN slide_templates st ON st.id = sl.template_id - LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id - WHERE ps.playlist_id = ? - ORDER BY ps.position ASC, ps.id ASC - `, [screen.playlist_id]); - - const templateIds = slideRows - .filter(function (slide) { return slide.template_id; }) - .map(function (slide) { return slide.template_id; }); - const templatesById = {}; - let templateRows = []; - let regionRows = []; - if (templateIds.length) { - [templateRows] = await pool.query(` - SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.created_at, st.modified_at, - cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height, cs.width AS canvas_width, cs.height AS canvas_height - FROM slide_templates st - LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id - WHERE st.id IN (?) - `, [templateIds]); - [regionRows] = await pool.query('SELECT id, template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_at, modified_at, created_by, modified_by FROM slide_template_regions WHERE template_id IN (?) ORDER BY template_id ASC, z_index ASC, id ASC', [templateIds]); - templateRows.forEach(function (template) { - template.regions = regionRows.filter(function (region) { return region.template_id === template.id; }); - templatesById[template.id] = template; - }); - } - - const slides = slideRows.map(function (slide) { - return { - id: slide.id, - title: slide.title, - body: slide.body, - duration_seconds: slide.duration_seconds, - schedule_mode: slide.schedule_mode, - schedule_start_datetime: slide.schedule_start_datetime, - schedule_end_datetime: slide.schedule_end_datetime, - schedule_start_time: slide.schedule_start_time, - schedule_end_time: slide.schedule_end_time, - schedule_days_json: slide.schedule_days_json, - media_url: slide.media_path, - media_type: slide.media_type, - kind: common.mediaKind(slide.media_path), - template_id: slide.template_id, - template: slide.template_id ? templatesById[slide.template_id] || null : null, - content: common.parseJsonSafe(slide.content_json) || {} - }; - }); - - const revision = getPlaylistRevision(screen, playlist, slideRows, templateRows, regionRows); - - return { screen, playlist, slides, revision }; -} - -function updatePlaylistRevisionHash(hash, value) { - hash.update(String(value === null || value === undefined ? '' : value)); - hash.update('\0'); -} - -function getPlaylistRevision(screen, playlist, slideRows, templateRows, regionRows) { - const hash = crypto.createHash('sha1'); - - updatePlaylistRevisionHash(hash, screen && screen.id); - updatePlaylistRevisionHash(hash, screen && screen.playlist_id); - updatePlaylistRevisionHash(hash, screen && screen.modified_at); - - updatePlaylistRevisionHash(hash, playlist && playlist.id); - updatePlaylistRevisionHash(hash, playlist && playlist.modified_at); - updatePlaylistRevisionHash(hash, playlist && playlist.fade_between_slides); - - (Array.isArray(slideRows) ? slideRows : []).forEach(function (slide) { - updatePlaylistRevisionHash(hash, slide.id); - updatePlaylistRevisionHash(hash, slide.title); - updatePlaylistRevisionHash(hash, slide.body); - updatePlaylistRevisionHash(hash, slide.template_id); - updatePlaylistRevisionHash(hash, slide.content_json); - updatePlaylistRevisionHash(hash, slide.media_path); - updatePlaylistRevisionHash(hash, slide.media_type); - updatePlaylistRevisionHash(hash, slide.modified_at); - updatePlaylistRevisionHash(hash, slide.position); - updatePlaylistRevisionHash(hash, slide.duration_seconds); - updatePlaylistRevisionHash(hash, slide.schedule_mode); - updatePlaylistRevisionHash(hash, slide.schedule_start_datetime); - updatePlaylistRevisionHash(hash, slide.schedule_end_datetime); - updatePlaylistRevisionHash(hash, slide.schedule_start_time); - updatePlaylistRevisionHash(hash, slide.schedule_end_time); - updatePlaylistRevisionHash(hash, slide.schedule_days_json); - }); - - (Array.isArray(templateRows) ? templateRows : []).forEach(function (template) { - updatePlaylistRevisionHash(hash, template.id); - updatePlaylistRevisionHash(hash, template.name); - updatePlaylistRevisionHash(hash, template.canvas_size_id); - updatePlaylistRevisionHash(hash, template.canvas_size_width); - updatePlaylistRevisionHash(hash, template.canvas_size_height); - updatePlaylistRevisionHash(hash, template.background_image_path); - updatePlaylistRevisionHash(hash, template.modified_at); - }); - - (Array.isArray(regionRows) ? regionRows : []).forEach(function (region) { - updatePlaylistRevisionHash(hash, region.id); - updatePlaylistRevisionHash(hash, region.template_id); - updatePlaylistRevisionHash(hash, region.region_key); - updatePlaylistRevisionHash(hash, region.region_type); - updatePlaylistRevisionHash(hash, region.label); - updatePlaylistRevisionHash(hash, region.font_family); - updatePlaylistRevisionHash(hash, region.x); - updatePlaylistRevisionHash(hash, region.y); - updatePlaylistRevisionHash(hash, region.width); - updatePlaylistRevisionHash(hash, region.height); - updatePlaylistRevisionHash(hash, region.z_index); - updatePlaylistRevisionHash(hash, region.modified_at); - }); - - return hash.digest('hex'); -} +const { createPlayerRuntime } = require('./player/runtime'); +const { createPlayerPlaylistService } = require('./player/playlist'); +const { normalizeDeviceId, registerPlayerOnboardingRoutes } = require('./player/onboarding'); +const { registerPlayerRoutes } = require('./player/routes'); // Player runtime, upload API, and websocket wiring. @@ -155,327 +16,30 @@ async function start() { const PORT = Number(process.env.PLAYER_PORT || 3001); const ASSET_DIR = path.join(__dirname, 'player', 'public'); const UPLOAD_DIR = path.join(__dirname, '..', 'uploads'); - const connectionsBySlug = new Map(); - const dashboardListenersBySlug = new Map(); + const playerRuntime = createPlayerRuntime({ + pool: pool, + normalizeDeviceId: normalizeDeviceId + }); + const playerPlaylistService = createPlayerPlaylistService({ + pool: pool, + common: common + }); const server = http.createServer(app); - const wss = new WebSocketServer({ noServer: true }); - + playerRuntime.installWebsocket(server); app.use(express.json()); - - // Static assets and mirrored uploads are served from the player container. - app.use('/assets', express.static(ASSET_DIR)); - app.use('/uploads', express.static(UPLOAD_DIR)); - - app.get('/api/uploads/config', function (_req, res) { - res.json({ - uploadDir: UPLOAD_DIR - }); + registerPlayerOnboardingRoutes(app, { + pool: pool, + common: common, + playerRuntime: playerRuntime, + QRCode: require('qrcode') }); - - app.put('/api/uploads/:filename', express.raw({ type: '*/*', limit: '100mb' }), async function (req, res, next) { - try { - const filename = path.basename(String(req.params.filename || '').trim()); - if (!filename) { - return res.status(400).json({ error: 'Filename is required' }); - } - const filePath = path.join(UPLOAD_DIR, filename); - const body = Buffer.isBuffer(req.body) ? req.body : Buffer.from(req.body || ''); - await fs.promises.mkdir(UPLOAD_DIR, { recursive: true }); - await fs.promises.writeFile(filePath, body); - res.json({ ok: true, filename: filename }); - } catch (error) { - next(error); - } - }); - - app.delete('/api/uploads/:filename', async function (req, res, next) { - try { - const filename = path.basename(String(req.params.filename || '').trim()); - if (!filename) { - return res.status(400).json({ error: 'Filename is required' }); - } - const filePath = path.join(UPLOAD_DIR, filename); - try { - await fs.promises.unlink(filePath); - } catch (error) { - if (!error || error.code !== 'ENOENT') { - throw error; - } - } - res.json({ ok: true, filename: filename }); - } catch (error) { - next(error); - } - }); - - function getConnectionBucket(slug) { - const key = String(slug || '').trim(); - if (!key) { - return null; - } - if (!connectionsBySlug.has(key)) { - connectionsBySlug.set(key, new Map()); - } - return connectionsBySlug.get(key); - } - - function removeConnection(slug, connectionId) { - const bucket = connectionsBySlug.get(slug); - if (!bucket) { - return; - } - bucket.delete(connectionId); - if (!bucket.size) { - connectionsBySlug.delete(slug); - } - } - - function getDashboardListenerBucket(slug) { - const key = String(slug || '').trim(); - if (!key) { - return null; - } - if (!dashboardListenersBySlug.has(key)) { - dashboardListenersBySlug.set(key, new Set()); - } - return dashboardListenersBySlug.get(key); - } - - function removeDashboardListener(slug, socket) { - const key = String(slug || '').trim(); - const bucket = dashboardListenersBySlug.get(key); - if (!bucket) { - return; - } - bucket.delete(socket); - if (!bucket.size) { - dashboardListenersBySlug.delete(key); - } - } - - function buildClientLabel(connection) { - const clientId = String(connection.clientId || '').trim(); - const userAgent = String(connection.userAgent || '').trim(); - const clientIp = String(connection.clientIp || '').trim(); - const viewport = connection.viewport && typeof connection.viewport === 'object' - ? connection.viewport - : null; - const labelParts = []; - - if (userAgent) { - labelParts.push(userAgent.length > 72 ? `${userAgent.slice(0, 72)}...` : userAgent); - } - - if (clientId) { - labelParts.push(`id ${clientId.slice(-6)}`); - } - - if (clientIp) { - labelParts.push(clientIp); - } - - if (viewport && Number.isFinite(Number(viewport.width)) && Number.isFinite(Number(viewport.height))) { - labelParts.push(`${Number(viewport.width)}x${Number(viewport.height)}`); - } - - if (!labelParts.length) { - return connection.remoteAddress || 'connected client'; - } - - return labelParts.join(' • '); - } - - function snapshotConnections(slug) { - const bucket = connectionsBySlug.get(String(slug || '').trim()); - if (!bucket) { - return []; - } - - return Array.from(bucket.values()).map(function (connection) { - return { - id: connection.id, - clientId: connection.clientId || null, - label: connection.label, - userAgent: connection.userAgent || null, - viewport: connection.viewport || null, - page: connection.page || null, - currentSlide: connection.currentSlide || null, - paused: Boolean(connection.paused), - blackout: Boolean(connection.blackout), - currentSlideId: connection.currentSlide && connection.currentSlide.id ? connection.currentSlide.id : null, - currentSlideTitle: connection.currentSlide && connection.currentSlide.title ? connection.currentSlide.title : null, - clientIp: connection.clientIp || null, - remoteAddress: connection.remoteAddress || null, - connectedAt: connection.connectedAt ? connection.connectedAt.toISOString() : null, - lastSeenAt: connection.lastSeenAt ? connection.lastSeenAt.toISOString() : null - }; - }); - } - - function broadcastConnectionSnapshot(slug) { - const key = String(slug || '').trim(); - const bucket = dashboardListenersBySlug.get(key); - if (!bucket || !bucket.size) { - return; - } - - const payload = JSON.stringify({ - type: 'snapshot', - slug: key, - connections: snapshotConnections(slug), - sentAt: new Date().toISOString() - }); - - bucket.forEach(function (socket) { - if (socket.readyState === WebSocket.OPEN) { - socket.send(payload); - } - }); - } - - function sendCommandToConnection(slug, connectionId, commandOrPayload) { - const bucket = connectionsBySlug.get(String(slug || '').trim()); - if (!bucket || !bucket.size) { - return 0; - } - - const target = bucket.get(String(connectionId || '').trim()); - if (!target || target.socket.readyState !== WebSocket.OPEN) { - return 0; - } - - const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null - ? Object.assign({}, commandOrPayload) - : { command: commandOrPayload }; - payload.type = 'command'; - payload.targetConnectionId = target.id; - payload.sentAt = new Date().toISOString(); - - target.socket.send(JSON.stringify(payload)); - return 1; - } - - function broadcastCommand(slug, commandOrPayload) { - const bucket = connectionsBySlug.get(String(slug || '').trim()); - if (!bucket || !bucket.size) { - return 0; - } - - let sent = 0; - bucket.forEach(function (connection) { - if (connection.socket.readyState !== WebSocket.OPEN) { - return; - } - const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null - ? Object.assign({}, commandOrPayload) - : { command: commandOrPayload }; - payload.type = 'command'; - payload.sentAt = new Date().toISOString(); - - connection.socket.send(JSON.stringify(payload)); - sent += 1; - }); - return sent; - } - - app.get('/', function (_req, res) { - res.send('Pulse Signage player service'); - }); - - // Screen playback endpoints render the active playlist for a slug. - app.get('/screen/:slug', function (req, res) { - res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); - res.set('Pragma', 'no-cache'); - buildScreenPlaylist(pool, req.params.slug).then(function (data) { - res.send(common.renderPlayerPage(req.params.slug, data)); - }).catch(function (error) { - console.error(error); - res.status(500).send('Internal server error'); - }); - }); - - app.get('/api/screens/:slug/playlist', async function (req, res, next) { - try { - res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); - const data = await buildScreenPlaylist(pool, req.params.slug); - if (!data.screen) { - return res.status(404).json({ error: 'Screen not found' }); - } - const etag = '"' + String(data.revision || '') + '"'; - res.set('ETag', etag); - if (String(req.headers['if-none-match'] || '').split(',').map(function (value) { - return String(value || '').trim(); - }).includes(etag)) { - return res.status(304).end(); - } - res.json(data); - } catch (error) { - next(error); - } - }); - - app.get(['/api/screens/:slug/connections', '/api/screens/:slug/clients'], async function (req, res, next) { - try { - const [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [req.params.slug]); - if (!screenRows.length) { - return res.status(404).json({ error: 'Screen not found' }); - } - const connections = snapshotConnections(req.params.slug); - res.json({ - screen: screenRows[0], - screenSlug: req.params.slug, - count: connections.length, - connections: connections - }); - } catch (error) { - next(error); - } - }); - - app.post('/api/screens/:slug/commands', async function (req, res, next) { - try { - const command = String((req.body && req.body.command) || req.query.command || '').trim().toLowerCase(); - const connectionId = String((req.body && (req.body.connectionId || req.body.clientId)) || req.query.connectionId || req.query.clientId || '').trim(); - const blackoutValue = req.body && Object.prototype.hasOwnProperty.call(req.body, 'blackout') - ? req.body.blackout - : req.query.blackout; - if (!command) { - return res.status(400).json({ error: 'Command is required' }); - } - if (['refresh', 'reload', 'redirect', 'pause', 'blackout', 'previous', 'next', 'left', 'right'].indexOf(command) === -1) { - return res.status(400).json({ error: 'Unsupported command' }); - } - - const isRedirectCommand = command === 'redirect'; - let screenRows = []; - if (!isRedirectCommand) { - [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [req.params.slug]); - if (!screenRows.length) { - return res.status(404).json({ error: 'Screen not found' }); - } - } - - const commandPayload = req.body && typeof req.body === 'object' && !Array.isArray(req.body) - ? Object.assign({}, req.body, { command: command }) - : command; - if (command === 'blackout' && blackoutValue !== undefined && commandPayload && typeof commandPayload === 'object') { - commandPayload.blackout = blackoutValue; - } - - const sent = connectionId - ? sendCommandToConnection(req.params.slug, connectionId, commandPayload) - : broadcastCommand(req.params.slug, commandPayload); - - res.json({ - screen: screenRows[0] || null, - screenSlug: req.params.slug, - command: command, - connectionId: connectionId || null, - sent: sent - }); - } catch (error) { - next(error); - } + registerPlayerRoutes(app, { + pool: pool, + common: common, + uploadDir: UPLOAD_DIR, + assetDir: ASSET_DIR, + playerRuntime: playerRuntime, + playerPlaylistService: playerPlaylistService }); app.use(function (error, _req, res, _next) { @@ -485,124 +49,6 @@ async function start() { await common.ensureSchema(pool); fs.mkdirSync(UPLOAD_DIR, { recursive: true }); - // Websocket upgrades split dashboard snapshots from player client sessions. - server.on('upgrade', function (request, socket, head) { - let pathname = ''; - try { - pathname = new URL(request.url, 'http://localhost').pathname; - } catch (_error) { - socket.destroy(); - return; - } - - const dashboardMatch = pathname.match(/^\/ws\/screens\/([^/]+)\/events$/); - const playerMatch = pathname.match(/^\/ws\/screens\/([^/]+)$/); - if (!dashboardMatch && !playerMatch) { - socket.destroy(); - return; - } - - const slug = decodeURIComponent((dashboardMatch || playerMatch)[1]); - wss.handleUpgrade(request, socket, head, function (ws) { - wss.emit('connection', ws, request, slug, dashboardMatch ? 'dashboard' : 'player'); - }); - }); - - wss.on('connection', function (socket, request, slug, role) { - if (role === 'dashboard') { - const listenerBucket = getDashboardListenerBucket(slug); - if (!listenerBucket) { - socket.close(); - return; - } - - listenerBucket.add(socket); - socket.send(JSON.stringify({ - type: 'snapshot', - slug: String(slug || '').trim(), - connections: snapshotConnections(slug), - sentAt: new Date().toISOString() - })); - - socket.on('close', function () { - removeDashboardListener(slug, socket); - }); - - socket.on('error', function () { - removeDashboardListener(slug, socket); - }); - return; - } - - const remoteAddress = request.socket && request.socket.remoteAddress ? request.socket.remoteAddress : null; - const forwardedFor = String(request.headers['x-forwarded-for'] || '').split(',')[0].trim(); - const connectionId = crypto.randomUUID(); - const connection = { - id: connectionId, - slug: slug, - socket: socket, - clientId: null, - userAgent: null, - viewport: null, - page: null, - paused: false, - blackout: false, - clientIp: forwardedFor || remoteAddress, - remoteAddress: remoteAddress, - label: forwardedFor || remoteAddress || 'connected client', - connectedAt: new Date(), - lastSeenAt: new Date() - }; - const bucket = getConnectionBucket(slug); - - if (!bucket) { - socket.close(); - return; - } - - bucket.set(connectionId, connection); - - socket.on('message', function (rawMessage) { - connection.lastSeenAt = new Date(); - let payload = null; - try { - payload = JSON.parse(String(rawMessage || '')); - } catch (_error) { - return; - } - - if (!payload || (payload.type !== 'hello' && payload.type !== 'state')) { - return; - } - - connection.clientId = payload.clientId ? String(payload.clientId).trim() : connection.clientId; - connection.userAgent = payload.userAgent ? String(payload.userAgent).trim() : connection.userAgent; - connection.viewport = payload.viewport && typeof payload.viewport === 'object' ? payload.viewport : connection.viewport; - connection.page = payload.page ? String(payload.page).trim() : connection.page; - connection.paused = Boolean(payload.paused); - connection.blackout = Boolean(payload.blackout); - connection.clientIp = payload.clientIp ? String(payload.clientIp).trim() : connection.clientIp; - connection.currentSlide = payload.currentSlide && typeof payload.currentSlide === 'object' ? { - id: payload.currentSlide.id || null, - title: payload.currentSlide.title || '', - kind: payload.currentSlide.kind || '', - playlistSignature: payload.currentSlide.playlistSignature || '' - } : connection.currentSlide; - connection.label = buildClientLabel(connection); - connection.lastSeenAt = new Date(); - broadcastConnectionSnapshot(slug); - }); - - socket.on('close', function () { - removeConnection(slug, connectionId); - broadcastConnectionSnapshot(slug); - }); - - socket.on('error', function () { - removeConnection(slug, connectionId); - broadcastConnectionSnapshot(slug); - }); - }); server.listen(PORT, function () { console.log(`Pulse Signage app listening on port ${PORT}`); @@ -617,3 +63,4 @@ if (require.main === module) { process.exit(1); }); } + diff --git a/src/player/onboarding.js b/src/player/onboarding.js new file mode 100644 index 0000000..b8594d7 --- /dev/null +++ b/src/player/onboarding.js @@ -0,0 +1,170 @@ +function normalizeDeviceId(value) { + return String(value || '').trim().replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128); +} + +function getPublicBaseUrl(req) { + const configured = String(process.env.PLAYER_PUBLIC_BASE_URL || process.env.PLAYER_BASE_URL || '').trim().replace(/\/$/, ''); + if (configured) { + return configured; + } + const forwardedProto = String(req.headers['x-forwarded-proto'] || '').trim().split(',')[0]; + const protocol = forwardedProto || (req.socket && req.socket.encrypted ? 'https' : 'http'); + const forwardedHost = String(req.headers['x-forwarded-host'] || '').trim().split(',')[0]; + const host = forwardedHost || String(req.headers.host || '').trim(); + return `${protocol}://${host}`.replace(/\/$/, ''); +} + +async function getOnboardingStatus(pool, deviceId) { + const normalizedDeviceId = normalizeDeviceId(deviceId); + if (!normalizedDeviceId) { + return null; + } + + const [rows] = await pool.query( + `SELECT d.device_id, d.client_name, d.screen_id, s.name AS screen_name, s.slug AS screen_slug, s.playlist_id + FROM player_onboarding_devices d + LEFT JOIN screens s ON s.id = d.screen_id + WHERE d.device_id = ?`, + [normalizedDeviceId] + ); + + return rows[0] || null; +} + +async function bindDeviceToScreen(pool, deviceId, clientName, screenSlug, isNameAvailableOnScreen) { + const normalizedDeviceId = normalizeDeviceId(deviceId); + const normalizedClientName = String(clientName || '').trim(); + const normalizedScreenSlug = String(screenSlug || '').trim(); + if (!normalizedDeviceId) { + throw new Error('Device ID is required.'); + } + if (!normalizedClientName) { + throw new Error('Client name is required.'); + } + + if (!normalizedScreenSlug) { + throw new Error('Screen is required.'); + } + + const [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [normalizedScreenSlug]); + if (!screenRows.length) { + throw new Error('Screen not found.'); + } + const screen = screenRows[0]; + + const available = typeof isNameAvailableOnScreen === 'function' + ? await isNameAvailableOnScreen(pool, normalizedClientName, normalizedDeviceId) + : true; + if (!available) { + const error = new Error('Client name already exists.'); + error.statusCode = 400; + throw error; + } + + await pool.query( + 'INSERT INTO player_onboarding_devices (device_id, client_name, screen_id) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE client_name = VALUES(client_name), screen_id = VALUES(screen_id), modified_at = CURRENT_TIMESTAMP', + [normalizedDeviceId, normalizedClientName, screen.id] + ); + + return getOnboardingStatus(pool, normalizedDeviceId); +} + +function registerPlayerOnboardingRoutes(app, options) { + const pool = options && options.pool ? options.pool : null; + const common = options && options.common ? options.common : null; + const playerRuntime = options && options.playerRuntime ? options.playerRuntime : null; + const QRCode = options && options.QRCode ? options.QRCode : null; + + if (!app || !pool || !common || !playerRuntime || !QRCode) { + throw new Error('registerPlayerOnboardingRoutes requires app, pool, common, playerRuntime, and QRCode.'); + } + + app.get('/', function (_req, res) { + res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.send(common.renderPlayerOnboardingLandingPage()); + }); + + app.get('/onboard', function (req, res) { + res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.send(common.renderPlayerOnboardingFormPage(String(req.query.deviceId || '').trim())); + }); + + app.get('/api/onboarding/status', async function (req, res, next) { + try { + const status = await getOnboardingStatus(pool, req.query.deviceId); + res.json({ + deviceId: normalizeDeviceId(req.query.deviceId), + onboarded: Boolean(status && status.screen_id), + clientName: status ? status.client_name : null, + screenId: status ? status.screen_id : null, + screenSlug: status ? status.screen_slug : null, + screenName: status ? status.screen_name : null, + playerUrl: status && status.screen_slug ? `${getPublicBaseUrl(req)}/screen/${encodeURIComponent(status.screen_slug)}` : null + }); + } catch (error) { + next(error); + } + }); + + app.get('/api/onboarding/screens', async function (_req, res, next) { + try { + const [rows] = await pool.query('SELECT id, name, slug FROM screens ORDER BY name ASC, id ASC'); + res.json({ screens: rows }); + } catch (error) { + next(error); + } + }); + + app.get('/api/onboarding/qr', async function (req, res, next) { + try { + const deviceId = normalizeDeviceId(req.query.deviceId); + if (!deviceId) { + return res.status(400).json({ error: 'Device ID is required' }); + } + const onboardingUrl = `${getPublicBaseUrl(req)}/onboard?deviceId=${encodeURIComponent(deviceId)}`; + const svg = await QRCode.toString(onboardingUrl, { type: 'svg', margin: 1, errorCorrectionLevel: 'M' }); + res.set('Content-Type', 'image/svg+xml; charset=utf-8'); + res.set('Cache-Control', 'no-store'); + res.send(svg); + } catch (error) { + next(error); + } + }); + + app.post('/api/onboarding', async function (req, res, next) { + try { + const deviceId = normalizeDeviceId(req.body && req.body.deviceId); + const clientName = String((req.body && req.body.clientName) || '').trim(); + const screenSlug = String((req.body && req.body.screenSlug) || '').trim(); + if (!deviceId) { + return res.status(400).json({ error: 'Device ID is required' }); + } + if (!clientName) { + return res.status(400).json({ error: 'Client name is required' }); + } + if (!screenSlug) { + return res.status(400).json({ error: 'Screen is required' }); + } + + const status = await bindDeviceToScreen(pool, deviceId, clientName, screenSlug, playerRuntime.isClientNameAvailableOnScreen); + res.json({ + deviceId: deviceId, + clientName: status ? status.client_name : clientName, + screenId: status ? status.screen_id : null, + screenSlug: status ? status.screen_slug : null, + screenName: status ? status.screen_name : null, + playerUrl: status && status.screen_slug ? `${getPublicBaseUrl(req)}/screen/${encodeURIComponent(status.screen_slug)}` : null + }); + } catch (error) { + next(error); + } + }); +} + +module.exports = { + normalizeDeviceId: normalizeDeviceId, + getPublicBaseUrl: getPublicBaseUrl, + getOnboardingStatus: getOnboardingStatus, + bindDeviceToScreen: bindDeviceToScreen, + registerPlayerOnboardingRoutes: registerPlayerOnboardingRoutes +}; \ No newline at end of file diff --git a/src/player/player-client-name.script.html b/src/player/player-client-name.script.html new file mode 100644 index 0000000..b69a147 --- /dev/null +++ b/src/player/player-client-name.script.html @@ -0,0 +1,98 @@ + diff --git a/src/player/player-onboarding-form.script.html b/src/player/player-onboarding-form.script.html new file mode 100644 index 0000000..f231b63 --- /dev/null +++ b/src/player/player-onboarding-form.script.html @@ -0,0 +1,88 @@ + diff --git a/src/player/player-onboarding-landing.script.html b/src/player/player-onboarding-landing.script.html new file mode 100644 index 0000000..14d1601 --- /dev/null +++ b/src/player/player-onboarding-landing.script.html @@ -0,0 +1,141 @@ + diff --git a/src/player/player-page.script.html b/src/player/player-page.script.html index f1de478..97ad65f 100644 --- a/src/player/player-page.script.html +++ b/src/player/player-page.script.html @@ -226,9 +226,12 @@ if (!socket || socket.readyState !== WebSocket.OPEN) { return; } + var clientName = getOnboardingClientName(); socket.send(JSON.stringify({ type: 'hello', clientId: getCommandClientId(), + clientName: clientName || null, + deviceId: getOnboardingDeviceId() || null, userAgent: window.navigator.userAgent || '', page: window.location.href, viewport: getCurrentViewport(), @@ -255,6 +258,8 @@ commandSocket.send(JSON.stringify({ type: 'state', clientId: getCommandClientId(), + clientName: getOnboardingClientName() || null, + deviceId: getOnboardingDeviceId() || null, userAgent: window.navigator.userAgent || '', page: window.location.href, viewport: getCurrentViewport(), @@ -488,6 +493,11 @@ case 'refresh': refresh(); return; + case 'setclientname': + if (payload.clientName) { + applyOnboardingClientName(payload.clientName, commandSocket); + } + return; case 'redirect': if (payload.url) { window.location.replace(String(payload.url)); @@ -542,6 +552,12 @@ commandSocket = socket; socket.onopen = function () { + if (typeof syncOnboardingClientNameFromServer === 'function') { + syncOnboardingClientNameFromServer(socket).then(function () { + sendCommandHello(socket); + }); + return; + } sendCommandHello(socket); }; @@ -1038,6 +1054,7 @@ canvasWidth: canvasSize.width, canvasHeight: canvasSize.height, background: template.background_image_path ? '' : '', + backgroundColor: template.background_color || '#111111', regions: regions }; @@ -1101,7 +1118,8 @@ const regionContent = content[region.regionKey] || {}; return plan.renderRegion(region, regionContent); }).join('') : ''; - return renderSlideShell(slide, '', (layout ? layout.canvasWidth : 0) + 'px', (layout ? layout.canvasHeight : 0) + 'px', '
' + (layout ? layout.background : '') + regions + '
'); + const stageStyle = layout ? 'background-color:' + escapeHtml(layout.backgroundColor || '#111111') + ';' : ''; + return renderSlideShell(slide, '', (layout ? layout.canvasWidth : 0) + 'px', (layout ? layout.canvasHeight : 0) + 'px', '
' + (layout ? layout.background : '') + regions + '
'); } // Media rendering helpers. diff --git a/src/player/player-page.template.html b/src/player/player-page.template.html index 40b7000..4712089 100644 --- a/src/player/player-page.template.html +++ b/src/player/player-page.template.html @@ -7,8 +7,8 @@ - -
Loading screen...
+ + {{{BODY}}} {{SCRIPT_BLOCK}} diff --git a/src/player/playlist.js b/src/player/playlist.js new file mode 100644 index 0000000..c2d7e22 --- /dev/null +++ b/src/player/playlist.js @@ -0,0 +1,162 @@ +const crypto = require('crypto'); + +function createPlayerPlaylistService(options) { + const pool = options && options.pool ? options.pool : null; + const common = options && options.common ? options.common : null; + + if (!pool) { + throw new Error('pool is required'); + } + if (!common) { + throw new Error('common is required'); + } + + async function buildScreenPlaylist(slug) { + const [screenRows] = await pool.query('SELECT id, name, slug, playlist_id, created_at, modified_at, created_by, modified_by FROM screens WHERE slug = ?', [slug]); + if (!screenRows.length) { + return { screen: null, playlist: null, slides: [] }; + } + + const screen = screenRows[0]; + if (!screen.playlist_id) { + return { + screen: screen, + playlist: null, + slides: [], + revision: getPlaylistRevision(screen, null, [], [], []) + }; + } + + const [playlistRows] = await pool.query('SELECT id, name, fade_between_slides, created_at, modified_at, created_by, modified_by FROM playlists WHERE id = ?', [screen.playlist_id]); + const playlist = playlistRows[0] || null; + const [slideRows] = await pool.query(` + SELECT sl.id, sl.title, sl.body, sl.template_id, sl.content_json, sl.media_path, sl.media_type, sl.created_at, sl.modified_at, + ps.position, ps.duration_seconds AS duration_seconds, ps.schedule_mode, ps.schedule_start_datetime, ps.schedule_end_datetime, ps.schedule_start_time, ps.schedule_end_time, ps.schedule_days_json, + st.name AS template_name, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height, cs.width AS canvas_width, cs.height AS canvas_height + FROM playlist_slides ps + JOIN slides sl ON sl.id = ps.slide_id + LEFT JOIN slide_templates st ON st.id = sl.template_id + LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id + WHERE ps.playlist_id = ? + ORDER BY ps.position ASC, ps.id ASC + `, [screen.playlist_id]); + + const templateIds = slideRows + .filter(function (slide) { return slide.template_id; }) + .map(function (slide) { return slide.template_id; }); + const templatesById = {}; + let templateRows = []; + let regionRows = []; + if (templateIds.length) { + [templateRows] = await pool.query(` + SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, + cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height, cs.width AS canvas_width, cs.height AS canvas_height + FROM slide_templates st + LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id + WHERE st.id IN (?) + `, [templateIds]); + [regionRows] = await pool.query('SELECT id, template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_at, modified_at, created_by, modified_by FROM slide_template_regions WHERE template_id IN (?) ORDER BY template_id ASC, z_index ASC, id ASC', [templateIds]); + templateRows.forEach(function (template) { + template.regions = regionRows.filter(function (region) { return region.template_id === template.id; }); + templatesById[template.id] = template; + }); + } + + const slides = slideRows.map(function (slide) { + return { + id: slide.id, + title: slide.title, + body: slide.body, + duration_seconds: slide.duration_seconds, + schedule_mode: slide.schedule_mode, + schedule_start_datetime: slide.schedule_start_datetime, + schedule_end_datetime: slide.schedule_end_datetime, + schedule_start_time: slide.schedule_start_time, + schedule_end_time: slide.schedule_end_time, + schedule_days_json: slide.schedule_days_json, + media_url: slide.media_path, + media_type: slide.media_type, + kind: common.mediaKind(slide.media_path), + template_id: slide.template_id, + template: slide.template_id ? templatesById[slide.template_id] || null : null, + content: common.parseJsonSafe(slide.content_json) || {} + }; + }); + + const revision = getPlaylistRevision(screen, playlist, slideRows, templateRows, regionRows); + + return { screen: screen, playlist: playlist, slides: slides, revision: revision }; + } + + function updatePlaylistRevisionHash(hash, value) { + hash.update(String(value === null || value === undefined ? '' : value)); + hash.update('\0'); + } + + function getPlaylistRevision(screen, playlist, slideRows, templateRows, regionRows) { + const hash = crypto.createHash('sha1'); + + updatePlaylistRevisionHash(hash, screen && screen.id); + updatePlaylistRevisionHash(hash, screen && screen.playlist_id); + updatePlaylistRevisionHash(hash, screen && screen.modified_at); + + updatePlaylistRevisionHash(hash, playlist && playlist.id); + updatePlaylistRevisionHash(hash, playlist && playlist.modified_at); + updatePlaylistRevisionHash(hash, playlist && playlist.fade_between_slides); + + (Array.isArray(slideRows) ? slideRows : []).forEach(function (slide) { + updatePlaylistRevisionHash(hash, slide.id); + updatePlaylistRevisionHash(hash, slide.title); + updatePlaylistRevisionHash(hash, slide.body); + updatePlaylistRevisionHash(hash, slide.template_id); + updatePlaylistRevisionHash(hash, slide.content_json); + updatePlaylistRevisionHash(hash, slide.media_path); + updatePlaylistRevisionHash(hash, slide.media_type); + updatePlaylistRevisionHash(hash, slide.modified_at); + updatePlaylistRevisionHash(hash, slide.position); + updatePlaylistRevisionHash(hash, slide.duration_seconds); + updatePlaylistRevisionHash(hash, slide.schedule_mode); + updatePlaylistRevisionHash(hash, slide.schedule_start_datetime); + updatePlaylistRevisionHash(hash, slide.schedule_end_datetime); + updatePlaylistRevisionHash(hash, slide.schedule_start_time); + updatePlaylistRevisionHash(hash, slide.schedule_end_time); + updatePlaylistRevisionHash(hash, slide.schedule_days_json); + }); + + (Array.isArray(templateRows) ? templateRows : []).forEach(function (template) { + updatePlaylistRevisionHash(hash, template.id); + updatePlaylistRevisionHash(hash, template.name); + updatePlaylistRevisionHash(hash, template.canvas_size_id); + updatePlaylistRevisionHash(hash, template.canvas_size_width); + updatePlaylistRevisionHash(hash, template.canvas_size_height); + updatePlaylistRevisionHash(hash, template.background_image_path); + updatePlaylistRevisionHash(hash, template.background_color); + updatePlaylistRevisionHash(hash, template.modified_at); + }); + + (Array.isArray(regionRows) ? regionRows : []).forEach(function (region) { + updatePlaylistRevisionHash(hash, region.id); + updatePlaylistRevisionHash(hash, region.template_id); + updatePlaylistRevisionHash(hash, region.region_key); + updatePlaylistRevisionHash(hash, region.region_type); + updatePlaylistRevisionHash(hash, region.label); + updatePlaylistRevisionHash(hash, region.font_family); + updatePlaylistRevisionHash(hash, region.x); + updatePlaylistRevisionHash(hash, region.y); + updatePlaylistRevisionHash(hash, region.width); + updatePlaylistRevisionHash(hash, region.height); + updatePlaylistRevisionHash(hash, region.z_index); + updatePlaylistRevisionHash(hash, region.modified_at); + }); + + return hash.digest('hex'); + } + + return { + buildScreenPlaylist: buildScreenPlaylist + }; +} + +module.exports = { + createPlayerPlaylistService: createPlayerPlaylistService +}; diff --git a/src/player/public/css/player.css b/src/player/public/css/player.css index 827d558..62034a0 100644 --- a/src/player/public/css/player.css +++ b/src/player/public/css/player.css @@ -9,6 +9,19 @@ body { font-family: Arial, sans-serif; } +body.onboarding-page { + background: + radial-gradient(circle at top, rgba(82, 144, 255, 0.28), transparent 32%), + radial-gradient(circle at bottom right, rgba(34, 197, 94, 0.18), transparent 26%), + linear-gradient(160deg, #09111f 0%, #0b1323 52%, #111827 100%); + overflow-x: hidden; + overflow-y: auto; +} + +body.onboarding-page #app { + display: none; +} + #app { width: 100%; height: 100%; @@ -19,6 +32,166 @@ body { position: relative; } +.onboarding-shell { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: clamp(16px, 3vw, 40px); + box-sizing: border-box; +} + +.onboarding-card { + width: min(100%, 1040px); + padding: clamp(20px, 3vw, 40px); + border-radius: 30px; + background: rgba(10, 17, 30, 0.82); + border: 1px solid rgba(148, 163, 184, 0.18); + box-shadow: 0 28px 80px rgba(0, 0, 0, 0.45); + backdrop-filter: blur(14px); + box-sizing: border-box; +} + +.onboarding-card h1 { + margin: 0 0 12px; + font-size: clamp(2rem, 4vw, 3.2rem); + line-height: 1.05; +} + +.onboarding-kicker { + margin: 0 0 12px; + text-transform: uppercase; + letter-spacing: 0.14em; + color: #8ab4ff; + font-size: 0.82rem; +} + +.onboarding-copy { + margin: 0 0 28px; + color: #cbd5e1; + font-size: 1.03rem; + line-height: 1.5; +} + +.onboarding-layout { + display: grid; + grid-template-columns: minmax(280px, 1fr) minmax(320px, 1fr); + gap: clamp(20px, 3vw, 32px); + align-items: stretch; +} + +.onboarding-qr-pane { + display: grid; + gap: 16px; + align-content: start; +} + +.onboarding-qr-frame { + display: flex; + justify-content: center; + padding: 22px; + border-radius: 26px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.onboarding-qr-frame img { + width: min(100%, 320px); + aspect-ratio: 1; + display: block; + background: #fff; + border-radius: 18px; +} + +.onboarding-form { + display: grid; + gap: 14px; +} + +.onboarding-form--local { + align-content: start; + padding: 22px; + border-radius: 26px; + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.onboarding-form label { + display: grid; + gap: 9px; + color: #e2e8f0; +} + +.onboarding-form input[type="text"] { + width: 100%; + box-sizing: border-box; + min-height: 48px; + padding: 12px 16px; + border-radius: 12px; + border: 1px solid rgba(148, 163, 184, 0.28); + background: rgba(15, 23, 42, 0.9); + color: #f8fafc; + font-size: 1rem; +} + +.onboarding-form select { + width: 100%; + box-sizing: border-box; + min-height: 48px; + padding: 12px 16px; + border-radius: 12px; + border: 1px solid rgba(148, 163, 184, 0.28); + background: rgba(15, 23, 42, 0.9); + color: #f8fafc; + font-size: 1rem; +} + +.onboarding-form input[type="text"]::placeholder { + color: #94a3b8; +} + +.onboarding-form button { + appearance: none; + border: 0; + border-radius: 12px; + background: linear-gradient(135deg, #60a5fa, #22c55e); + color: #08111f; + font-size: 1rem; + font-weight: 700; + min-height: 48px; + padding: 12px 18px; + cursor: pointer; +} + +.onboarding-status { + margin-top: 8px; + min-height: 1.4em; + color: #cbd5e1; + font-size: 0.96rem; +} + +.onboarding-card--landing .onboarding-status { + text-align: center; +} + +@media (max-width: 860px), (orientation: portrait) { + .onboarding-shell { + align-items: center; + } + + .onboarding-layout { + grid-template-columns: 1fr; + } + + .onboarding-card { + width: 100%; + } + + .onboarding-qr-frame img { + width: min(100%, 280px); + } +} + .slide-shell { position: absolute; inset: 0; diff --git a/src/player/render-helpers.js b/src/player/render-helpers.js new file mode 100644 index 0000000..bcbb98f --- /dev/null +++ b/src/player/render-helpers.js @@ -0,0 +1,345 @@ +const fs = require('fs'); +const path = require('path'); + +function mediaKind(mediaPath) { + const ext = path.extname(mediaPath || '').toLowerCase(); + if (['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg'].includes(ext)) { + return 'image'; + } + if (['.mp4', '.webm', '.ogg'].includes(ext)) { + return 'video'; + } + if (ext === '.pdf') { + return 'pdf'; + } + return 'file'; +} + +function escapeHtml(value) { + return String(value ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function sanitizeFontFamily(value) { + return String(value || '').replace(/[^a-zA-Z0-9 ,"-]/g, '').trim(); +} + +function sanitizeFontSize(value) { + return Math.max(8, Number(value || 0) || 24); +} + +function sanitizeTextColor(value, fallback) { + const raw = String(value || '').trim(); + if (/^#[0-9a-fA-F]{6}$/.test(raw) || /^#[0-9a-fA-F]{3}$/.test(raw)) { + return raw; + } + return fallback || '#000000'; +} + +const ALLOWED_RICH_TEXT_TAGS = ['a', 'b', 'blockquote', 'br', 'code', 'div', 'em', 'figure', 'figcaption', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'li', 'ol', 'p', 'pre', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'u', 'ul']; + +function sanitizeRichTextAttributes(tagName, attrText) { + const allowedAttributes = { + a: ['href', 'title', 'target', 'rel', 'class', 'style'], + blockquote: ['class', 'style'], + div: ['class', 'style'], + figure: ['class', 'style'], + figcaption: ['class', 'style'], + h1: ['class', 'style'], + h2: ['class', 'style'], + h3: ['class', 'style'], + h4: ['class', 'style'], + h5: ['class', 'style'], + h6: ['class', 'style'], + li: ['class', 'style'], + ol: ['class', 'style', 'start'], + p: ['class', 'style'], + pre: ['class', 'style'], + span: ['class', 'style'], + table: ['class', 'style'], + td: ['class', 'style', 'colspan', 'rowspan'], + th: ['class', 'style', 'colspan', 'rowspan', 'scope'], + tr: ['class', 'style'], + ul: ['class', 'style'] + }; + const allowed = allowedAttributes[tagName] || []; + if (!allowed.length) { + return ''; + } + + const attrs = []; + String(attrText || '').replace(/([a-zA-Z0-9:-]+)(?:\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>/=`]+)))?/g, (_full, key, _valuePart, doubleQuoted, singleQuoted, bareValue) => { + const lowerKey = String(key || '').toLowerCase(); + if (!allowed.includes(lowerKey)) { + return ''; + } + const value = doubleQuoted !== undefined ? doubleQuoted : singleQuoted !== undefined ? singleQuoted : bareValue !== undefined ? bareValue : ''; + if (lowerKey === 'href' && /^(?:\s*javascript:|\s*data:)/i.test(String(value || ''))) { + return ''; + } + if (lowerKey === 'style' && /(?:expression\s*\(|javascript:|url\s*\()/i.test(String(value || ''))) { + return ''; + } + if (lowerKey === 'target') { + const targetValue = String(value || '').trim(); + if (targetValue === '_blank') { + attrs.push(' target="_blank"'); + if (!attrs.includes(' rel="noreferrer noopener"')) { + attrs.push(' rel="noreferrer noopener"'); + } + return ''; + } + } + attrs.push(' ' + lowerKey + '="' + escapeHtml(value) + '"'); + return ''; + }); + + return attrs.join(''); +} + +function safeJsonForScript(value) { + return JSON.stringify(value === undefined ? null : value).replace(//gi, ''); + output = output.replace(//gi, ''); + return output.replace(/<[^>]+>/g, (tag) => { + const match = tag.match(/^<\s*(\/?)\s*([a-z0-9]+)([\s\S]*?)(\/?)>$/i); + if (!match) { + return ''; + } + const closing = Boolean(match[1]); + const name = String(match[2] || '').toLowerCase(); + const attrText = String(match[3] || ''); + if (!ALLOWED_RICH_TEXT_TAGS.includes(name)) { + return ''; + } + if (closing) { + return ``; + } + return `<${name}${sanitizeRichTextAttributes(name, attrText)}>`; + }); +} + +function renderEditorJsBlock(block) { + if (!block || !block.type || !block.data) { + return ''; + } + + if (block.type === 'header') { + const level = Math.max(1, Math.min(6, Number(block.data.level || 2))); + return '' + sanitizeRichText(block.data.text || '') + ''; + } else if (block.type === 'list') { + const tag = block.data.style === 'ordered' ? 'ol' : 'ul'; + const items = Array.isArray(block.data.items) ? block.data.items : []; + return '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + items.map((item) => renderEditorJsListItem(item, tag)).join('') + ''; + } else if (block.type === 'delimiter') { + return '
'; + } else if (block.type === 'code') { + return '
' + escapeHtml(block.data.code || '') + '
'; + } else if (block.type === 'table') { + return renderEditorJsTable(block.data); + } else if (block.type === 'paragraph') { + return '

' + sanitizeRichText(block.data.text || '') + '

'; + } + + return ''; +} + +function renderEditorJsListItem(item, tag) { + if (item && typeof item === 'object') { + const content = item.content !== undefined ? item.content : (item.text !== undefined ? item.text : item.value !== undefined ? item.value : ''); + const children = Array.isArray(item.items) ? item.items : Array.isArray(item.subItems) ? item.subItems : Array.isArray(item.children) ? item.children : []; + const nested = children.length ? '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + children.map((child) => renderEditorJsListItem(child, tag)).join('') + '' : ''; + return '
  • ' + sanitizeRichText(content || '') + nested + '
  • '; + } + return '
  • ' + sanitizeRichText(item || '') + '
  • '; +} + +function renderEditorJsTable(data) { + const rows = Array.isArray(data.content) ? data.content : Array.isArray(data.rows) ? data.rows : []; + if (!rows.length) { + return ''; + } + const hasHeadings = Boolean(data.withHeadings); + const tableRows = rows.map(function (row, rowIndex) { + const cells = Array.isArray(row) ? row : []; + const cellTag = hasHeadings && rowIndex === 0 ? 'th' : 'td'; + const cellAttrs = cellTag === 'th' ? ' scope="col"' : ''; + return '' + cells.map(function (cell) { + return '<' + cellTag + cellAttrs + '>' + sanitizeRichText(cell || '') + ''; + }).join('') + ''; + }).join(''); + return '' + tableRows + '
    '; +} + +function renderEditorJsContent(value) { + if (value && typeof value === 'object') { + if (Array.isArray(value.blocks)) { + return value.blocks.map(renderEditorJsBlock).join(''); + } + if (value.value !== undefined) { + return renderEditorJsContent(value.value); + } + } + const raw = String(value || ''); + try { + const parsed = JSON.parse(raw); + if (parsed && Array.isArray(parsed.blocks)) { + return parsed.blocks.map(renderEditorJsBlock).join(''); + } + } catch (_error) { + // fall through to legacy HTML rendering + } + return sanitizeRichText(raw); +} + +function renderHtmlRegionContent(value) { + const html = String(value || '').trim(); + if (!html) { + return '
    HTML
    '; + } + return ''; +} + +function fitCanvasSize(canvasWidth, canvasHeight, maxWidth, maxHeight) { + const width = Math.max(1, Number(canvasWidth || 0) || 1920); + const height = Math.max(1, Number(canvasHeight || 0) || 1080); + const viewportWidth = Math.max(1, Number(maxWidth || 0) || width); + const viewportHeight = Math.max(1, Number(maxHeight || 0) || height); + const scale = Math.min(viewportWidth / width, viewportHeight / height); + return { + width: Math.round(width * scale), + height: Math.round(height * scale) + }; +} + +const playerPageTemplatePath = path.join(__dirname, 'player-page.template.html'); +const playerClientNameScriptPath = path.join(__dirname, 'player-client-name.script.html'); +const playerPageScriptPath = path.join(__dirname, 'player-page.script.html'); +const playerOnboardingLandingScriptPath = path.join(__dirname, 'player-onboarding-landing.script.html'); +const playerOnboardingFormScriptPath = path.join(__dirname, 'player-onboarding-form.script.html'); +let playerPageTemplateCache = null; +let playerClientNameScriptCache = null; +let playerPageScriptCache = null; +let playerOnboardingLandingScriptCache = null; +let playerOnboardingFormScriptCache = null; + +function loadTemplate(filePath, cache) { + const stat = fs.statSync(filePath); + if (cache.value && cache.mtimeMs === stat.mtimeMs) { + return cache.value; + } + const compiled = require('handlebars').compile(fs.readFileSync(filePath, 'utf8')); + cache.value = compiled; + cache.mtimeMs = stat.mtimeMs; + return compiled; +} + +function getPlayerPageTemplate() { + return loadTemplate(playerPageTemplatePath, playerPageTemplateCache || (playerPageTemplateCache = {})); +} + +function getPlayerClientNameScript() { + return loadTemplate(playerClientNameScriptPath, playerClientNameScriptCache || (playerClientNameScriptCache = {})); +} + +function getPlayerPageScript() { + return loadTemplate(playerPageScriptPath, playerPageScriptCache || (playerPageScriptCache = {})); +} + +function getPlayerOnboardingLandingScript() { + return loadTemplate(playerOnboardingLandingScriptPath, playerOnboardingLandingScriptCache || (playerOnboardingLandingScriptCache = {})); +} + +function getPlayerOnboardingFormScript() { + return loadTemplate(playerOnboardingFormScriptPath, playerOnboardingFormScriptCache || (playerOnboardingFormScriptCache = {})); +} + +module.exports = { + mediaKind: mediaKind, + escapeHtml: escapeHtml, + sanitizeFontFamily: sanitizeFontFamily, + sanitizeFontSize: sanitizeFontSize, + sanitizeTextColor: sanitizeTextColor, + sanitizeRichTextAttributes: sanitizeRichTextAttributes, + safeJsonForScript: safeJsonForScript, + parseMaybeJson: parseMaybeJson, + normalizeContentValue: normalizeContentValue, + normalizeSlide: normalizeSlide, + sanitizeRichText: sanitizeRichText, + renderEditorJsBlock: renderEditorJsBlock, + renderEditorJsListItem: renderEditorJsListItem, + renderEditorJsTable: renderEditorJsTable, + renderEditorJsContent: renderEditorJsContent, + renderHtmlRegionContent: renderHtmlRegionContent, + fitCanvasSize: fitCanvasSize, + loadTemplate: loadTemplate, + getPlayerPageTemplate: getPlayerPageTemplate, + getPlayerClientNameScript: getPlayerClientNameScript, + getPlayerPageScript: getPlayerPageScript, + getPlayerOnboardingLandingScript: getPlayerOnboardingLandingScript, + getPlayerOnboardingFormScript: getPlayerOnboardingFormScript +}; \ No newline at end of file diff --git a/src/player/render.js b/src/player/render.js index 29baff3..4256b70 100644 --- a/src/player/render.js +++ b/src/player/render.js @@ -1,320 +1,123 @@ -const fs = require('fs'); -const path = require('path'); const Handlebars = require('handlebars'); +const { mediaKind, safeJsonForScript, getPlayerPageTemplate, getPlayerClientNameScript, getPlayerPageScript, getPlayerOnboardingLandingScript, getPlayerOnboardingFormScript } = require('./render-helpers'); -function mediaKind(mediaPath) { - const ext = path.extname(mediaPath || '').toLowerCase(); - if (['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg'].includes(ext)) { - return 'image'; - } - if (['.mp4', '.webm', '.ogg'].includes(ext)) { - return 'video'; - } - if (ext === '.pdf') { - return 'pdf'; - } - return 'file'; -} - -function escapeHtml(value) { - return String(value ?? '') - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function sanitizeFontFamily(value) { - return String(value || '').replace(/[^a-zA-Z0-9 ,"-]/g, '').trim(); -} - -function sanitizeFontSize(value) { - return Math.max(8, Number(value || 0) || 24); -} - -function sanitizeTextColor(value, fallback) { - const raw = String(value || '').trim(); - if (/^#[0-9a-fA-F]{6}$/.test(raw) || /^#[0-9a-fA-F]{3}$/.test(raw)) { - return raw; - } - return fallback || '#000000'; -} - -const ALLOWED_RICH_TEXT_TAGS = ['a', 'b', 'blockquote', 'br', 'code', 'div', 'em', 'figure', 'figcaption', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'li', 'ol', 'p', 'pre', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'u', 'ul']; - -function sanitizeRichTextAttributes(tagName, attrText) { - const allowedAttributes = { - a: ['href', 'title', 'target', 'rel', 'class', 'style'], - blockquote: ['class', 'style'], - div: ['class', 'style'], - figure: ['class', 'style'], - figcaption: ['class', 'style'], - h1: ['class', 'style'], - h2: ['class', 'style'], - h3: ['class', 'style'], - h4: ['class', 'style'], - h5: ['class', 'style'], - h6: ['class', 'style'], - li: ['class', 'style'], - ol: ['class', 'style', 'start'], - p: ['class', 'style'], - pre: ['class', 'style'], - span: ['class', 'style'], - table: ['class', 'style'], - td: ['class', 'style', 'colspan', 'rowspan'], - th: ['class', 'style', 'colspan', 'rowspan', 'scope'], - tr: ['class', 'style'], - ul: ['class', 'style'] - }; - const allowed = allowedAttributes[tagName] || []; - if (!allowed.length) { - return ''; - } - - const attrs = []; - String(attrText || '').replace(/([a-zA-Z0-9:-]+)(?:\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>/=`]+)))?/g, (_full, key, _valuePart, doubleQuoted, singleQuoted, bareValue) => { - const lowerKey = String(key || '').toLowerCase(); - if (!allowed.includes(lowerKey)) { - return ''; - } - const value = doubleQuoted !== undefined ? doubleQuoted : singleQuoted !== undefined ? singleQuoted : bareValue !== undefined ? bareValue : ''; - if (lowerKey === 'href' && /^(?:\s*javascript:|\s*data:)/i.test(String(value || ''))) { - return ''; - } - if (lowerKey === 'style' && /(?:expression\s*\(|javascript:|url\s*\()/i.test(String(value || ''))) { - return ''; - } - if (lowerKey === 'target') { - const targetValue = String(value || '').trim(); - if (targetValue === '_blank') { - attrs.push(' target="_blank"'); - if (!attrs.includes(' rel="noreferrer noopener"')) { - attrs.push(' rel="noreferrer noopener"'); - } - return ''; - } - } - attrs.push(' ' + lowerKey + '="' + escapeHtml(value) + '"'); - return ''; - }); - - return attrs.join(''); -} - -function safeJsonForScript(value) { - return JSON.stringify(value === undefined ? null : value).replace(//gi, ''); - output = output.replace(//gi, ''); - return output.replace(/<[^>]+>/g, (tag) => { - const match = tag.match(/^<\s*(\/?)\s*([a-z0-9]+)([\s\S]*?)(\/?)>$/i); - if (!match) { - return ''; - } - const closing = Boolean(match[1]); - const name = String(match[2] || '').toLowerCase(); - const attrText = String(match[3] || ''); - if (!ALLOWED_RICH_TEXT_TAGS.includes(name)) { - return ''; - } - if (closing) { - return ``; - } - return `<${name}${sanitizeRichTextAttributes(name, attrText)}>`; +function renderPage(template, options) { + return template({ + TITLE: options.title, + BODY_CLASS: options.bodyClass || '', + BODY: new Handlebars.SafeString(options.body || ''), + SCRIPT_BLOCK: new Handlebars.SafeString(options.script || '') }); } -function renderEditorJsBlock(block) { - if (!block || !block.type || !block.data) { - return ''; - } - - if (block.type === 'header') { - const level = Math.max(1, Math.min(6, Number(block.data.level || 2))); - return '' + sanitizeRichText(block.data.text || '') + ''; - } else if (block.type === 'list') { - const tag = block.data.style === 'ordered' ? 'ol' : 'ul'; - const items = Array.isArray(block.data.items) ? block.data.items : []; - return '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + items.map((item) => renderEditorJsListItem(item, tag)).join('') + ''; - } else if (block.type === 'delimiter') { - return '
    '; - } else if (block.type === 'code') { - return '
    ' + escapeHtml(block.data.code || '') + '
    '; - } else if (block.type === 'table') { - return renderEditorJsTable(block.data); - } else if (block.type === 'paragraph') { - return '

    ' + sanitizeRichText(block.data.text || '') + '

    '; - } - - return ''; +function renderOnboardingLandingBody() { + return [ + '
    ', + '
    ', + '

    Pulse Signage

    ', + '

    Onboard this player

    ', + '

    Choose an existing screen, name the client, and either scan the QR code or finish right here with a keyboard and mouse.

    ', + '
    ', + '
    ', + '
    ', + ' Onboarding QR code', + '
    ', + '
    Preparing onboarding link...
    ', + '
    ', + '
    ', + ' ', + ' ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join(''); } -function renderEditorJsListItem(item, tag) { - if (item && typeof item === 'object') { - const content = item.content !== undefined ? item.content : (item.text !== undefined ? item.text : item.value !== undefined ? item.value : ''); - const children = Array.isArray(item.items) ? item.items : Array.isArray(item.subItems) ? item.subItems : Array.isArray(item.children) ? item.children : []; - const nested = children.length ? '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + children.map((child) => renderEditorJsListItem(child, tag)).join('') + '' : ''; - return '
  • ' + sanitizeRichText(content || '') + nested + '
  • '; - } - return '
  • ' + sanitizeRichText(item || '') + '
  • '; +function renderOnboardingFormBody(deviceId) { + return [ + '
    ', + '
    ', + '

    Pulse Signage

    ', + '

    Name this client

    ', + '

    Pick an existing screen and give this player a friendly name that will persist after refreshes.

    ', + '
    ', + ' ', + ' ', + ' ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ' + ].join(''); } -function renderEditorJsTable(data) { - const rows = Array.isArray(data.content) ? data.content : Array.isArray(data.rows) ? data.rows : []; - if (!rows.length) { - return ''; - } - const hasHeadings = Boolean(data.withHeadings); - const tableRows = rows.map(function (row, rowIndex) { - const cells = Array.isArray(row) ? row : []; - const cellTag = hasHeadings && rowIndex === 0 ? 'th' : 'td'; - const cellAttrs = cellTag === 'th' ? ' scope="col"' : ''; - return '' + cells.map(function (cell) { - return '<' + cellTag + cellAttrs + '>' + sanitizeRichText(cell || '') + ''; - }).join('') + ''; - }).join(''); - return '' + tableRows + '
    '; + +function renderOnboardingLandingScript() { + return getPlayerOnboardingLandingScript()(); } -function renderEditorJsContent(value) { - if (value && typeof value === 'object') { - if (Array.isArray(value.blocks)) { - return value.blocks.map(renderEditorJsBlock).join(''); - } - if (value.value !== undefined) { - return renderEditorJsContent(value.value); - } - } - const raw = String(value || ''); - try { - const parsed = JSON.parse(raw); - if (parsed && Array.isArray(parsed.blocks)) { - return parsed.blocks.map(renderEditorJsBlock).join(''); - } - } catch (_error) { - // fall through to legacy HTML rendering - } - return sanitizeRichText(raw); -} - -function renderHtmlRegionContent(value) { - const html = String(value || '').trim(); - if (!html) { - return '
    HTML
    '; - } - return ''; -} - -function fitCanvasSize(canvasWidth, canvasHeight, maxWidth, maxHeight) { - const width = Math.max(1, Number(canvasWidth || 0) || 1920); - const height = Math.max(1, Number(canvasHeight || 0) || 1080); - const viewportWidth = Math.max(1, Number(maxWidth || 0) || width); - const viewportHeight = Math.max(1, Number(maxHeight || 0) || height); - const scale = Math.min(viewportWidth / width, viewportHeight / height); - return { - width: Math.round(width * scale), - height: Math.round(height * scale) - }; -} - -const playerPageTemplatePath = path.join(__dirname, 'player-page.template.html'); -const playerPageScriptPath = path.join(__dirname, 'player-page.script.html'); -let playerPageTemplateCache = null; -let playerPageScriptCache = null; - -function loadTemplate(filePath, cache) { - const stat = fs.statSync(filePath); - if (cache.value && cache.mtimeMs === stat.mtimeMs) { - return cache.value; - } - const compiled = Handlebars.compile(fs.readFileSync(filePath, 'utf8')); - cache.value = compiled; - cache.mtimeMs = stat.mtimeMs; - return compiled; -} - -function getPlayerPageTemplate() { - return loadTemplate(playerPageTemplatePath, playerPageTemplateCache || (playerPageTemplateCache = {})); -} - -function getPlayerPageScript() { - return loadTemplate(playerPageScriptPath, playerPageScriptCache || (playerPageScriptCache = {})); +function renderOnboardingFormScript(deviceId) { + return getPlayerOnboardingFormScript()({ + DEVICE_ID_JSON: new Handlebars.SafeString(JSON.stringify(deviceId || '')) + }); } function renderPlayerPage(slug, initialData) { + const onboardingScript = getPlayerClientNameScript()(); const template = getPlayerPageTemplate(); const script = getPlayerPageScript()({ SLUG_JSON: new Handlebars.SafeString(JSON.stringify(slug)), INITIAL_DATA_JSON: new Handlebars.SafeString(safeJsonForScript(initialData || null)) }); - return template({ - TITLE: 'Screen ' + slug, - SCRIPT_BLOCK: new Handlebars.SafeString(script) + return renderPage(template, { + title: 'Screen ' + slug, + body: '
    Loading screen...
    ', + script: onboardingScript + script + }); +} + +function renderPlayerOnboardingLandingPage() { + return renderPage(getPlayerPageTemplate(), { + title: 'Onboard player', + bodyClass: 'onboarding-page', + body: renderOnboardingLandingBody(), + script: renderOnboardingLandingScript() + }); +} + +function renderPlayerOnboardingFormPage(deviceId) { + return renderPage(getPlayerPageTemplate(), { + title: 'Onboard screen', + bodyClass: 'onboarding-page', + body: renderOnboardingFormBody(deviceId), + script: renderOnboardingFormScript(deviceId) }); } module.exports = { mediaKind, - renderPlayerPage + renderPlayerPage, + renderPlayerOnboardingLandingPage, + renderPlayerOnboardingFormPage }; diff --git a/src/player/routes.js b/src/player/routes.js new file mode 100644 index 0000000..742bde2 --- /dev/null +++ b/src/player/routes.js @@ -0,0 +1,159 @@ +const fs = require('fs'); +const express = require('express'); + +function registerPlayerRoutes(app, options) { + const pool = options && options.pool ? options.pool : null; + const common = options && options.common ? options.common : null; + const uploadDir = options && options.uploadDir ? options.uploadDir : null; + const assetDir = options && options.assetDir ? options.assetDir : null; + const playerRuntime = options && options.playerRuntime ? options.playerRuntime : null; + const playerPlaylistService = options && options.playerPlaylistService ? options.playerPlaylistService : null; + + if (!app || !pool || !common || !uploadDir || !assetDir || !playerRuntime || !playerPlaylistService) { + throw new Error('registerPlayerRoutes requires app, pool, common, uploadDir, assetDir, playerRuntime, and playerPlaylistService.'); + } + + app.use('/assets', express.static(assetDir)); + app.use('/uploads', express.static(uploadDir)); + + app.get('/api/uploads/config', function (_req, res) { + res.json({ + uploadDir: uploadDir + }); + }); + + app.put('/api/uploads/:filename', express.raw({ type: '*/*', limit: '100mb' }), async function (req, res, next) { + try { + const filename = require('path').basename(String(req.params.filename || '').trim()); + if (!filename) { + return res.status(400).json({ error: 'Filename is required' }); + } + const filePath = require('path').join(uploadDir, filename); + const body = Buffer.isBuffer(req.body) ? req.body : Buffer.from(req.body || ''); + await fs.promises.mkdir(uploadDir, { recursive: true }); + await fs.promises.writeFile(filePath, body); + res.json({ ok: true, filename: filename }); + } catch (error) { + next(error); + } + }); + + app.delete('/api/uploads/:filename', async function (req, res, next) { + try { + const filename = require('path').basename(String(req.params.filename || '').trim()); + if (!filename) { + return res.status(400).json({ error: 'Filename is required' }); + } + const filePath = require('path').join(uploadDir, filename); + try { + await fs.promises.unlink(filePath); + } catch (error) { + if (!error || error.code !== 'ENOENT') { + throw error; + } + } + res.json({ ok: true, filename: filename }); + } catch (error) { + next(error); + } + }); + + app.get('/screen/:slug', function (req, res) { + res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.set('Pragma', 'no-cache'); + playerPlaylistService.buildScreenPlaylist(req.params.slug).then(function (data) { + res.send(common.renderPlayerPage(req.params.slug, data)); + }).catch(function (error) { + console.error(error); + res.status(500).send('Internal server error'); + }); + }); + + app.get('/api/screens/:slug/playlist', async function (req, res, next) { + try { + res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + const data = await playerPlaylistService.buildScreenPlaylist(req.params.slug); + if (!data.screen) { + return res.status(404).json({ error: 'Screen not found' }); + } + const etag = '"' + String(data.revision || '') + '"'; + res.set('ETag', etag); + if (String(req.headers['if-none-match'] || '').split(',').map(function (value) { + return String(value || '').trim(); + }).includes(etag)) { + return res.status(304).end(); + } + res.json(data); + } catch (error) { + next(error); + } + }); + + app.get(['/api/screens/:slug/connections', '/api/screens/:slug/clients'], async function (req, res, next) { + try { + const [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [req.params.slug]); + if (!screenRows.length) { + return res.status(404).json({ error: 'Screen not found' }); + } + const connections = playerRuntime.snapshotConnections(req.params.slug); + res.json({ + screen: screenRows[0], + screenSlug: req.params.slug, + count: connections.length, + connections: connections + }); + } catch (error) { + next(error); + } + }); + + app.post('/api/screens/:slug/commands', async function (req, res, next) { + try { + const command = String((req.body && req.body.command) || req.query.command || '').trim().toLowerCase(); + const connectionId = String((req.body && (req.body.connectionId || req.body.clientId)) || req.query.connectionId || req.query.clientId || '').trim(); + const blackoutValue = req.body && Object.prototype.hasOwnProperty.call(req.body, 'blackout') + ? req.body.blackout + : req.query.blackout; + if (!command) { + return res.status(400).json({ error: 'Command is required' }); + } + if (['refresh', 'reload', 'redirect', 'pause', 'blackout', 'previous', 'next', 'left', 'right', 'setclientname'].indexOf(command) === -1) { + return res.status(400).json({ error: 'Unsupported command' }); + } + + const isRedirectCommand = command === 'redirect'; + let screenRows = []; + if (!isRedirectCommand) { + [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [req.params.slug]); + if (!screenRows.length) { + return res.status(404).json({ error: 'Screen not found' }); + } + } + + const commandPayload = req.body && typeof req.body === 'object' && !Array.isArray(req.body) + ? Object.assign({}, req.body, { command: command }) + : command; + if (command === 'blackout' && blackoutValue !== undefined && commandPayload && typeof commandPayload === 'object') { + commandPayload.blackout = blackoutValue; + } + + const sent = connectionId + ? playerRuntime.sendCommandToConnection(req.params.slug, connectionId, commandPayload) + : playerRuntime.broadcastCommand(req.params.slug, commandPayload); + + res.json({ + screen: screenRows[0] || null, + screenSlug: req.params.slug, + command: command, + connectionId: connectionId || null, + sent: sent + }); + } catch (error) { + next(error); + } + }); +} + +module.exports = { + registerPlayerRoutes: registerPlayerRoutes +}; \ No newline at end of file diff --git a/src/player/runtime.js b/src/player/runtime.js new file mode 100644 index 0000000..4bec3bf --- /dev/null +++ b/src/player/runtime.js @@ -0,0 +1,416 @@ +const crypto = require('crypto'); +const { WebSocketServer, WebSocket } = require('ws'); + +function createPlayerRuntime(options) { + const pool = options && options.pool ? options.pool : null; + const normalizeDeviceId = typeof options.normalizeDeviceId === 'function' + ? options.normalizeDeviceId + : function (value) { + return String(value || '').trim().replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 128); + }; + const connectionsBySlug = new Map(); + const dashboardListenersBySlug = new Map(); + const wss = new WebSocketServer({ noServer: true }); + + function normalizeClientIp(value) { + const ip = String(value || '').trim(); + if (!ip) { + return null; + } + + if (ip.toLowerCase().startsWith('::ffff:')) { + return ip.slice(7).trim() || null; + } + + return ip; + } + + function getConnectionBucket(slug) { + const key = String(slug || '').trim(); + if (!key) { + return null; + } + if (!connectionsBySlug.has(key)) { + connectionsBySlug.set(key, new Map()); + } + return connectionsBySlug.get(key); + } + + function removeConnection(slug, connectionId) { + const bucket = connectionsBySlug.get(String(slug || '').trim()); + if (!bucket) { + return; + } + bucket.delete(connectionId); + if (!bucket.size) { + connectionsBySlug.delete(String(slug || '').trim()); + } + } + + function getDashboardListenerBucket(slug) { + const key = String(slug || '').trim(); + if (!key) { + return null; + } + if (!dashboardListenersBySlug.has(key)) { + dashboardListenersBySlug.set(key, new Set()); + } + return dashboardListenersBySlug.get(key); + } + + function removeDashboardListener(slug, socket) { + const key = String(slug || '').trim(); + const bucket = dashboardListenersBySlug.get(key); + if (!bucket) { + return; + } + bucket.delete(socket); + if (!bucket.size) { + dashboardListenersBySlug.delete(key); + } + } + + function buildClientLabel(connection) { + const clientName = String(connection.clientName || '').trim(); + const clientId = String(connection.clientId || '').trim(); + const userAgent = String(connection.userAgent || '').trim(); + const clientIp = String(connection.clientIp || '').trim(); + const viewport = connection.viewport && typeof connection.viewport === 'object' + ? connection.viewport + : null; + const labelParts = []; + + if (userAgent) { + labelParts.push(userAgent.length > 72 ? `${userAgent.slice(0, 72)}...` : userAgent); + } + + if (clientName) { + labelParts.push(clientName); + } else if (clientId) { + labelParts.push(`id ${clientId.slice(-6)}`); + } + + if (clientIp) { + labelParts.push(clientIp); + } + + if (viewport && Number.isFinite(Number(viewport.width)) && Number.isFinite(Number(viewport.height))) { + labelParts.push(`${Number(viewport.width)}x${Number(viewport.height)}`); + } + + if (!labelParts.length) { + return connection.remoteAddress || 'connected client'; + } + + return labelParts.join(' • '); + } + + function snapshotConnections(slug) { + const bucket = connectionsBySlug.get(String(slug || '').trim()); + if (!bucket) { + return []; + } + + return Array.from(bucket.values()).map(function (connection) { + return { + id: connection.id, + clientId: connection.clientId || null, + clientName: connection.clientName || null, + deviceId: connection.deviceId || null, + label: connection.label, + userAgent: connection.userAgent || null, + viewport: connection.viewport || null, + page: connection.page || null, + currentSlide: connection.currentSlide || null, + paused: Boolean(connection.paused), + blackout: Boolean(connection.blackout), + currentSlideId: connection.currentSlide && connection.currentSlide.id ? connection.currentSlide.id : null, + currentSlideTitle: connection.currentSlide && connection.currentSlide.title ? connection.currentSlide.title : null, + clientIp: connection.clientIp || null, + remoteAddress: connection.remoteAddress || null, + connectedAt: connection.connectedAt ? connection.connectedAt.toISOString() : null, + lastSeenAt: connection.lastSeenAt ? connection.lastSeenAt.toISOString() : null + }; + }); + } + + async function isClientNameAvailableOnScreen(poolArg, clientName, excludeDeviceId) { + const normalizedName = String(clientName || '').trim(); + if (!normalizedName) { + return false; + } + + const normalizedDeviceId = normalizeDeviceId(excludeDeviceId); + const lowerName = normalizedName.toLowerCase(); + const liveDeviceIds = new Set(); + const liveClientIds = new Set(); + + for (const bucket of connectionsBySlug.values()) { + if (!bucket || typeof bucket.values !== 'function') { + continue; + } + for (const connection of bucket.values()) { + const existingDeviceId = normalizeDeviceId(connection && connection.deviceId ? connection.deviceId : ''); + const existingClientId = normalizeDeviceId(connection && connection.clientId ? connection.clientId : ''); + if (existingDeviceId) { + liveDeviceIds.add(existingDeviceId); + } + if (existingClientId) { + liveClientIds.add(existingClientId); + } + const existingName = String(connection && connection.clientName ? connection.clientName : '').trim(); + if (!existingName) { + continue; + } + if (existingName.toLowerCase() !== lowerName) { + continue; + } + if (normalizedDeviceId && existingDeviceId && existingDeviceId === normalizedDeviceId) { + continue; + } + return false; + } + } + + const activePool = poolArg || pool; + if (!activePool || (!liveDeviceIds.size && !liveClientIds.size)) { + return true; + } + + try { + const [deviceRows] = await activePool.query( + `SELECT device_id + FROM player_onboarding_devices + WHERE client_name IS NOT NULL + AND TRIM(client_name) <> '' + AND LOWER(TRIM(client_name)) = LOWER(TRIM(?))`, + [normalizedName] + ); + + for (let i = 0; i < deviceRows.length; i += 1) { + const deviceId = normalizeDeviceId(deviceRows[i] && deviceRows[i].device_id ? deviceRows[i].device_id : ''); + if (!deviceId) { + continue; + } + if (normalizedDeviceId && deviceId === normalizedDeviceId) { + continue; + } + if (liveDeviceIds.has(deviceId)) { + return false; + } + } + } catch (_error) { + return true; + } + + return true; + } + + function broadcastConnectionSnapshot(slug) { + const key = String(slug || '').trim(); + const bucket = dashboardListenersBySlug.get(key); + if (!bucket || !bucket.size) { + return; + } + + const payload = JSON.stringify({ + type: 'snapshot', + slug: key, + connections: snapshotConnections(slug), + sentAt: new Date().toISOString() + }); + + bucket.forEach(function (socket) { + if (socket.readyState === WebSocket.OPEN) { + socket.send(payload); + } + }); + } + + function sendCommandToConnection(slug, connectionId, commandOrPayload) { + const bucket = connectionsBySlug.get(String(slug || '').trim()); + if (!bucket || !bucket.size) { + return 0; + } + + const target = bucket.get(String(connectionId || '').trim()); + if (!target || target.socket.readyState !== WebSocket.OPEN) { + return 0; + } + + const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null + ? Object.assign({}, commandOrPayload) + : { command: commandOrPayload }; + payload.type = 'command'; + payload.targetConnectionId = target.id; + payload.sentAt = new Date().toISOString(); + + target.socket.send(JSON.stringify(payload)); + return 1; + } + + function broadcastCommand(slug, commandOrPayload) { + const bucket = connectionsBySlug.get(String(slug || '').trim()); + if (!bucket || !bucket.size) { + return 0; + } + + let sent = 0; + bucket.forEach(function (connection) { + if (connection.socket.readyState !== WebSocket.OPEN) { + return; + } + const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null + ? Object.assign({}, commandOrPayload) + : { command: commandOrPayload }; + payload.type = 'command'; + payload.sentAt = new Date().toISOString(); + + connection.socket.send(JSON.stringify(payload)); + sent += 1; + }); + return sent; + } + + function handleUpgrade(request, socket, head) { + let pathname = ''; + try { + pathname = new URL(request.url, 'http://localhost').pathname; + } catch (_error) { + socket.destroy(); + return; + } + + const dashboardMatch = pathname.match(/^\/ws\/screens\/([^/]+)\/events$/); + const playerMatch = pathname.match(/^\/ws\/screens\/([^/]+)$/); + if (!dashboardMatch && !playerMatch) { + socket.destroy(); + return; + } + + const slug = decodeURIComponent((dashboardMatch || playerMatch)[1]); + wss.handleUpgrade(request, socket, head, function (ws) { + wss.emit('connection', ws, request, slug, dashboardMatch ? 'dashboard' : 'player'); + }); + } + + wss.on('connection', function (socket, request, slug, role) { + if (role === 'dashboard') { + const listenerBucket = getDashboardListenerBucket(slug); + if (!listenerBucket) { + socket.close(); + return; + } + + listenerBucket.add(socket); + socket.send(JSON.stringify({ + type: 'snapshot', + slug: String(slug || '').trim(), + connections: snapshotConnections(slug), + sentAt: new Date().toISOString() + })); + + socket.on('close', function () { + removeDashboardListener(slug, socket); + }); + + socket.on('error', function () { + removeDashboardListener(slug, socket); + }); + return; + } + + const remoteAddress = request.socket && request.socket.remoteAddress ? request.socket.remoteAddress : null; + const forwardedFor = normalizeClientIp(String(request.headers['x-forwarded-for'] || '').split(',')[0]); + const normalizedRemoteAddress = normalizeClientIp(remoteAddress); + const connectionId = crypto.randomUUID(); + const connection = { + id: connectionId, + slug: slug, + socket: socket, + clientId: null, + clientName: null, + deviceId: null, + userAgent: null, + viewport: null, + page: null, + paused: false, + blackout: false, + clientIp: forwardedFor || normalizedRemoteAddress, + remoteAddress: normalizedRemoteAddress, + label: forwardedFor || normalizedRemoteAddress || 'connected client', + connectedAt: new Date(), + lastSeenAt: new Date() + }; + const bucket = getConnectionBucket(slug); + + if (!bucket) { + socket.close(); + return; + } + + bucket.set(connectionId, connection); + + socket.on('message', function (rawMessage) { + connection.lastSeenAt = new Date(); + let payload = null; + try { + payload = JSON.parse(String(rawMessage || '')); + } catch (_error) { + return; + } + + if (!payload || (payload.type !== 'hello' && payload.type !== 'state')) { + return; + } + + connection.clientId = payload.clientId ? String(payload.clientId).trim() : connection.clientId; + connection.clientName = payload.clientName ? String(payload.clientName).trim() : connection.clientName; + connection.deviceId = payload.deviceId ? normalizeDeviceId(payload.deviceId) || connection.deviceId : connection.deviceId; + if (!connection.clientName && connection.clientId) { + connection.clientName = connection.clientId; + } + connection.userAgent = payload.userAgent ? String(payload.userAgent).trim() : connection.userAgent; + connection.viewport = payload.viewport && typeof payload.viewport === 'object' ? payload.viewport : connection.viewport; + connection.page = payload.page ? String(payload.page).trim() : connection.page; + connection.paused = Boolean(payload.paused); + connection.blackout = Boolean(payload.blackout); + connection.clientIp = payload.clientIp ? normalizeClientIp(payload.clientIp) || connection.clientIp : connection.clientIp; + connection.currentSlide = payload.currentSlide && typeof payload.currentSlide === 'object' ? { + id: payload.currentSlide.id || null, + title: payload.currentSlide.title || '', + kind: payload.currentSlide.kind || '', + playlistSignature: payload.currentSlide.playlistSignature || '' + } : connection.currentSlide; + connection.label = buildClientLabel(connection); + connection.lastSeenAt = new Date(); + broadcastConnectionSnapshot(slug); + }); + + socket.on('close', function () { + removeConnection(slug, connectionId); + broadcastConnectionSnapshot(slug); + }); + + socket.on('error', function () { + removeConnection(slug, connectionId); + broadcastConnectionSnapshot(slug); + }); + }); + + function installWebsocket(server) { + server.on('upgrade', handleUpgrade); + } + + return { + installWebsocket: installWebsocket, + snapshotConnections: snapshotConnections, + isClientNameAvailableOnScreen: isClientNameAvailableOnScreen, + sendCommandToConnection: sendCommandToConnection, + broadcastCommand: broadcastCommand + }; +} + +module.exports = { + createPlayerRuntime: createPlayerRuntime +}; diff --git a/src/web.js b/src/web.js index 150ddc0..0885570 100644 --- a/src/web.js +++ b/src/web.js @@ -4,10 +4,34 @@ const multer = require('multer'); const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); -const { WebSocketServer, WebSocket } = require('ws'); const common = require('./common'); const { verifyPassword, createSessionToken, hashSessionToken, hashPassword } = require('./auth'); const pages = require('./web/routes'); +const registerAuthRoutes = require('./web/routes/auth'); +const registerAdminPagesRoutes = require('./web/routes/admin-pages'); +const registerAdminAccountRoutes = require('./web/routes/admin-account'); +const registerAdminUsersRoutes = require('./web/routes/admin-users'); +const registerAdminManageRoutes = require('./web/routes/admin-manage'); +const registerAdminScreenCommandRoutes = require('./web/routes/admin-screen-commands'); +const registerAdminContentRoutes = require('./web/routes/admin-content'); +const { createWebBootstrap } = require('./web/bootstrap'); +const { createPlayerActionService } = require('./web/player-actions'); +const { createSessionService } = require('./web/session'); +const { + formatDashboardDate, + readArrayField, + parseDateTimeLocal, + parseTimeLocal, + normalizeScheduleMode, + getAuditUserId, + getCanvasSignature, + fetchPlaylistCanvasSignature, + fetchScreensByPlaylistId, + fetchScreensBySlideId, + fetchScreensByTemplateId, + fetchOrderedPlaylistSlides, + redirectAfterSave +} = require('./web/helpers'); const PLAYER_INTERNAL_BASE_URL = (process.env.PLAYER_INTERNAL_BASE_URL || process.env.PLAYER_BASE_URL || 'http://player:3001').replace(/\/$/, ''); const PLAYER_PUBLIC_BASE_URL = (process.env.PLAYER_PUBLIC_BASE_URL || process.env.PLAYER_BASE_URL || 'http://localhost:3001').replace(/\/$/, ''); const PLAYER_WS_BASE_URL = PLAYER_INTERNAL_BASE_URL.replace(/^http/, 'ws'); @@ -15,933 +39,6 @@ const SESSION_COOKIE_NAME = 'digital_signage_session'; const SESSION_MAX_AGE_DAYS = Number(process.env.SESSION_MAX_AGE_DAYS || 14); const SESSION_MAX_AGE_MS = (Number.isFinite(SESSION_MAX_AGE_DAYS) && SESSION_MAX_AGE_DAYS > 0 ? SESSION_MAX_AGE_DAYS : 14) * 24 * 60 * 60 * 1000; -const playerSnapshotCache = new Map(); -const playerSnapshotSockets = new Map(); -let playerUploadSyncMode = null; -let playerUploadSyncModePromise = null; -const pendingPlayerUploadSyncs = new Map(); -let pendingPlayerUploadSyncFlushTimer = null; -let pendingPlayerUploadSyncFlushInFlight = null; -const pendingPlaylistUploadSyncs = new Map(); -let pendingPlaylistUploadSyncFlushTimer = null; -let pendingPlaylistUploadSyncFlushInFlight = null; - -function normalizeUploadRoot(uploadDir) { - return path.resolve(String(uploadDir || '').trim()); -} - -function readArrayField(body, keys) { - const searchKeys = Array.isArray(keys) ? keys : [keys]; - for (let i = 0; i < searchKeys.length; i += 1) { - const value = body[searchKeys[i]]; - if (Array.isArray(value)) { - return value; - } - if (value !== undefined && value !== null && value !== '') { - return [value]; - } - } - return []; -} - -function parseDateTimeLocal(value) { - if (!value) { - return null; - } - const date = new Date(String(value)); - return Number.isNaN(date.getTime()) ? null : date; -} - -function parseTimeLocal(value) { - const raw = String(value || '').trim(); - if (!raw) { - return null; - } - if (!/^\d{2}:\d{2}(:\d{2})?$/.test(raw)) { - return null; - } - return raw.length === 5 ? raw + ':00' : raw; -} - -function normalizeScheduleMode(value) { - const mode = String(value || 'always'); - if (mode === 'dates' || mode === 'times') { - return mode; - } - return 'always'; -} - - -// Session and auth helpers. -function getAuditUserId(req) { - return req && req.currentUser ? Number(req.currentUser.id) : null; -} - -function getCanvasSignature(width, height) { - const normalizedWidth = Number(width); - const normalizedHeight = Number(height); - if (!Number.isFinite(normalizedWidth) || !Number.isFinite(normalizedHeight)) { - return null; - } - return normalizedWidth + 'x' + normalizedHeight; -} - -async function fetchPlaylistCanvasSignature(pool, playlistId) { - const [rows] = await pool.query(` - SELECT DISTINCT cs.width AS canvas_width, cs.height AS canvas_height - FROM playlist_slides ps - JOIN slides sl ON sl.id = ps.slide_id - LEFT JOIN slide_templates st ON st.id = sl.template_id - LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id - WHERE ps.playlist_id = ? - AND cs.width IS NOT NULL - AND cs.height IS NOT NULL - `, [playlistId]); - const signatures = Array.from(new Set(rows.map((row) => getCanvasSignature(row.canvas_width, row.canvas_height)).filter(Boolean))); - if (!signatures.length) { - return null; - } - return signatures.length === 1 ? signatures[0] : 'mismatch'; -} - -// Player snapshot and dashboard helpers. -function getPlayerSnapshotSocketUrl(slug) { - const url = new URL(PLAYER_WS_BASE_URL); - url.pathname = `/ws/screens/${encodeURIComponent(slug)}/events`; - url.search = ''; - return url.toString(); -} - -function storePlayerSnapshot(slug, connections) { - const normalizedConnections = Array.isArray(connections) ? connections : []; - playerSnapshotCache.set(String(slug || '').trim(), { - slug: String(slug || '').trim(), - count: normalizedConnections.length, - connections: normalizedConnections - }); -} - -function clearPlayerSnapshotSocket(slug) { - const key = String(slug || '').trim(); - playerSnapshotSockets.delete(key); -} - -function ensurePlayerSnapshotSubscription(slug) { - const key = String(slug || '').trim(); - if (!key || playerSnapshotSockets.has(key)) { - return; - } - - const socket = new WebSocket(getPlayerSnapshotSocketUrl(key)); - playerSnapshotSockets.set(key, socket); - - socket.onmessage = function (event) { - try { - const payload = JSON.parse(String(event.data || '{}')); - if (!payload || payload.type !== 'snapshot' || payload.slug !== key) { - return; - } - storePlayerSnapshot(key, payload.connections || []); - broadcastDashboardState().catch(function (error) { - console.error(error); - }); - } catch (_error) { - // Ignore malformed player snapshot payloads. - } - }; - - socket.onclose = function () { - clearPlayerSnapshotSocket(key); - setTimeout(function () { - ensurePlayerSnapshotSubscription(key); - }, 2000); - }; - - socket.onerror = function () { - try { - socket.close(); - } catch (_error) { - // ignore close errors - } - }; -} - -function enrichScreensWithConnections(screens, connectionsBySlug) { - return (screens || []).map(function (screen) { - const connectionState = connectionsBySlug[screen.slug] || { count: 0, connections: [] }; - return Object.assign({}, screen, { - player_connection_count: connectionState.count || 0, - player_connections: Array.isArray(connectionState.connections) ? connectionState.connections : [] - }); - }); -} - -function buildClientRows(screens, connectionsBySlug) { - return (screens || []).flatMap(function (screen) { - const connectionState = connectionsBySlug[screen.slug] || { count: 0, connections: [] }; - return (connectionState.connections || []).map(function (connection) { - return Object.assign({}, connection, { - screen_slug: screen.slug, - screen_name: screen.name, - playlist_name: screen.playlist_name || null, - connectedAtLabel: formatDashboardDate(connection.connectedAt), - lastSeenAtLabel: formatDashboardDate(connection.lastSeenAt), - player_url: `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(screen.slug)}` - }); - }); - }); -} - -// Player command helpers. -async function forwardPlayerCommand(slug, commandOrPayload, connectionId) { - const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null - ? Object.assign({}, commandOrPayload) - : { command: commandOrPayload }; - if (connectionId) { - payload.connectionId = connectionId; - } - const response = await fetch(`${PLAYER_INTERNAL_BASE_URL}/api/screens/${encodeURIComponent(slug)}/commands`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - const errorText = await response.text().catch(function () { return ''; }); - const error = new Error(errorText || `Unable to send command to player ${slug}.`); - error.statusCode = response.status; - throw error; - } - - return response.json().catch(function () { - return { ok: true }; - }); -} - -async function notifyPlayerScreens(slugs, commandOrPayload) { - const uniqueSlugs = Array.from(new Set((slugs || []).map(function (slug) { - return String(slug || '').trim(); - }).filter(Boolean))); - - if (!uniqueSlugs.length) { - return 0; - } - - const results = await Promise.allSettled(uniqueSlugs.map(function (slug) { - return forwardPlayerCommand(slug, commandOrPayload || 'refresh'); - })); - - return results.filter(function (result) { - return result.status === 'fulfilled'; - }).length; -} - -// Screen lookup helpers used by the admin routes. -async function fetchAllScreenSlugs(connection) { - const [rows] = await connection.query('SELECT slug FROM screens WHERE slug IS NOT NULL'); - return rows.map(function (row) { - return row.slug; - }); -} - -async function fetchScreensByPlaylistId(connection, playlistId) { - const [rows] = await connection.query( - 'SELECT slug FROM screens WHERE playlist_id = ? AND slug IS NOT NULL', - [playlistId] - ); - return rows.map(function (row) { - return row.slug; - }); -} - -async function fetchScreensBySlideId(connection, slideId) { - const [rows] = await connection.query( - `SELECT DISTINCT s.slug - FROM screens s - JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id - WHERE ps.slide_id = ? - AND s.slug IS NOT NULL`, - [slideId] - ); - return rows.map(function (row) { - return row.slug; - }); -} - -async function fetchScreensByTemplateId(connection, templateId) { - const [rows] = await connection.query( - `SELECT DISTINCT s.slug - FROM screens s - JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id - JOIN slides sl ON sl.id = ps.slide_id - WHERE sl.template_id = ? - AND s.slug IS NOT NULL`, - [templateId] - ); - return rows.map(function (row) { - return row.slug; - }); -} - -async function fetchSlideIdsByTemplateId(connection, templateId) { - const [rows] = await connection.query( - 'SELECT id FROM slides WHERE template_id = ?', - [templateId] - ); - return rows.map(function (row) { - return Number(row.id); - }).filter(function (value) { - return Number.isFinite(value); - }); -} - -function formatDashboardDate(value) { - if (!value) { - return ''; - } - const date = new Date(value); - if (Number.isNaN(date.getTime())) { - return ''; - } - return new Intl.DateTimeFormat('en-US', { - month: 'short', - day: '2-digit', - year: 'numeric', - hour: 'numeric', - minute: '2-digit', - second: '2-digit' - }).format(date); -} - -async function buildDashboardState(pool) { - const data = await common.fetchAdminData(pool); - const screensData = data.screens || []; - screensData.forEach(function (screen) { - ensurePlayerSnapshotSubscription(screen.slug); - }); - - const connectionsBySlug = {}; - screensData.forEach(function (screen) { - const cached = playerSnapshotCache.get(String(screen.slug || '').trim()); - if (cached && Array.isArray(cached.connections)) { - connectionsBySlug[screen.slug] = cached; - } - }); - - const screens = enrichScreensWithConnections(data.screens || [], connectionsBySlug).map(function (screen) { - return Object.assign({}, screen, { - player_url: `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(screen.slug)}` - }); - }); - const clients = buildClientRows(data.screens || [], connectionsBySlug); - const playerServiceConnected = Array.from(playerSnapshotSockets.values()).some(function (socket) { - return socket && socket.readyState === WebSocket.OPEN; - }); - - return { - playlists: data.playlists || [], - screens: screens, - clients: clients, - slides: data.slides || [], - playerServiceConnected: playerServiceConnected, - connectedClientsCount: screens.reduce(function (total, screen) { - return total + Number(screen.player_connection_count || 0); - }, 0) - }; -} - -function buildDashboardPayload(state) { - return JSON.stringify({ - type: 'dashboard-state', - state: state - }); -} - -async function fetchOrderedPlaylistSlides(connection, playlistId) { - const [rows] = await connection.query( - 'SELECT id, position FROM playlist_slides WHERE playlist_id = ? ORDER BY position ASC, id ASC', - [playlistId] - ); - return rows; -} - -// Upload synchronization and retry helpers. -function createUploadMiddleware(uploadDir) { - const storage = multer.diskStorage({ - destination: function (_req, _file, cb) { - cb(null, uploadDir); - }, - filename: function (_req, file, cb) { - const safeExt = path.extname(file.originalname || '').toLowerCase(); - const stamp = `${Date.now()}-${crypto.randomUUID()}`; - cb(null, `${stamp}${safeExt}`); - } - }); - return multer({ storage }); -} - -function normalizeUploadReference(uploadPath) { - const value = String(uploadPath || '').trim(); - if (!value || !value.startsWith('/uploads/')) { - return null; - } - return value; -} - -function collectUploadReferencesFromValue(value, refs) { - if (!value) { - return refs; - } - const stack = [value]; - while (stack.length) { - const current = stack.pop(); - if (Array.isArray(current)) { - current.forEach(function (item) { - stack.push(item); - }); - continue; - } - if (current && typeof current === 'object') { - Object.keys(current).forEach(function (key) { - stack.push(current[key]); - }); - continue; - } - if (typeof current === 'string') { - const reference = normalizeUploadReference(current); - if (reference) { - refs.add(reference); - } - } - } - return refs; -} - -function collectUploadReferencesFromSlide(slide) { - const refs = new Set(); - if (!slide) { - return refs; - } - collectUploadReferencesFromValue(slide.media_path, refs); - collectUploadReferencesFromValue(common.parseJsonSafe(slide.content_json), refs); - return refs; -} - -function collectUploadReferencesFromTemplate(template) { - const refs = new Set(); - if (!template) { - return refs; - } - collectUploadReferencesFromValue(template.background_image_path, refs); - return refs; -} - -function collectUploadReferencesFromPayload(payload) { - const refs = new Set(); - if (!payload) { - return refs; - } - collectUploadReferencesFromValue(payload.mediaPath, refs); - collectUploadReferencesFromValue(common.parseJsonSafe(payload.contentJson), refs); - collectUploadReferencesFromValue(payload.backgroundImagePath, refs); - return refs; -} - -async function countUploadReferences(pool, uploadPath) { - const [slideRows] = await pool.query( - `SELECT COUNT(*) AS ref_count - FROM slides - WHERE media_path = ? - OR JSON_SEARCH(COALESCE(content_json, JSON_OBJECT()), 'one', ?) IS NOT NULL`, - [uploadPath, uploadPath] - ); - const [templateRows] = await pool.query( - 'SELECT COUNT(*) AS ref_count FROM slide_templates WHERE background_image_path = ?', - [uploadPath] - ); - return Number(slideRows[0].ref_count || 0) + Number(templateRows[0].ref_count || 0); -} - -async function removeUnusedUploadFiles(pool, uploadDir, uploadPaths) { - const uniquePaths = Array.from(new Set((uploadPaths || []).map(normalizeUploadReference).filter(Boolean))); - for (let i = 0; i < uniquePaths.length; i += 1) { - const uploadPath = uniquePaths[i]; - const referenceCount = await countUploadReferences(pool, uploadPath); - if (referenceCount > 0) { - continue; - } - - const filePath = path.join(uploadDir, path.basename(uploadPath)); - try { - await fs.promises.unlink(filePath); - } catch (error) { - if (error && error.code !== 'ENOENT') { - console.warn('Unable to remove unused upload file:', filePath, error); - } - } - queuePlayerUploadSync({ - type: 'delete', - uploadPath: uploadPath, - uploadDir: uploadDir - }); - } -} - -async function getPlayerUploadSyncMode(localUploadDir) { - if (playerUploadSyncMode) { - return playerUploadSyncMode; - } - if (playerUploadSyncModePromise) { - return playerUploadSyncModePromise; - } - - playerUploadSyncModePromise = (async function () { - try { - const response = await fetch(`${PLAYER_INTERNAL_BASE_URL}/api/uploads/config`, { - headers: { - Accept: 'application/json' - } - }); - if (!response.ok) { - return null; - } - const data = await response.json(); - const playerUploadDir = data && data.uploadDir ? normalizeUploadRoot(data.uploadDir) : null; - if (!playerUploadDir) { - return null; - } - return playerUploadDir === normalizeUploadRoot(localUploadDir) ? 'shared' : 'different'; - } catch (_error) { - return null; - } - })().then(function (mode) { - if (mode) { - playerUploadSyncMode = mode; - } - playerUploadSyncModePromise = null; - return mode; - }, function () { - playerUploadSyncModePromise = null; - return null; - }); - - return playerUploadSyncModePromise; -} - -async function shouldMirrorUploads(localUploadDir) { - return Boolean(localUploadDir); -} - -function queuePlayerUploadSync(operation) { - if (!operation || !operation.uploadPath) { - return; - } - - pendingPlayerUploadSyncs.set(normalizeUploadReference(operation.uploadPath), { - type: operation.type === 'delete' ? 'delete' : 'put', - uploadPath: normalizeUploadReference(operation.uploadPath), - uploadDir: operation.uploadDir || null - }); - - schedulePendingPlayerUploadSyncFlush(); -} - -function schedulePendingPlayerUploadSyncFlush() { - if (pendingPlayerUploadSyncFlushTimer) { - return; - } - - pendingPlayerUploadSyncFlushTimer = setTimeout(function () { - pendingPlayerUploadSyncFlushTimer = null; - flushPendingPlayerUploadSyncs().catch(function (error) { - console.warn('Unable to flush pending upload syncs:', error); - }); - }, 5000); -} - -async function pushUploadFileToPlayer(uploadPath, localUploadDir) { - if (!uploadPath || !(await shouldMirrorUploads(localUploadDir))) { - return false; - } - - const filename = path.basename(uploadPath); - const sourcePath = path.join(localUploadDir, filename); - let fileBuffer = null; - try { - fileBuffer = await fs.promises.readFile(sourcePath); - } catch (error) { - if (!error || error.code !== 'ENOENT') { - console.warn('Unable to read upload for player sync:', sourcePath, error); - } - return; - } - - try { - const response = await fetch(`${PLAYER_INTERNAL_BASE_URL}/api/uploads/${encodeURIComponent(filename)}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/octet-stream' - }, - body: fileBuffer - }); - if (!response.ok) { - console.warn('Unable to sync upload to player:', filename, response.status, response.statusText); - return false; - } - return true; - } catch (error) { - console.warn('Unable to sync upload to player:', filename, error); - return false; - } -} - -async function removeUploadFileFromPlayer(uploadPath, localUploadDir) { - if (!uploadPath || !(await shouldMirrorUploads(localUploadDir))) { - return false; - } - - const filename = path.basename(uploadPath); - try { - const response = await fetch(`${PLAYER_INTERNAL_BASE_URL}/api/uploads/${encodeURIComponent(filename)}`, { - method: 'DELETE', - headers: { - Accept: 'application/json' - } - }); - if (!response.ok && response.status !== 404) { - console.warn('Unable to remove upload from player:', filename, response.status, response.statusText); - return false; - } - return true; - } catch (error) { - console.warn('Unable to remove upload from player:', filename, error); - return false; - } -} - -async function syncUploadRefsToPlayer(uploadRefs, localUploadDir) { - if (!(await shouldMirrorUploads(localUploadDir))) { - return; - } - - const uniqueRefs = Array.from(new Set((uploadRefs || []).map(normalizeUploadReference).filter(Boolean))); - for (let i = 0; i < uniqueRefs.length; i += 1) { - const success = await pushUploadFileToPlayer(uniqueRefs[i], localUploadDir); - if (!success) { - queuePlayerUploadSync({ - type: 'put', - uploadPath: uniqueRefs[i], - uploadDir: localUploadDir - }); - } - } -} - -async function syncExistingUploadsToPlayer(pool, localUploadDir) { - if (!(await shouldMirrorUploads(localUploadDir))) { - return; - } - - const data = await common.fetchAdminData(pool); - const uploadRefs = new Set(); - (data.slides || []).forEach(function (slide) { - collectUploadReferencesFromSlide(slide).forEach(function (reference) { - uploadRefs.add(reference); - }); - }); - (data.templates || []).forEach(function (template) { - collectUploadReferencesFromTemplate(template).forEach(function (reference) { - uploadRefs.add(reference); - }); - }); - Array.from(uploadRefs).forEach(function (uploadPath) { - queuePlayerUploadSync({ - type: 'put', - uploadPath: uploadPath, - uploadDir: localUploadDir - }); - }); - await flushPendingPlayerUploadSyncs(); -} - -function getVisibleCurrentSlideIds() { - const visibleSlideIds = new Set(); - playerSnapshotCache.forEach(function (snapshot) { - const connections = snapshot && Array.isArray(snapshot.connections) ? snapshot.connections : []; - connections.forEach(function (connection) { - const currentSlide = connection && connection.currentSlide && typeof connection.currentSlide === 'object' - ? connection.currentSlide - : null; - const slideId = currentSlide && currentSlide.id !== undefined && currentSlide.id !== null - ? String(currentSlide.id).trim() - : ''; - if (slideId) { - visibleSlideIds.add(slideId); - } - }); - }); - return visibleSlideIds; -} - -function isScreenRefreshBlocked(screenSlug, blockedSlideIds) { - const slideIds = Array.isArray(blockedSlideIds) - ? blockedSlideIds.map(function (value) { - return String(value || '').trim(); - }).filter(Boolean) - : []; - if (!slideIds.length) { - return false; - } - const snapshot = playerSnapshotCache.get(String(screenSlug || '').trim()); - const connections = snapshot && Array.isArray(snapshot.connections) ? snapshot.connections : []; - return connections.some(function (connection) { - const currentSlide = connection && connection.currentSlide && typeof connection.currentSlide === 'object' - ? connection.currentSlide - : null; - const currentSlideId = currentSlide && currentSlide.id !== undefined && currentSlide.id !== null - ? String(currentSlide.id).trim() - : ''; - return currentSlideId && slideIds.includes(currentSlideId); - }); -} - -function splitRefreshScreenSlugsByVisibility(screenSlugs, blockedSlideIds) { - const ready = []; - const blocked = []; - Array.from(new Set(Array.isArray(screenSlugs) ? screenSlugs : [])).forEach(function (screenSlug) { - const normalizedScreenSlug = String(screenSlug || '').trim(); - if (!normalizedScreenSlug) { - return; - } - if (isScreenRefreshBlocked(normalizedScreenSlug, blockedSlideIds)) { - blocked.push(normalizedScreenSlug); - } else { - ready.push(normalizedScreenSlug); - } - }); - return { ready: ready, blocked: blocked }; -} - -function normalizePlaylistUploadSyncOperation(options) { - return { - key: String(options && options.key ? options.key : '').trim(), - pool: options && options.pool ? options.pool : null, - localUploadDir: options && options.localUploadDir ? options.localUploadDir : null, - previousUploadRefs: Array.from(new Set(options && options.previousUploadRefs ? options.previousUploadRefs : [])), - nextUploadRefs: Array.from(new Set(options && options.nextUploadRefs ? options.nextUploadRefs : [])), - blockedSlideIds: Array.from(new Set(options && options.blockedSlideIds ? options.blockedSlideIds : [])).map(function (value) { - return String(value || '').trim(); - }).filter(Boolean), - refreshScreenSlugs: Array.from(new Set(options && options.refreshScreenSlugs ? options.refreshScreenSlugs : [])).map(function (value) { - return String(value || '').trim(); - }).filter(Boolean) - }; -} - -function queuePlaylistUploadSync(operation) { - if (!operation || !operation.key) { - return; - } - pendingPlaylistUploadSyncs.set(operation.key, normalizePlaylistUploadSyncOperation(operation)); - schedulePendingPlaylistUploadSyncFlush(); -} - -function schedulePendingPlaylistUploadSyncFlush() { - if (pendingPlaylistUploadSyncFlushTimer) { - return; - } - - pendingPlaylistUploadSyncFlushTimer = setTimeout(function () { - pendingPlaylistUploadSyncFlushTimer = null; - flushPendingPlaylistUploadSyncs().catch(function (error) { - console.warn('Unable to flush pending playlist upload syncs:', error); - }); - }, 5000); -} - -async function syncPlaylistUploadsOnChange(options) { - const operation = normalizePlaylistUploadSyncOperation(options); - if (!operation.key) { - return; - } - - if (operation.previousUploadRefs.length) { - const nextUploadRefSet = new Set(operation.nextUploadRefs); - await removeUnusedUploadFiles(operation.pool, operation.localUploadDir, operation.previousUploadRefs.filter(function (reference) { - return !nextUploadRefSet.has(reference); - })); - } - - if (operation.nextUploadRefs.length) { - await syncUploadRefsToPlayer(operation.nextUploadRefs, operation.localUploadDir); - } - - if (operation.refreshScreenSlugs.length) { - const refreshTargets = splitRefreshScreenSlugsByVisibility(operation.refreshScreenSlugs, operation.blockedSlideIds); - if (refreshTargets.ready.length) { - await notifyPlayerScreens(refreshTargets.ready, 'refresh'); - } - refreshTargets.blocked.forEach(function (screenSlug) { - queuePlaylistUploadSync({ - key: operation.key + ':refresh:' + screenSlug, - blockedSlideIds: operation.blockedSlideIds, - refreshScreenSlugs: [screenSlug] - }); - }); - } -} - -async function flushPendingPlaylistUploadSyncs() { - if (pendingPlaylistUploadSyncFlushInFlight) { - return pendingPlaylistUploadSyncFlushInFlight; - } - - if (!pendingPlaylistUploadSyncs.size) { - return null; - } - - pendingPlaylistUploadSyncFlushInFlight = (async function () { - const pendingEntries = Array.from(pendingPlaylistUploadSyncs.values()); - for (let i = 0; i < pendingEntries.length; i += 1) { - const operation = pendingEntries[i]; - const refreshTargets = splitRefreshScreenSlugsByVisibility(operation.refreshScreenSlugs, operation.blockedSlideIds); - if (!refreshTargets.ready.length) { - continue; - } - - if (refreshTargets.ready.length) { - await notifyPlayerScreens(refreshTargets.ready, 'refresh'); - } - - pendingPlaylistUploadSyncs.delete(operation.key); - } - })().finally(function () { - pendingPlaylistUploadSyncFlushInFlight = null; - if (pendingPlaylistUploadSyncs.size) { - schedulePendingPlaylistUploadSyncFlush(); - } - }); - - return pendingPlaylistUploadSyncFlushInFlight; -} - -async function flushPendingPlayerUploadSyncs() { - if (pendingPlayerUploadSyncFlushInFlight) { - return pendingPlayerUploadSyncFlushInFlight; - } - - if (!pendingPlayerUploadSyncs.size) { - return null; - } - - pendingPlayerUploadSyncFlushInFlight = (async function () { - const pendingEntries = Array.from(pendingPlayerUploadSyncs.values()); - for (let i = 0; i < pendingEntries.length; i += 1) { - const operation = pendingEntries[i]; - let success = false; - if (operation.type === 'delete') { - success = await removeUploadFileFromPlayer(operation.uploadPath, operation.uploadDir); - } else { - success = await pushUploadFileToPlayer(operation.uploadPath, operation.uploadDir); - } - if (success) { - pendingPlayerUploadSyncs.delete(operation.uploadPath); - } - } - })().finally(function () { - pendingPlayerUploadSyncFlushInFlight = null; - if (pendingPlayerUploadSyncs.size) { - schedulePendingPlayerUploadSyncFlush(); - } - }); - - return pendingPlayerUploadSyncFlushInFlight; -} - -function parseCookies(cookieHeader) { - return String(cookieHeader || '').split(/;\s*/).reduce(function (cookies, pair) { - if (!pair) { - return cookies; - } - const separatorIndex = pair.indexOf('='); - if (separatorIndex === -1) { - return cookies; - } - const name = decodeURIComponent(pair.slice(0, separatorIndex).trim()); - const value = decodeURIComponent(pair.slice(separatorIndex + 1).trim()); - if (name) { - cookies[name] = value; - } - return cookies; - }, {}); -} - -function serializeCookie(name, value, options) { - const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]; - if (options && options.maxAge !== undefined) { - parts.push(`Max-Age=${Math.max(0, Math.trunc(Number(options.maxAge) / 1000))}`); - } - parts.push('Path=/'); - parts.push('HttpOnly'); - parts.push('SameSite=Lax'); - return parts.join('; '); -} - -function clearSessionCookie(res) { - res.setHeader('Set-Cookie', serializeCookie(SESSION_COOKIE_NAME, '', { maxAge: 0 })); -} - -function setSessionCookie(res, token) { - res.setHeader('Set-Cookie', serializeCookie(SESSION_COOKIE_NAME, token, { maxAge: SESSION_MAX_AGE_MS })); -} - -async function loadCurrentUser(pool, req) { - const cookies = parseCookies(req.headers.cookie || ''); - const token = cookies[SESSION_COOKIE_NAME]; - if (!token) { - return null; - } - - const tokenHash = hashSessionToken(token); - const [rows] = await pool.query( - `SELECT s.user_id, u.id, u.name, u.username - FROM auth_sessions s - JOIN users u ON u.id = s.user_id - WHERE s.session_hash = ? - AND s.expires_at > NOW() - LIMIT 1`, - [tokenHash] - ); - if (!rows.length) { - return null; - } - - await pool.query('UPDATE auth_sessions SET last_used_at = CURRENT_TIMESTAMP, modified_by = ? WHERE session_hash = ?', [rows[0].user_id, tokenHash]); - return rows[0]; -} - -async function createUserSession(pool, userId) { - const token = createSessionToken(); - const tokenHash = hashSessionToken(token); - const expiresAt = new Date(Date.now() + SESSION_MAX_AGE_MS); - await pool.query( - 'INSERT INTO auth_sessions (session_hash, user_id, expires_at, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', - [tokenHash, userId, expiresAt, userId, userId] - ); - return token; -} - -function requireAuth(req, res, next) { - if (req.currentUser) { - return next(); - } - res.redirect('/login?message=' + encodeURIComponent('Please sign in to continue.')); -} - -// Admin app routes and websocket wiring. async function start() { const app = express(); const server = http.createServer(app); @@ -949,13 +46,56 @@ async function start() { const PORT = Number(process.env.WEB_PORT || 3000); const UPLOAD_DIR = path.join(__dirname, '..', 'uploads'); const ASSET_DIR = path.join(__dirname, 'web', 'public'); - const dashboardWs = new WebSocketServer({ noServer: true }); - const dashboardClients = new Set(); - const dashboardRefreshIntervalMs = Number(process.env.DASHBOARD_REFRESH_INTERVAL_MS || 2000); - let dashboardRefreshInFlight = null; - fs.mkdirSync(UPLOAD_DIR, { recursive: true }); + const playerActionService = createPlayerActionService({ + common: common, + playerInternalBaseUrl: PLAYER_INTERNAL_BASE_URL + }); + const notifyPlayerScreens = function (slugs, commandOrPayload) { + const uniqueSlugs = Array.from(new Set((slugs || []).map(function (slug) { + return String(slug || '').trim(); + }).filter(Boolean))); - const upload = createUploadMiddleware(UPLOAD_DIR); + if (!uniqueSlugs.length) { + return Promise.resolve(0); + } + + return Promise.allSettled(uniqueSlugs.map(function (slug) { + return playerActionService.forwardPlayerCommand(slug, commandOrPayload || 'refresh'); + })).then(function (results) { + return results.filter(function (result) { + return result.status === 'fulfilled'; + }).length; + }); + }; + const webBootstrap = createWebBootstrap({ + pool: pool, + common: common, + playerInternalBaseUrl: PLAYER_INTERNAL_BASE_URL, + playerPublicBaseUrl: PLAYER_PUBLIC_BASE_URL, + uploadDir: UPLOAD_DIR, + dashboardRefreshIntervalMs: Number(process.env.DASHBOARD_REFRESH_INTERVAL_MS || 2000), + formatDashboardDate: formatDashboardDate, + notifyPlayerScreens: notifyPlayerScreens + }); + const upload = webBootstrap.upload; + const collectUploadReferencesFromSlide = webBootstrap.collectUploadReferencesFromSlide; + const collectUploadReferencesFromTemplate = webBootstrap.collectUploadReferencesFromTemplate; + const collectUploadReferencesFromPayload = webBootstrap.collectUploadReferencesFromPayload; + const syncPlaylistUploadsOnChange = webBootstrap.syncPlaylistUploadsOnChange; + const syncExistingUploadsToPlayer = webBootstrap.syncExistingUploadsToPlayer; + const broadcastDashboardState = webBootstrap.broadcastDashboardState; + const sessionService = createSessionService({ + sessionCookieName: SESSION_COOKIE_NAME, + sessionMaxAgeMs: SESSION_MAX_AGE_MS, + hashSessionToken: hashSessionToken, + createSessionToken: createSessionToken + }); + const parseCookies = sessionService.parseCookies; + const clearSessionCookie = sessionService.clearSessionCookie; + const setSessionCookie = sessionService.setSessionCookie; + const loadCurrentUser = sessionService.loadCurrentUser; + const createUserSession = sessionService.createUserSession; + const requireAuth = sessionService.requireAuth; app.use(express.urlencoded({ extended: true })); app.use(express.json()); @@ -971,1253 +111,94 @@ async function start() { } }); - app.get('/', function (_req, res) { - res.redirect(_req.currentUser ? '/admin' : '/login'); - }); - - app.get('/login', function (req, res) { - if (req.currentUser) { - return res.redirect('/admin'); - } - res.send(pages.renderLoginPage(req.query.message ? String(req.query.message) : '')); - }); - - app.post('/login', async function (req, res, next) { - try { - const username = String(req.body.username || '').trim(); - const password = String(req.body.password || ''); - if (!username || !password) { - return res.status(400).send('Username and password are required.'); - } - - const [rows] = await pool.query('SELECT id, name, username, password_hash, password_salt, password_iterations FROM users WHERE username = ? LIMIT 1', [username]); - const user = rows[0] || null; - if (!user || !verifyPassword(password, user)) { - return res.redirect('/login?message=' + encodeURIComponent('Invalid username or password.')); - } - - const token = await createUserSession(pool, user.id); - setSessionCookie(res, token); - res.redirect('/admin'); - } catch (error) { - next(error); - } - }); - - app.get('/logout', async function (req, res, next) { - try { - const cookies = parseCookies(req.headers.cookie || ''); - const token = cookies[SESSION_COOKIE_NAME]; - if (token) { - await pool.query('DELETE FROM auth_sessions WHERE session_hash = ?', [hashSessionToken(token)]); - } - clearSessionCookie(res); - res.redirect('/login?message=' + encodeURIComponent('You have been signed out.')); - } catch (error) { - next(error); - } - }); - app.use('/admin', requireAuth); - // Dashboard and account pages live in the authenticated admin area. - app.get('/admin', async function (req, res, next) { - try { - const data = await buildDashboardState(pool); - res.send(pages.renderDashboardPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } + registerAuthRoutes(app, { + pool: pool, + pages: pages, + createUserSession: createUserSession, + setSessionCookie: setSessionCookie, + clearSessionCookie: clearSessionCookie, + parseCookies: parseCookies, + hashSessionToken: hashSessionToken, + verifyPassword: verifyPassword, + sessionCookieName: SESSION_COOKIE_NAME }); - app.get('/admin/account', function (req, res) { - res.send(pages.renderAccountPage(req.currentUser, req.query.message ? String(req.query.message) : '')); + registerAdminPagesRoutes(app, { + pool: pool, + common: common, + pages: pages, + buildDashboardState: webBootstrap.buildDashboardState }); - app.post('/admin/account/name', async function (req, res, next) { - try { - const name = String(req.body.name || '').trim(); - if (!name) { - return res.status(400).send('Name is required.'); - } - - const actorId = getAuditUserId(req); - const [result] = await pool.query('UPDATE users SET name = ?, modified_by = ? WHERE id = ?', [name, actorId, req.currentUser.id]); - if (!result.affectedRows) { - return res.status(404).send('User not found.'); - } - - res.redirect('/admin/account?message=' + encodeURIComponent('Name updated.')); - } catch (error) { - next(error); - } + registerAdminAccountRoutes(app, { + pool: pool, + pages: pages, + formatDashboardDate: formatDashboardDate, + getAuditUserId: getAuditUserId, + verifyPassword: verifyPassword, + hashPassword: hashPassword, + createUserSession: createUserSession, + setSessionCookie: setSessionCookie }); - app.post('/admin/account/password', async function (req, res, next) { - try { - const currentPassword = String(req.body.current_password || ''); - const newPassword = String(req.body.new_password || ''); - const confirmPassword = String(req.body.confirm_password || ''); - - const [rows] = await pool.query('SELECT id, name, username, password_hash, password_salt, password_iterations FROM users WHERE id = ? LIMIT 1', [req.currentUser.id]); - const user = rows[0] || null; - if (!user) { - return res.status(404).send('User not found.'); - } - if (!verifyPassword(currentPassword, user)) { - return res.status(400).send('Current password is incorrect.'); - } - if (!newPassword || newPassword.length < 8) { - return res.status(400).send('New password must be at least 8 characters.'); - } - if (newPassword !== confirmPassword) { - return res.status(400).send('New passwords do not match.'); - } - - const passwordRecord = hashPassword(newPassword); - await pool.query( - 'UPDATE users SET password_hash = ?, password_salt = ?, password_iterations = ?, modified_by = ? WHERE id = ?', - [passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, getAuditUserId(req), user.id] - ); - await pool.query('DELETE FROM auth_sessions WHERE user_id = ?', [user.id]); - - const token = await createUserSession(pool, user.id); - setSessionCookie(res, token); - res.redirect('/admin/account?message=' + encodeURIComponent('Password updated.')); - } catch (error) { - next(error); - } + registerAdminUsersRoutes(app, { + pool: pool, + pages: pages, + formatDashboardDate: formatDashboardDate, + getAuditUserId: getAuditUserId, + hashPassword: hashPassword }); - app.get('/admin/users', async function (req, res, next) { - try { - const [rows] = await pool.query('SELECT id, name, username, created_at, modified_at FROM users ORDER BY id ASC'); - const users = rows.map(function (user) { - return Object.assign({}, user, { - isCurrentUser: Number(user.id) === Number(req.currentUser.id), - createdAtLabel: formatDashboardDate(user.created_at), - modifiedAtLabel: formatDashboardDate(user.modified_at) - }); - }); - res.send(pages.renderUsersPage({ users: users }, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } + registerAdminManageRoutes(app, { + pool: pool, + common: common, + pages: pages, + fetchOrderedPlaylistSlides: fetchOrderedPlaylistSlides, + fetchScreensByPlaylistId: fetchScreensByPlaylistId, + fetchPlaylistCanvasSignature: fetchPlaylistCanvasSignature, + getCanvasSignature: getCanvasSignature, + normalizeScheduleMode: normalizeScheduleMode, + parseDateTimeLocal: parseDateTimeLocal, + parseTimeLocal: parseTimeLocal, + readArrayField: readArrayField, + getAuditUserId: getAuditUserId, + redirectAfterSave: redirectAfterSave, + notifyPlayerScreens: notifyPlayerScreens, + broadcastDashboardState: broadcastDashboardState, + getScreenDeleteBlockMessage: playerActionService.getScreenDeleteBlockMessage, + getPlaylistDeleteBlockMessage: playerActionService.getPlaylistDeleteBlockMessage, + forwardPlayerCommand: playerActionService.forwardPlayerCommand, + playerPublicBaseUrl: PLAYER_PUBLIC_BASE_URL }); - app.get('/admin/users/new', function (req, res) { - res.send(pages.renderUsersAddPage(req.query.message ? String(req.query.message) : '', req.currentUser)); + registerAdminScreenCommandRoutes(app, { + pool: pool, + forwardPlayerCommand: playerActionService.forwardPlayerCommand }); - app.get('/admin/users/:id/edit', async function (req, res, next) { - try { - const userId = Number(req.params.id); - if (!Number.isInteger(userId) || userId <= 0) { - return res.status(400).send('Invalid user.'); - } - - const [rows] = await pool.query('SELECT id, name, username, created_at, modified_at FROM users WHERE id = ? LIMIT 1', [userId]); - const user = rows[0] || null; - if (!user) { - return res.status(404).send('User not found.'); - } - if (Number(req.currentUser.id) === userId) { - return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to update your own login details.')); - } - - res.send(pages.renderUsersEditPage(Object.assign({}, user, { - isCurrentUser: false, - createdAtLabel: formatDashboardDate(user.created_at), - modifiedAtLabel: formatDashboardDate(user.modified_at) - }), req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } + registerAdminContentRoutes(app, { + pool: pool, + common: common, + pages: pages, + upload: upload, + uploadDir: UPLOAD_DIR, + fetchScreensBySlideId: fetchScreensBySlideId, + fetchScreensByTemplateId: fetchScreensByTemplateId, + collectUploadReferencesFromSlide: collectUploadReferencesFromSlide, + collectUploadReferencesFromTemplate: collectUploadReferencesFromTemplate, + collectUploadReferencesFromPayload: collectUploadReferencesFromPayload, + syncPlaylistUploadsOnChange: syncPlaylistUploadsOnChange, + getAuditUserId: getAuditUserId, + redirectAfterSave: redirectAfterSave, + notifyPlayerScreens: notifyPlayerScreens, + broadcastDashboardState: broadcastDashboardState, + getSlideDeleteBlockMessage: playerActionService.getSlideDeleteBlockMessage, + getTemplateDeleteBlockMessage: playerActionService.getTemplateDeleteBlockMessage, + getCanvasSizeDeleteBlockMessage: playerActionService.getCanvasSizeDeleteBlockMessage }); - app.post('/admin/users', async function (req, res, next) { - try { - const name = String(req.body.name || '').trim(); - const username = String(req.body.username || '').trim(); - const password = String(req.body.password || ''); - const confirmPassword = String(req.body.confirm_password || ''); - - if (!name) { - return res.redirect('/admin/users/new?message=' + encodeURIComponent('Name is required.')); - } - if (!username) { - return res.redirect('/admin/users/new?message=' + encodeURIComponent('Username is required.')); - } - if (!password || password.length < 8) { - return res.redirect('/admin/users/new?message=' + encodeURIComponent('Password must be at least 8 characters.')); - } - if (password !== confirmPassword) { - return res.redirect('/admin/users/new?message=' + encodeURIComponent('Passwords do not match.')); - } - - const [existingRows] = await pool.query('SELECT id FROM users WHERE username = ? LIMIT 1', [username]); - if (existingRows.length) { - return res.redirect('/admin/users/new?message=' + encodeURIComponent('That username already exists.')); - } - - const passwordRecord = hashPassword(password); - const actorId = getAuditUserId(req); - await pool.query( - 'INSERT INTO users (name, username, password_hash, password_salt, password_iterations, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?)', - [name, username, passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, actorId, actorId] - ); - res.redirect('/admin/users?message=' + encodeURIComponent('User created.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/users/:id/username', async function (req, res, next) { - try { - const userId = Number(req.params.id); - const name = String(req.body.name || '').trim(); - const username = String(req.body.username || '').trim(); - - if (!Number.isInteger(userId) || userId <= 0) { - return res.status(400).send('Invalid user.'); - } - if (!name) { - return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('Name is required.')); - } - if (Number(req.currentUser.id) === userId) { - return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to update your own username or password.')); - } - if (!username) { - return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('Username is required.')); - } - - const [existingRows] = await pool.query('SELECT id FROM users WHERE username = ? AND id <> ? LIMIT 1', [username, userId]); - if (existingRows.length) { - return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('That username already exists.')); - } - - const [result] = await pool.query('UPDATE users SET name = ?, username = ?, modified_by = ? WHERE id = ?', [name, username, getAuditUserId(req), userId]); - if (!result.affectedRows) { - return res.status(404).send('User not found.'); - } - res.redirect('/admin/users?message=' + encodeURIComponent('Username updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/users/:id/password', async function (req, res, next) { - try { - const userId = Number(req.params.id); - const password = String(req.body.password || ''); - const confirmPassword = String(req.body.confirm_password || ''); - - if (!Number.isInteger(userId) || userId <= 0) { - return res.status(400).send('Invalid user.'); - } - if (Number(req.currentUser.id) === userId) { - return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to change your own password.')); - } - if (!password || password.length < 8) { - return res.redirect('/admin/users?message=' + encodeURIComponent('Password must be at least 8 characters.')); - } - if (password !== confirmPassword) { - return res.redirect('/admin/users?message=' + encodeURIComponent('Passwords do not match.')); - } - - const [rows] = await pool.query('SELECT id FROM users WHERE id = ? LIMIT 1', [userId]); - if (!rows.length) { - return res.status(404).send('User not found.'); - } - - const passwordRecord = hashPassword(password); - await pool.query( - 'UPDATE users SET password_hash = ?, password_salt = ?, password_iterations = ?, modified_by = ? WHERE id = ?', - [passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, getAuditUserId(req), userId] - ); - await pool.query('DELETE FROM auth_sessions WHERE user_id = ?', [userId]); - res.redirect('/admin/users?message=' + encodeURIComponent('Password updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/users/:id/delete', async function (req, res, next) { - try { - const userId = Number(req.params.id); - if (!Number.isInteger(userId) || userId <= 0) { - return res.status(400).send('Invalid user.'); - } - if (Number(req.currentUser.id) === userId) { - return res.redirect('/admin/users?message=' + encodeURIComponent('You cannot delete your own account from the users page.')); - } - - const [countRows] = await pool.query('SELECT COUNT(*) AS user_count FROM users'); - if (!countRows.length || Number(countRows[0].user_count) <= 1) { - return res.redirect('/admin/users?message=' + encodeURIComponent('At least one user must remain.')); - } - - const [result] = await pool.query('DELETE FROM users WHERE id = ?', [userId]); - if (!result.affectedRows) { - return res.status(404).send('User not found.'); - } - res.redirect('/admin/users?message=' + encodeURIComponent('User deleted.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/clients', async function (req, res, next) { - try { - const data = await common.fetchAdminData(pool); - res.send(pages.renderConnectedClientsPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - async function getDashboardStateSnapshot() { - if (!dashboardRefreshInFlight) { - dashboardRefreshInFlight = buildDashboardState(pool).finally(function () { - dashboardRefreshInFlight = null; - }); - } - return dashboardRefreshInFlight; - } - - function sendDashboardState(socket, state) { - if (!socket || socket.readyState !== WebSocket.OPEN) { - return; - } - socket.send(buildDashboardPayload(state)); - } - - async function broadcastDashboardState() { - if (!dashboardClients.size) { - return; - } - const state = await getDashboardStateSnapshot(); - const payload = buildDashboardPayload(state); - dashboardClients.forEach(function (socket) { - if (socket.readyState === WebSocket.OPEN) { - socket.send(payload); - } - }); - } - - async function sendDashboardStateToSocket(socket) { - try { - const state = await getDashboardStateSnapshot(); - sendDashboardState(socket, state); - } catch (_error) { - try { - socket.close(); - } catch (_closeError) { - // ignore close errors - } - } - } - - app.post('/admin/commands', async function (req, res, next) { - try { - const command = String(req.body.command || '').trim().toLowerCase(); - if (!command) { - return res.status(400).send('Command is required.'); - } - if (['reload', 'blackout'].indexOf(command) === -1) { - return res.status(400).send('Unsupported command.'); - } - - const slugs = await fetchAllScreenSlugs(pool); - const sent = command === 'blackout' - ? await notifyPlayerScreens(slugs, { - command: 'blackout', - blackout: req.body.blackout - }) - : await notifyPlayerScreens(slugs, command); - await broadcastDashboardState(); - - const message = sent - ? `Sent ${command} command to ${sent} screen${sent === 1 ? '' : 's'}.` - : `No screens were available for the ${command} command.`; - - if (String(req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest') { - return res.json({ - ok: true, - command: command, - sent: sent, - message: message - }); - } - - res.redirect('/admin?message=' + encodeURIComponent(message)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/screens/:slug/commands', async function (req, res, next) { - try { - const command = String(req.body.command || '').trim().toLowerCase(); - const connectionId = String(req.body.connectionId || '').trim(); - const blackoutValue = req.body && Object.prototype.hasOwnProperty.call(req.body, 'blackout') - ? req.body.blackout - : undefined; - if (!command) { - return res.status(400).send('Command is required.'); - } - if (['refresh', 'reload', 'pause', 'blackout', 'previous', 'next', 'left', 'right'].indexOf(command) === -1) { - return res.status(400).send('Unsupported command.'); - } - const commandPayload = command === 'blackout' && blackoutValue !== undefined - ? { - command: command, - blackout: blackoutValue - } - : command; - await forwardPlayerCommand(req.params.slug, commandPayload, connectionId); - await broadcastDashboardState(); - - if (String(req.get('X-Requested-With') || '').toLowerCase() === 'xmlhttprequest') { - return res.json({ - ok: true, - message: connectionId ? `Sent ${command} command to a connected client on ${req.params.slug}.` : `Sent ${command} command to ${req.params.slug}.` - }); - } - - res.redirect('/admin?message=' + encodeURIComponent(connectionId ? `Sent ${command} command to a connected client on ${req.params.slug}.` : `Sent ${command} command to ${req.params.slug}.`)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/playlists', async function (req, res, next) { - try { - const data = await common.fetchAdminData(pool); - if (req.query.edit) { - const playlist = await common.fetchPlaylistById(pool, Number(req.query.edit)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - return res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } - res.send(pages.renderPlaylistsPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/playlists/new', function (req, res) { - res.send(pages.renderPlaylistFormPage(req.query.message ? String(req.query.message) : '', req.currentUser)); - }); - - app.post('/admin/playlists', async function (req, res, next) { - try { - const name = String(req.body.name || '').trim(); - const fadeBetweenSlides = req.body.fade_between_slides ? 1 : 0; - if (!name) { - return res.status(400).send('Playlist name is required.'); - } - const actorId = getAuditUserId(req); - await pool.query('INSERT INTO playlists (name, fade_between_slides, created_by, modified_by) VALUES (?, ?, ?, ?)', [name, fadeBetweenSlides, actorId, actorId]); - res.redirect('/admin/playlists?message=' + encodeURIComponent('Playlist created.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id', async function (req, res, next) { - const connection = await pool.getConnection(); - try { - const name = String(req.body.name || '').trim(); - const fadeBetweenSlides = req.body.fade_between_slides ? 1 : 0; - if (!name) { - return res.status(400).send('Playlist name is required.'); - } - const playlist = await common.fetchPlaylistById(connection, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - - const affectedScreens = await fetchScreensByPlaylistId(connection, playlist.id); - - const slideIds = readArrayField(req.body, ['slide_id[]', 'slide_id']); - const durations = readArrayField(req.body, ['duration_seconds[]', 'duration_seconds']); - const scheduleModes = readArrayField(req.body, ['schedule_mode[]', 'schedule_mode']); - const scheduleStartDateTimes = readArrayField(req.body, ['schedule_start_datetime[]', 'schedule_start_datetime']); - const scheduleEndDateTimes = readArrayField(req.body, ['schedule_end_datetime[]', 'schedule_end_datetime']); - const scheduleStartTimes = readArrayField(req.body, ['schedule_start_time[]', 'schedule_start_time']); - const scheduleEndTimes = readArrayField(req.body, ['schedule_end_time[]', 'schedule_end_time']); - const scheduleDaysJsonValues = readArrayField(req.body, ['schedule_days_json[]', 'schedule_days_json']); - - if (durations.length && durations.length !== slideIds.length) { - return res.status(400).send('Playlist slide data is invalid.'); - } - if (scheduleModes.length && scheduleModes.length !== slideIds.length) { - return res.status(400).send('Playlist schedule data is invalid.'); - } - - const normalizedSlides = []; - const seenSlideIds = new Set(); - for (let i = 0; i < slideIds.length; i += 1) { - const slideId = Number(slideIds[i]); - if (!Number.isInteger(slideId) || slideId <= 0) { - return res.status(400).send('Invalid slide selection.'); - } - if (seenSlideIds.has(slideId)) { - return res.status(400).send('A slide can only be added to a playlist once.'); - } - seenSlideIds.add(slideId); - - const durationRaw = Number(durations[i]); - const durationSeconds = Number.isFinite(durationRaw) ? Math.max(1, Math.trunc(durationRaw)) : 10; - const scheduleMode = normalizeScheduleMode(scheduleModes[i]); - - let scheduleStartDatetime = null; - let scheduleEndDatetime = null; - let scheduleStartTime = null; - let scheduleEndTime = null; - let scheduleDaysJson = null; - - if (scheduleMode === 'dates') { - scheduleStartDatetime = parseDateTimeLocal(scheduleStartDateTimes[i]); - scheduleEndDatetime = parseDateTimeLocal(scheduleEndDateTimes[i]); - if (!scheduleStartDatetime || !scheduleEndDatetime) { - return res.status(400).send('Start and end datetimes are required for date scheduling.'); - } - if (scheduleEndDatetime < scheduleStartDatetime) { - return res.status(400).send('End datetime must be after start datetime.'); - } - } else if (scheduleMode === 'times') { - scheduleStartTime = parseTimeLocal(scheduleStartTimes[i]); - scheduleEndTime = parseTimeLocal(scheduleEndTimes[i]); - if (!scheduleStartTime || !scheduleEndTime) { - return res.status(400).send('Start and end times are required for time scheduling.'); - } - - let scheduleDays = []; - try { - const parsedDays = JSON.parse(String(scheduleDaysJsonValues[i] || '[]')); - scheduleDays = Array.isArray(parsedDays) ? parsedDays : []; - } catch (_error) { - scheduleDays = []; - } - scheduleDays = scheduleDays - .map(function (value) { return Number(value); }) - .filter(function (value) { return Number.isInteger(value) && value >= 0 && value <= 6; }); - if (!scheduleDays.length) { - return res.status(400).send('Select at least one day for time scheduling.'); - } - scheduleDaysJson = JSON.stringify(Array.from(new Set(scheduleDays)).sort()); - } - - normalizedSlides.push({ - slideId, - position: i, - durationSeconds, - scheduleMode, - scheduleStartDatetime, - scheduleEndDatetime, - scheduleStartTime, - scheduleEndTime, - scheduleDaysJson - }); - } - - if (normalizedSlides.length) { - const [slides] = await connection.query( - `SELECT sl.id, cs.width AS canvas_width, cs.height AS canvas_height - FROM slides sl - LEFT JOIN slide_templates st ON st.id = sl.template_id - LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id - WHERE sl.id IN (?)`, - [normalizedSlides.map(function (item) { return item.slideId; })] - ); - if (slides.length !== normalizedSlides.length) { - return res.status(400).send('One or more selected slides no longer exist.'); - } - const signatures = Array.from(new Set( - slides - .map(function (slide) { return getCanvasSignature(slide.canvas_width, slide.canvas_height); }) - .filter(Boolean) - )); - if (signatures.length > 1) { - return res.status(400).send('All playlist slides must share the same canvas size.'); - } - } - - const actorId = getAuditUserId(req); - - await connection.beginTransaction(); - await connection.query('UPDATE playlists SET name = ?, fade_between_slides = ?, modified_by = ? WHERE id = ?', [name, fadeBetweenSlides, actorId, playlist.id]); - await connection.query('DELETE FROM playlist_slides WHERE playlist_id = ?', [playlist.id]); - for (let i = 0; i < normalizedSlides.length; i += 1) { - const item = normalizedSlides[i]; - await connection.query( - 'INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, schedule_mode, schedule_start_datetime, schedule_end_datetime, schedule_start_time, schedule_end_time, schedule_days_json, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [ - playlist.id, - item.slideId, - item.position, - item.durationSeconds, - item.scheduleMode, - item.scheduleStartDatetime, - item.scheduleEndDatetime, - item.scheduleStartTime, - item.scheduleEndTime, - item.scheduleDaysJson, - actorId, - actorId - ] - ); - } - await connection.commit(); - await notifyPlayerScreens(affectedScreens, 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Playlist updated.')); - } catch (error) { - try { - await connection.rollback(); - } catch (_rollbackError) { - // Ignore rollback failures and surface the original error. - } - next(error); - } finally { - connection.release(); - } - }); - - app.post('/admin/playlists/:id/delete', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - await pool.query('DELETE FROM playlists WHERE id = ?', [playlist.id]); - res.redirect('/admin/playlists?message=' + encodeURIComponent('Playlist deleted.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id/slides', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const slideId = Number(req.body.slide_id); - if (!slideId) { - return res.status(400).send('Slide is required.'); - } - const playlistCanvasSignature = await fetchPlaylistCanvasSignature(pool, playlist.id); - if (playlistCanvasSignature === 'mismatch') { - return res.status(400).send('This playlist already contains slides with different canvas sizes.'); - } - const slide = await common.fetchSlideById(pool, slideId); - if (!slide) { - return res.status(404).send('Slide not found'); - } - const slideCanvasSignature = getCanvasSignature(slide.canvas_width, slide.canvas_height); - if (playlistCanvasSignature && slideCanvasSignature !== playlistCanvasSignature) { - return res.status(400).send('The slide canvas size must match the existing playlist items.'); - } - const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10)); - const [positionRows] = await pool.query('SELECT COALESCE(MAX(position), -1) AS max_position FROM playlist_slides WHERE playlist_id = ?', [playlist.id]); - const nextPosition = Number(positionRows[0].max_position) + 1; - const actorId = getAuditUserId(req); - await pool.query('INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?)', [playlist.id, slideId, nextPosition, durationSeconds, actorId, actorId]); - await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide added to playlist.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id/slides/:playlistSlideId', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const playlistSlideId = Number(req.params.playlistSlideId); - const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10)); - const actorId = getAuditUserId(req); - const [result] = await pool.query( - 'UPDATE playlist_slides SET duration_seconds = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', - [durationSeconds, actorId, playlistSlideId, playlist.id] - ); - if (!result.affectedRows) { - return res.status(404).send('Playlist slide not found'); - } - await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide duration updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id/slides/:playlistSlideId/move', async function (req, res, next) { - const connection = await pool.getConnection(); - try { - const playlist = await common.fetchPlaylistById(connection, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const playlistSlideId = Number(req.params.playlistSlideId); - const direction = String(req.body.direction || '').toLowerCase(); - if (direction !== 'up' && direction !== 'down') { - return res.status(400).send('Invalid move direction.'); - } - - await connection.beginTransaction(); - const orderedSlides = await fetchOrderedPlaylistSlides(connection, playlist.id); - const currentIndex = orderedSlides.findIndex(function (item) { - return Number(item.id) === playlistSlideId; - }); - if (currentIndex === -1) { - await connection.rollback(); - return res.status(404).send('Playlist slide not found'); - } - - const swapIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1; - if (swapIndex < 0 || swapIndex >= orderedSlides.length) { - await connection.rollback(); - return res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide is already at the ' + (direction === 'up' ? 'top' : 'bottom') + '.')); - } - - const currentSlide = orderedSlides[currentIndex]; - const swapSlide = orderedSlides[swapIndex]; - const actorId = getAuditUserId(req); - - await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [swapSlide.position, actorId, currentSlide.id, playlist.id]); - await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [currentSlide.position, actorId, swapSlide.id, playlist.id]); - await connection.commit(); - await notifyPlayerScreens(await fetchScreensByPlaylistId(connection, playlist.id), 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide order updated.')); - } catch (error) { - await connection.rollback(); - next(error); - } finally { - connection.release(); - } - }); - - app.get('/admin/playlists/:id/slides/:playlistSlideId/config', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const data = await common.fetchAdminData(pool); - const playlistSlide = (data.playlistSlides || []).find(function (item) { - return item.id === Number(req.params.playlistSlideId) && item.playlist_id === playlist.id; - }); - if (!playlistSlide) { - return res.status(404).send('Playlist slide not found'); - } - playlistSlide.schedule_days = common.parseJsonSafe(playlistSlide.schedule_days_json) || []; - return res.send(pages.renderPlaylistSlideConfigPage(playlist, playlistSlide, req.query.message ? String(req.query.message) : '', req.query.row_key ? String(req.query.row_key) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id/slides/:playlistSlideId/config', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const rowKey = String(req.body.row_key || '').trim(); - if (rowKey) { - return res.status(400).send('Schedule changes from the playlist editor are staged until you click Save changes.'); - } - const playlistSlideId = Number(req.params.playlistSlideId); - let scheduleMode = normalizeScheduleMode(req.body.schedule_mode); - let scheduleStartDatetime = null; - let scheduleEndDatetime = null; - let scheduleStartTime = null; - let scheduleEndTime = null; - let scheduleDaysJson = null; - - const hasDateRange = Boolean(req.body.schedule_start_datetime && req.body.schedule_end_datetime); - const hasTimeRange = Boolean(req.body.schedule_start_time && req.body.schedule_end_time); - const hasSelectedDays = Boolean(readArrayField(req.body, ['schedule_days', 'schedule_days[]']).length); - - if (scheduleMode === 'dates' && !hasDateRange) { - scheduleMode = 'always'; - } else if (scheduleMode === 'times' && (!hasTimeRange || !hasSelectedDays)) { - scheduleMode = 'always'; - } - - if (scheduleMode === 'dates') { - scheduleStartDatetime = parseDateTimeLocal(req.body.schedule_start_datetime); - scheduleEndDatetime = parseDateTimeLocal(req.body.schedule_end_datetime); - if (!scheduleStartDatetime || !scheduleEndDatetime) { - scheduleMode = 'always'; - scheduleStartDatetime = null; - scheduleEndDatetime = null; - } else if (scheduleEndDatetime < scheduleStartDatetime) { - return res.status(400).send('End datetime must be after start datetime.'); - } - } else if (scheduleMode === 'times') { - scheduleStartTime = parseTimeLocal(req.body.schedule_start_time); - scheduleEndTime = parseTimeLocal(req.body.schedule_end_time); - const scheduleDays = readArrayField(req.body, ['schedule_days', 'schedule_days[]']).map(function (value) { - return Number(value); - }).filter(function (value) { - return Number.isInteger(value) && value >= 0 && value <= 6; - }); - if (!scheduleStartTime || !scheduleEndTime) { - scheduleMode = 'always'; - scheduleStartTime = null; - scheduleEndTime = null; - scheduleDaysJson = null; - } else if (!scheduleDays.length) { - scheduleMode = 'always'; - scheduleStartTime = null; - scheduleEndTime = null; - scheduleDaysJson = null; - } else { - if (scheduleEndTime < scheduleStartTime) { - return res.status(400).send('End time must be after start time.'); - } - scheduleDaysJson = JSON.stringify(Array.from(new Set(scheduleDays)).sort()); - } - } - - const actorId = getAuditUserId(req); - const [result] = await pool.query( - 'UPDATE playlist_slides SET schedule_mode = ?, schedule_start_datetime = ?, schedule_end_datetime = ?, schedule_start_time = ?, schedule_end_time = ?, schedule_days_json = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', - [scheduleMode, scheduleStartDatetime, scheduleEndDatetime, scheduleStartTime, scheduleEndTime, scheduleDaysJson, actorId, playlistSlideId, playlist.id] - ); - if (!result.affectedRows) { - return res.status(404).send('Playlist slide not found'); - } - await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide timings updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/playlists/:id/slides/:playlistSlideId/delete', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - await pool.query('DELETE FROM playlist_slides WHERE id = ? AND playlist_id = ?', [Number(req.params.playlistSlideId), playlist.id]); - await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); - await broadcastDashboardState(); - res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide removed.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/screens', async function (req, res, next) { - try { - const data = await buildDashboardState(pool); - if (req.query.edit) { - const screen = await common.fetchScreenById(pool, Number(req.query.edit)); - if (!screen) { - return res.status(404).send('Screen not found'); - } - const editData = await common.fetchScreenEditData(pool); - return res.send(pages.renderScreenEditPage(screen, editData, req.query.message ? String(req.query.message) : '', req.currentUser)); - } - res.send(pages.renderScreensPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/screens/:id/edit', async function (req, res, next) { - try { - const screen = await common.fetchScreenById(pool, Number(req.params.id)); - if (!screen) { - return res.status(404).send('Screen not found'); - } - const editData = await common.fetchScreenEditData(pool); - return res.send(pages.renderScreenEditPage(screen, editData, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/playlists/:id/edit', async function (req, res, next) { - try { - const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); - if (!playlist) { - return res.status(404).send('Playlist not found'); - } - const data = await common.fetchAdminData(pool); - res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/screens/new', async function (req, res, next) { - try { - const data = await common.fetchScreenEditData(pool); - res.send(pages.renderScreenFormPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/screens', async function (req, res, next) { - try { - const name = String(req.body.name || '').trim(); - if (!name) { - return res.status(400).send('Screen name is required.'); - } - const slugInput = String(req.body.slug || '').trim(); - const playlistId = req.body.playlist_id ? Number(req.body.playlist_id) : null; - const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name)); - const actorId = getAuditUserId(req); - await pool.query('INSERT INTO screens (name, slug, playlist_id, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, slug, playlistId, actorId, actorId]); - res.redirect('/admin/screens?message=' + encodeURIComponent('Screen created.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/screens/:id', async function (req, res, next) { - try { - const name = String(req.body.name || '').trim(); - if (!name) { - return res.status(400).send('Screen name is required.'); - } - const screen = await common.fetchScreenById(pool, Number(req.params.id)); - if (!screen) { - return res.status(404).send('Screen not found'); - } - const slugInput = String(req.body.slug || '').trim(); - const playlistId = req.body.playlist_id ? Number(req.body.playlist_id) : null; - const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name), screen.id); - const previousSlug = String(screen.slug || '').trim(); - await pool.query('UPDATE screens SET name = ?, slug = ?, playlist_id = ?, modified_by = ? WHERE id = ?', [name, slug, playlistId, getAuditUserId(req), screen.id]); - if (previousSlug && previousSlug !== slug) { - await forwardPlayerCommand(previousSlug, { - command: 'redirect', - url: `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(slug)}` - }); - } - res.redirect('/admin/screens?edit=' + screen.id + '&message=' + encodeURIComponent('Screen updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/screens/:id/delete', async function (req, res, next) { - try { - const screen = await common.fetchScreenById(pool, Number(req.params.id)); - if (!screen) { - return res.status(404).send('Screen not found'); - } - await pool.query('DELETE FROM screens WHERE id = ?', [screen.id]); - res.redirect('/admin/screens?message=' + encodeURIComponent('Screen deleted.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/slides', async function (req, res, next) { - try { - const data = await common.fetchAdminData(pool); - res.send(pages.renderSlidesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/slides/new', async function (req, res, next) { - try { - const data = await common.fetchTemplatesData(pool); - res.send(pages.renderSlideFormPage(data, 'create', null, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/slides/:id/edit', async function (req, res, next) { - try { - const slide = await common.fetchSlideById(pool, Number(req.params.id)); - if (!slide) { - return res.status(404).send('Slide not found'); - } - const data = await common.fetchTemplatesData(pool); - res.send(pages.renderSlideFormPage(data, 'edit', slide, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/slides', upload.any(), async function (req, res, next) { - try { - const payload = await common.buildSlidePayload(pool, req, null); - const actorId = getAuditUserId(req); - const [result] = await pool.query( - 'INSERT INTO slides (title, body, template_id, content_json, media_path, media_type, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', - [payload.title, payload.body, payload.templateId, payload.contentJson, payload.mediaPath, payload.mediaType, actorId, actorId] - ); - await syncPlaylistUploadsOnChange({ - key: 'slide:create:' + result.insertId, - pool: pool, - localUploadDir: UPLOAD_DIR, - nextUploadRefs: collectUploadReferencesFromPayload(payload) - }); - res.redirect('/admin/slides/' + result.insertId + '/edit?message=' + encodeURIComponent('Slide created.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/slides/:id', upload.any(), async function (req, res, next) { - try { - const slide = await common.fetchSlideById(pool, Number(req.params.id)); - if (!slide) { - return res.status(404).send('Slide not found'); - } - const affectedScreens = await fetchScreensBySlideId(pool, slide.id); - const existingUploadRefs = collectUploadReferencesFromSlide(slide); - const payload = await common.buildSlidePayload(pool, req, slide); - const nextUploadRefs = collectUploadReferencesFromPayload(payload); - const actorId = getAuditUserId(req); - await pool.query( - 'UPDATE slides SET title = ?, body = ?, template_id = ?, content_json = ?, media_path = ?, media_type = ?, modified_by = ? WHERE id = ?', - [payload.title, payload.body, payload.templateId, payload.contentJson, payload.mediaPath, payload.mediaType, actorId, slide.id] - ); - await syncPlaylistUploadsOnChange({ - key: 'slide:update:' + slide.id, - pool: pool, - localUploadDir: UPLOAD_DIR, - previousUploadRefs: existingUploadRefs, - nextUploadRefs: nextUploadRefs, - blockedSlideIds: [slide.id], - refreshScreenSlugs: affectedScreens - }); - await broadcastDashboardState(); - res.redirect('/admin/slides/' + slide.id + '/edit?message=' + encodeURIComponent('Slide updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/slides/:id/delete', async function (req, res, next) { - try { - const slide = await common.fetchSlideById(pool, Number(req.params.id)); - if (!slide) { - return res.status(404).send('Slide not found'); - } - const affectedScreens = await fetchScreensBySlideId(pool, slide.id); - const uploadRefs = collectUploadReferencesFromSlide(slide); - await pool.query('DELETE FROM slides WHERE id = ?', [slide.id]); - await syncPlaylistUploadsOnChange({ - key: 'slide:delete:' + slide.id, - pool: pool, - localUploadDir: UPLOAD_DIR, - previousUploadRefs: uploadRefs, - blockedSlideIds: [slide.id], - refreshScreenSlugs: affectedScreens - }); - await broadcastDashboardState(); - res.redirect('/admin/slides?message=' + encodeURIComponent('Slide deleted.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/templates', async function (req, res, next) { - try { - const data = await common.fetchTemplatesData(pool); - res.send(pages.renderTemplatesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/templates/new', async function (req, res, next) { - try { - const data = await common.fetchCanvasSizesData(pool); - res.send(pages.renderTemplateFormPage(null, 'create', req.query.message ? String(req.query.message) : '', data.canvasSizes, req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/templates', upload.any(), async function (req, res, next) { - try { - const payload = await common.buildTemplatePayload(pool, req, null); - const actorId = getAuditUserId(req); - const [result] = await pool.query( - 'INSERT INTO slide_templates (name, canvas_size_id, background_image_path, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', - [payload.name, payload.canvasSizeId, payload.backgroundImagePath, actorId, actorId] - ); - for (let i = 0; i < payload.regions.length; i += 1) { - const region = payload.regions[i]; - await pool.query( - 'INSERT INTO slide_template_regions (template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [result.insertId, region.region_key, region.region_type, region.label, region.font_family, region.x, region.y, region.width, region.height, region.z_index, actorId, actorId] - ); - } - await syncPlaylistUploadsOnChange({ - key: 'template:create:' + result.insertId, - pool: pool, - localUploadDir: UPLOAD_DIR, - nextUploadRefs: collectUploadReferencesFromPayload(payload) - }); - res.redirect('/admin/templates/' + result.insertId + '/edit?message=' + encodeURIComponent('Template created.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/templates/:id/edit', async function (req, res, next) { - try { - const template = await common.fetchTemplateById(pool, Number(req.params.id)); - if (!template) { - return res.status(404).send('Template not found'); - } - const sizeData = await common.fetchCanvasSizesData(pool); - res.send(pages.renderTemplateFormPage(template, 'edit', req.query.message ? String(req.query.message) : '', sizeData.canvasSizes, req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/templates/:id', upload.any(), async function (req, res, next) { - try { - const template = await common.fetchTemplateById(pool, Number(req.params.id)); - if (!template) { - return res.status(404).send('Template not found'); - } - const existingUploadRefs = collectUploadReferencesFromTemplate(template); - const payload = await common.buildTemplatePayload(pool, req, template); - const nextUploadRefs = collectUploadReferencesFromPayload(payload); - const affectedScreens = await fetchScreensByTemplateId(pool, template.id); - const actorId = getAuditUserId(req); - await pool.query( - 'UPDATE slide_templates SET name = ?, canvas_size_id = ?, background_image_path = ?, modified_by = ? WHERE id = ?', - [payload.name, payload.canvasSizeId, payload.backgroundImagePath, actorId, template.id] - ); - await pool.query('DELETE FROM slide_template_regions WHERE template_id = ?', [template.id]); - for (let i = 0; i < payload.regions.length; i += 1) { - const region = payload.regions[i]; - await pool.query( - 'INSERT INTO slide_template_regions (template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [template.id, region.region_key, region.region_type, region.label, region.font_family, region.x, region.y, region.width, region.height, region.z_index, actorId, actorId] - ); - } - await syncPlaylistUploadsOnChange({ - key: 'template:update:' + template.id, - pool: pool, - localUploadDir: UPLOAD_DIR, - previousUploadRefs: existingUploadRefs, - nextUploadRefs: nextUploadRefs - }); - await notifyPlayerScreens(affectedScreens, 'refresh'); - res.redirect('/admin/templates/' + template.id + '/edit?message=' + encodeURIComponent('Template updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/templates/:id/delete', async function (req, res, next) { - try { - const template = await common.fetchTemplateById(pool, Number(req.params.id)); - if (!template) { - return res.status(404).send('Template not found'); - } - const uploadRefs = collectUploadReferencesFromTemplate(template); - const affectedScreens = await fetchScreensByTemplateId(pool, template.id); - await pool.query('UPDATE slides SET template_id = NULL, modified_by = ? WHERE template_id = ?', [getAuditUserId(req), template.id]); - await pool.query('DELETE FROM slide_template_regions WHERE template_id = ?', [template.id]); - await pool.query('DELETE FROM slide_templates WHERE id = ?', [template.id]); - await syncPlaylistUploadsOnChange({ - key: 'template:delete:' + template.id, - pool: pool, - localUploadDir: UPLOAD_DIR, - previousUploadRefs: uploadRefs - }); - await notifyPlayerScreens(affectedScreens, 'refresh'); - res.redirect('/admin/templates?message=' + encodeURIComponent('Template deleted.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/canvas-sizes', async function (req, res, next) { - try { - const data = await common.fetchAdminData(pool); - res.send(pages.renderCanvasSizesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.get('/admin/canvas-sizes/new', function (req, res) { - res.send(pages.renderCanvasSizeFormPage(null, 'create', req.query.message ? String(req.query.message) : '', req.currentUser)); - }); - - app.post('/admin/canvas-sizes', async function (req, res, next) { - try { - const payload = common.buildCanvasSizePayload(req, null); - const actorId = getAuditUserId(req); - await pool.query('INSERT INTO canvas_sizes (name, width, height, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [payload.name, payload.width, payload.height, actorId, actorId]); - res.redirect('/admin/canvas-sizes?message=' + encodeURIComponent('Canvas size created.')); - } catch (error) { - next(error); - } - }); - - app.get('/admin/canvas-sizes/:id/edit', async function (req, res, next) { - try { - const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); - if (!canvasSize) { - return res.status(404).send('Canvas size not found'); - } - res.send(pages.renderCanvasSizeEditPage(canvasSize, null, req.query.message ? String(req.query.message) : '', req.currentUser)); - } catch (error) { - next(error); - } - }); - - app.post('/admin/canvas-sizes/:id', async function (req, res, next) { - try { - const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); - if (!canvasSize) { - return res.status(404).send('Canvas size not found'); - } - const payload = common.buildCanvasSizePayload(req, canvasSize); - await pool.query('UPDATE canvas_sizes SET name = ?, width = ?, height = ?, modified_by = ? WHERE id = ?', [payload.name, payload.width, payload.height, getAuditUserId(req), canvasSize.id]); - res.redirect('/admin/canvas-sizes?message=' + encodeURIComponent('Canvas size updated.')); - } catch (error) { - next(error); - } - }); - - app.post('/admin/canvas-sizes/:id/delete', async function (req, res, next) { - try { - const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); - if (!canvasSize) { - return res.status(404).send('Canvas size not found'); - } - await pool.query('UPDATE slide_templates SET canvas_size_id = NULL, modified_by = ? WHERE canvas_size_id = ?', [getAuditUserId(req), canvasSize.id]); - await pool.query('DELETE FROM canvas_sizes WHERE id = ?', [canvasSize.id]); - res.redirect('/admin/canvas-sizes?message=' + encodeURIComponent('Canvas size deleted.')); - } catch (error) { - next(error); - } - }); app.use(function (error, _req, res, _next) { console.error(error); @@ -2230,58 +211,12 @@ async function start() { syncExistingUploadsToPlayer(pool, UPLOAD_DIR).catch(function (error) { console.warn('Unable to sync existing uploads to player:', error); }); - server.on('upgrade', async function (request, socket, head) { - let pathname = ''; - try { - pathname = new URL(request.url, 'http://localhost').pathname; - } catch (_error) { - socket.destroy(); - return; - } - - if (pathname !== '/ws/admin/dashboard') { - socket.destroy(); - return; - } - - try { - const currentUser = await loadCurrentUser(pool, request); - if (!currentUser) { - socket.destroy(); - return; - } - } catch (_error) { - socket.destroy(); - return; - } - - dashboardWs.handleUpgrade(request, socket, head, function (ws) { - dashboardWs.emit('connection', ws, request); - }); - }); - - dashboardWs.on('connection', function (socket) { - dashboardClients.add(socket); - sendDashboardStateToSocket(socket); - - socket.on('close', function () { - dashboardClients.delete(socket); - }); - - socket.on('error', function () { - dashboardClients.delete(socket); - }); - }); + webBootstrap.installDashboardWebsocket(server, loadCurrentUser); server.listen(PORT, function () { console.log(`Pulse Signage app listening on port ${PORT}`); }); - setInterval(function () { - broadcastDashboardState().catch(function (error) { - console.error(error); - }); - }, dashboardRefreshIntervalMs); } module.exports = { start }; diff --git a/src/web/bootstrap.js b/src/web/bootstrap.js new file mode 100644 index 0000000..bb975d3 --- /dev/null +++ b/src/web/bootstrap.js @@ -0,0 +1,208 @@ +const { WebSocketServer, WebSocket } = require('ws'); +const { createDashboardStateService } = require('./dashboard-state'); +const { createUploadSyncService } = require('./upload-sync'); + +function createWebBootstrap(options) { + const pool = options && options.pool; + const common = options && options.common; + const playerInternalBaseUrl = String(options && options.playerInternalBaseUrl || '').replace(/\/$/, ''); + const playerPublicBaseUrl = String(options && options.playerPublicBaseUrl || '').replace(/\/$/, ''); + const uploadDir = String(options && options.uploadDir || '').trim(); + const dashboardRefreshIntervalMs = Number(options && options.dashboardRefreshIntervalMs || 2000); + const formatDashboardDate = options && options.formatDashboardDate; + const notifyPlayerScreens = options && options.notifyPlayerScreens; + + if (!pool || !common || !uploadDir || typeof formatDashboardDate !== 'function' || typeof notifyPlayerScreens !== 'function') { + throw new Error('createWebBootstrap requires the web bootstrap dependencies.'); + } + + const dashboardWs = new WebSocketServer({ noServer: true }); + const dashboardClients = new Set(); + const playerSnapshotCache = new Map(); + const playerSnapshotSockets = new Map(); + let dashboardRefreshInFlight = null; + let broadcastDashboardState = null; + + function getPlayerSnapshotSocketUrl(slug) { + const url = new URL(playerInternalBaseUrl.replace(/^http/, 'ws')); + url.pathname = `/ws/screens/${encodeURIComponent(slug)}/events`; + url.search = ''; + return url.toString(); + } + + function storePlayerSnapshot(slug, connections) { + const normalizedSlug = String(slug || '').trim(); + const normalizedConnections = Array.isArray(connections) ? connections : []; + playerSnapshotCache.set(normalizedSlug, { + slug: normalizedSlug, + count: normalizedConnections.length, + connections: normalizedConnections + }); + } + + function clearPlayerSnapshotSocket(slug) { + const key = String(slug || '').trim(); + playerSnapshotSockets.delete(key); + } + + function ensurePlayerSnapshotSubscription(slug) { + const key = String(slug || '').trim(); + if (!key || playerSnapshotSockets.has(key)) { + return; + } + + const socket = new WebSocket(getPlayerSnapshotSocketUrl(key)); + playerSnapshotSockets.set(key, socket); + + socket.onmessage = function (event) { + try { + const payload = JSON.parse(String(event.data || '{}')); + if (!payload || payload.type !== 'snapshot' || payload.slug !== key) { + return; + } + storePlayerSnapshot(key, payload.connections || []); + if (broadcastDashboardState) { + broadcastDashboardState().catch(function (error) { + console.error(error); + }); + } + } catch (_error) { + // Ignore malformed player snapshot payloads. + } + }; + + socket.onclose = function () { + clearPlayerSnapshotSocket(key); + setTimeout(function () { + ensurePlayerSnapshotSubscription(key); + }, 2000); + }; + + socket.onerror = function () { + try { + socket.close(); + } catch (_error) { + // ignore close errors + } + }; + } + + const dashboardStateService = createDashboardStateService({ + pool: pool, + common: common, + playerSnapshotCache: playerSnapshotCache, + playerSnapshotSockets: playerSnapshotSockets, + ensurePlayerSnapshotSubscription: ensurePlayerSnapshotSubscription, + playerPublicBaseUrl: playerPublicBaseUrl, + formatDashboardDate: formatDashboardDate + }); + const buildDashboardState = dashboardStateService.buildDashboardState; + + const uploadSyncService = createUploadSyncService({ + common: common, + playerInternalBaseUrl: playerInternalBaseUrl, + playerSnapshotCache: playerSnapshotCache, + notifyPlayerScreens: notifyPlayerScreens + }); + + const upload = uploadSyncService.createUploadMiddleware(uploadDir); + const collectUploadReferencesFromSlide = uploadSyncService.collectUploadReferencesFromSlide; + const collectUploadReferencesFromTemplate = uploadSyncService.collectUploadReferencesFromTemplate; + const collectUploadReferencesFromPayload = uploadSyncService.collectUploadReferencesFromPayload; + const syncPlaylistUploadsOnChange = uploadSyncService.syncPlaylistUploadsOnChange; + const syncExistingUploadsToPlayer = uploadSyncService.syncExistingUploadsToPlayer; + + async function sendDashboardStateToSocket(socket) { + if (!socket || socket.readyState !== WebSocket.OPEN) { + return; + } + const state = await buildDashboardState(); + socket.send(JSON.stringify({ type: 'dashboard-state', state: state })); + } + + broadcastDashboardState = async function () { + if (dashboardRefreshInFlight) { + return dashboardRefreshInFlight; + } + + dashboardRefreshInFlight = (async function () { + const state = await buildDashboardState(); + const payload = JSON.stringify({ type: 'dashboard-state', state: state }); + for (const socket of dashboardClients) { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(payload); + } + } + return state; + })().finally(function () { + dashboardRefreshInFlight = null; + }); + + return dashboardRefreshInFlight; + }; + + function installDashboardWebsocket(server, loadCurrentUser) { + server.on('upgrade', async function (request, socket, head) { + let pathname = ''; + try { + pathname = new URL(request.url, 'http://localhost').pathname; + } catch (_error) { + socket.destroy(); + return; + } + + if (pathname !== '/ws/admin/dashboard') { + socket.destroy(); + return; + } + + try { + const currentUser = await loadCurrentUser(pool, request); + if (!currentUser) { + socket.destroy(); + return; + } + } catch (_error) { + socket.destroy(); + return; + } + + dashboardWs.handleUpgrade(request, socket, head, function (ws) { + dashboardWs.emit('connection', ws, request); + }); + }); + + dashboardWs.on('connection', function (socket) { + dashboardClients.add(socket); + sendDashboardStateToSocket(socket); + + socket.on('close', function () { + dashboardClients.delete(socket); + }); + + socket.on('error', function () { + dashboardClients.delete(socket); + }); + }); + + setInterval(function () { + broadcastDashboardState().catch(function (error) { + console.error(error); + }); + }, dashboardRefreshIntervalMs); + } + + return { + upload: upload, + buildDashboardState: buildDashboardState, + collectUploadReferencesFromSlide: collectUploadReferencesFromSlide, + collectUploadReferencesFromTemplate: collectUploadReferencesFromTemplate, + collectUploadReferencesFromPayload: collectUploadReferencesFromPayload, + syncPlaylistUploadsOnChange: syncPlaylistUploadsOnChange, + syncExistingUploadsToPlayer: syncExistingUploadsToPlayer, + broadcastDashboardState: broadcastDashboardState, + installDashboardWebsocket: installDashboardWebsocket + }; +} + +module.exports = { createWebBootstrap }; \ No newline at end of file diff --git a/src/web/dashboard-state.js b/src/web/dashboard-state.js new file mode 100644 index 0000000..1cc0df1 --- /dev/null +++ b/src/web/dashboard-state.js @@ -0,0 +1,112 @@ +const { WebSocket } = require('ws'); + +function normalizeClientName(value) { + return String(value || '').trim(); +} + +function enrichScreensWithConnections(screens, connectionsBySlug, onboardingNameBySlug) { + return (screens || []).map(function (screen) { + const connectionState = connectionsBySlug[screen.slug] || { count: 0, connections: [] }; + return Object.assign({}, screen, { + client_name: onboardingNameBySlug[screen.slug] || screen.client_name || null, + player_connection_count: connectionState.count || 0, + player_connections: Array.isArray(connectionState.connections) ? connectionState.connections : [] + }); + }); +} + +function buildClientRows(screens, connectionsBySlug, onboardingNameBySlug, onboardingNameByDeviceId, playerPublicBaseUrl, formatDashboardDate) { + return (screens || []).flatMap(function (screen) { + const connectionState = connectionsBySlug[screen.slug] || { count: 0, connections: [] }; + return (connectionState.connections || []).map(function (connection) { + const deviceId = String(connection.deviceId || '').trim(); + return Object.assign({}, connection, { + screen_slug: screen.slug, + screen_name: screen.name, + client_name: (deviceId && onboardingNameByDeviceId && onboardingNameByDeviceId[deviceId]) || connection.clientName || onboardingNameBySlug[screen.slug] || String(connection.clientId || '').trim() || null, + playlist_name: screen.playlist_name || null, + connectedAtLabel: formatDashboardDate(connection.connectedAt), + lastSeenAtLabel: formatDashboardDate(connection.lastSeenAt), + player_url: `${playerPublicBaseUrl}/screen/${encodeURIComponent(screen.slug)}` + }); + }); + }); +} + +function createDashboardStateService(options) { + const pool = options && options.pool; + const common = options && options.common; + const playerSnapshotCache = options && options.playerSnapshotCache; + const playerSnapshotSockets = options && options.playerSnapshotSockets; + const ensurePlayerSnapshotSubscription = options && options.ensurePlayerSnapshotSubscription; + const playerPublicBaseUrl = String(options && options.playerPublicBaseUrl || '').replace(/\/$/, ''); + const formatDashboardDate = options && options.formatDashboardDate; + + if (!pool || !common || !playerSnapshotCache || !playerSnapshotSockets || typeof ensurePlayerSnapshotSubscription !== 'function' || typeof formatDashboardDate !== 'function') { + throw new Error('createDashboardStateService requires the dashboard dependencies.'); + } + + async function buildDashboardState() { + const data = await common.fetchAdminData(pool); + const screensData = data.screens || []; + screensData.forEach(function (screen) { + ensurePlayerSnapshotSubscription(screen.slug); + }); + + const [onboardingRows] = await pool.query( + `SELECT s.slug, pod.device_id, pod.client_name + FROM player_onboarding_devices pod + JOIN screens s ON s.id = pod.screen_id + WHERE pod.client_name IS NOT NULL + AND TRIM(pod.client_name) <> ''` + ); + const onboardingNameBySlug = {}; + const onboardingNameByDeviceId = {}; + onboardingRows.forEach(function (row) { + const clientName = normalizeClientName(row.client_name); + const slug = normalizeClientName(row.slug); + const deviceId = normalizeClientName(row.device_id); + if (slug) { + onboardingNameBySlug[slug] = clientName; + } + if (deviceId) { + onboardingNameByDeviceId[deviceId] = clientName; + } + }); + + const connectionsBySlug = {}; + screensData.forEach(function (screen) { + const cached = playerSnapshotCache.get(String(screen.slug || '').trim()); + if (cached && Array.isArray(cached.connections)) { + connectionsBySlug[screen.slug] = cached; + } + }); + + const screens = enrichScreensWithConnections(data.screens || [], connectionsBySlug, onboardingNameBySlug).map(function (screen) { + return Object.assign({}, screen, { + player_url: `${playerPublicBaseUrl}/screen/${encodeURIComponent(screen.slug)}` + }); + }); + const clients = buildClientRows(screens, connectionsBySlug, onboardingNameBySlug, onboardingNameByDeviceId, playerPublicBaseUrl, formatDashboardDate); + const playerServiceConnected = Array.from(playerSnapshotSockets.values()).some(function (socket) { + return socket && socket.readyState === WebSocket.OPEN; + }); + + return { + playlists: data.playlists || [], + screens: screens, + clients: clients, + slides: data.slides || [], + playerServiceConnected: playerServiceConnected, + connectedClientsCount: screens.reduce(function (total, screen) { + return total + Number(screen.player_connection_count || 0); + }, 0) + }; + } + + return { + buildDashboardState: buildDashboardState + }; +} + +module.exports = { createDashboardStateService }; \ No newline at end of file diff --git a/src/web/helpers.js b/src/web/helpers.js new file mode 100644 index 0000000..c5cd080 --- /dev/null +++ b/src/web/helpers.js @@ -0,0 +1,192 @@ +const dashboardDateFormatter = new Intl.DateTimeFormat('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + hour: 'numeric', + minute: '2-digit', + second: '2-digit' +}); + +function normalizeUploadRoot(uploadDir) { + return require('path').resolve(String(uploadDir || '').trim()); +} + +function formatDashboardDate(value) { + if (!value) { + return ''; + } + const date = new Date(value); + if (Number.isNaN(date.getTime())) { + return ''; + } + return dashboardDateFormatter.format(date); +} + +function buildDashboardPayload(state) { + return JSON.stringify({ + type: 'dashboard-state', + state: state + }); +} + +function readArrayField(body, keys) { + const searchKeys = Array.isArray(keys) ? keys : [keys]; + for (let i = 0; i < searchKeys.length; i += 1) { + const key = searchKeys[i]; + const value = body && Object.prototype.hasOwnProperty.call(body, key) ? body[key] : undefined; + if (Array.isArray(value)) { + return value.filter(function (item) { + return item !== undefined && item !== null && String(item).trim() !== ''; + }).map(function (item) { + return String(item); + }); + } + if (value !== undefined && value !== null && String(value).trim() !== '') { + return [String(value)]; + } + } + return []; +} + +function parseDateTimeLocal(value) { + if (!value) { + return null; + } + const date = new Date(String(value)); + return Number.isNaN(date.getTime()) ? null : date; +} + +function parseTimeLocal(value) { + const raw = String(value || '').trim(); + if (!raw) { + return null; + } + if (!/^\d{2}:\d{2}(:\d{2})?$/.test(raw)) { + return null; + } + return raw.length === 5 ? raw + ':00' : raw; +} + +function normalizeScheduleMode(value) { + const mode = String(value || 'always'); + if (mode === 'dates' || mode === 'times') { + return mode; + } + return 'always'; +} + +function getAuditUserId(req) { + return req && req.currentUser ? Number(req.currentUser.id) : null; +} + +function getCanvasSignature(width, height) { + const normalizedWidth = Number(width); + const normalizedHeight = Number(height); + if (!Number.isFinite(normalizedWidth) || !Number.isFinite(normalizedHeight)) { + return null; + } + return normalizedWidth + 'x' + normalizedHeight; +} + +async function fetchPlaylistCanvasSignature(pool, playlistId) { + const [rows] = await pool.query( + `SELECT DISTINCT cs.width AS canvas_width, cs.height AS canvas_height + FROM playlist_slides ps + JOIN slides sl ON sl.id = ps.slide_id + LEFT JOIN slide_templates st ON st.id = sl.template_id + LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id + WHERE ps.playlist_id = ? + AND cs.width IS NOT NULL + AND cs.height IS NOT NULL`, + [playlistId] + ); + const signatures = Array.from(new Set(rows.map(function (row) { + return getCanvasSignature(row.canvas_width, row.canvas_height); + }).filter(Boolean))); + if (!signatures.length) { + return null; + } + return signatures.length === 1 ? signatures[0] : 'mismatch'; +} + +async function fetchScreensByPlaylistId(connection, playlistId) { + const [rows] = await connection.query( + 'SELECT slug FROM screens WHERE playlist_id = ? AND slug IS NOT NULL', + [playlistId] + ); + return rows.map(function (row) { + return row.slug; + }); +} + +async function fetchScreensBySlideId(connection, slideId) { + const [rows] = await connection.query( + `SELECT DISTINCT s.slug + FROM screens s + JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id + WHERE ps.slide_id = ? + AND s.slug IS NOT NULL`, + [slideId] + ); + return rows.map(function (row) { + return row.slug; + }); +} + +async function fetchScreensByTemplateId(connection, templateId) { + const [rows] = await connection.query( + `SELECT DISTINCT s.slug + FROM screens s + JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id + JOIN slides sl ON sl.id = ps.slide_id + WHERE sl.template_id = ? + AND s.slug IS NOT NULL`, + [templateId] + ); + return rows.map(function (row) { + return row.slug; + }); +} + +async function fetchOrderedPlaylistSlides(connection, playlistId) { + const [rows] = await connection.query( + 'SELECT id, position FROM playlist_slides WHERE playlist_id = ? ORDER BY position ASC, id ASC', + [playlistId] + ); + return rows; +} + +function redirectAfterSave(req, res, defaultUrl, options) { + const safeOptions = options || {}; + const action = String((req && req.body && req.body.action) || req.query.action || '').toLowerCase(); + if (action === 'close') { + return res.redirect(safeOptions.closeUrl || defaultUrl); + } + if (action === 'new') { + return res.redirect(safeOptions.newUrl || defaultUrl); + } + const message = safeOptions.message || ''; + if (message) { + const joiner = defaultUrl.indexOf('?') === -1 ? '?' : '&'; + return res.redirect(defaultUrl + joiner + 'message=' + encodeURIComponent(message)); + } + return res.redirect(defaultUrl); +} + +module.exports = { + normalizeUploadRoot: normalizeUploadRoot, + formatDashboardDate: formatDashboardDate, + buildDashboardPayload: buildDashboardPayload, + readArrayField: readArrayField, + parseDateTimeLocal: parseDateTimeLocal, + parseTimeLocal: parseTimeLocal, + normalizeScheduleMode: normalizeScheduleMode, + getAuditUserId: getAuditUserId, + getCanvasSignature: getCanvasSignature, + fetchPlaylistCanvasSignature: fetchPlaylistCanvasSignature, + fetchScreensByPlaylistId: fetchScreensByPlaylistId, + fetchScreensBySlideId: fetchScreensBySlideId, + fetchScreensByTemplateId: fetchScreensByTemplateId, + fetchOrderedPlaylistSlides: fetchOrderedPlaylistSlides, + redirectAfterSave: redirectAfterSave +}; \ No newline at end of file diff --git a/src/web/player-actions.js b/src/web/player-actions.js new file mode 100644 index 0000000..e1bbc58 --- /dev/null +++ b/src/web/player-actions.js @@ -0,0 +1,72 @@ +function createPlayerActionService(options) { + const playerInternalBaseUrl = String(options && options.playerInternalBaseUrl || '').replace(/\/$/, ''); + const common = options && options.common; + + if (!playerInternalBaseUrl || !common) { + throw new Error('createPlayerActionService requires the player action dependencies.'); + } + + async function forwardPlayerCommand(slug, commandOrPayload, connectionId) { + const payload = typeof commandOrPayload === 'object' && commandOrPayload !== null + ? Object.assign({}, commandOrPayload) + : { command: commandOrPayload }; + if (connectionId) { + payload.connectionId = connectionId; + } + const response = await fetch(`${playerInternalBaseUrl}/api/screens/${encodeURIComponent(slug)}/commands`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + const errorText = await response.text().catch(function () { return ''; }); + const error = new Error(errorText || `Unable to send command to player ${slug}.`); + error.statusCode = response.status; + throw error; + } + + return response.json().catch(function () { + return { ok: true }; + }); + } + + async function getScreenDeleteBlockMessage(pool, screen) { + const [rows] = await pool.query('SELECT COUNT(*) AS ref_count FROM player_onboarding_devices WHERE screen_id = ?', [screen.id]); + return Number(rows[0] && rows[0].ref_count) > 0 ? 'This screen is still linked to onboarding devices.' : ''; + } + + async function getSlideDeleteBlockMessage(pool, slide) { + const [rows] = await pool.query('SELECT COUNT(*) AS ref_count FROM playlist_slides WHERE slide_id = ?', [slide.id]); + return Number(rows[0] && rows[0].ref_count) > 0 ? 'This slide is still used by one or more playlists.' : ''; + } + + async function getTemplateDeleteBlockMessage(pool, template) { + const [rows] = await pool.query('SELECT COUNT(*) AS ref_count FROM slides WHERE template_id = ?', [template.id]); + return Number(rows[0] && rows[0].ref_count) > 0 ? 'This template is still used by one or more slides.' : ''; + } + + async function getCanvasSizeDeleteBlockMessage(pool, canvasSize) { + const [rows] = await pool.query('SELECT COUNT(*) AS ref_count FROM slide_templates WHERE canvas_size_id = ?', [canvasSize.id]); + return Number(rows[0] && rows[0].ref_count) > 0 ? 'This canvas size is still used by one or more templates.' : ''; + } + + async function getPlaylistDeleteBlockMessage(pool, playlist) { + const [rows] = await pool.query('SELECT COUNT(*) AS ref_count FROM screens WHERE playlist_id = ?', [playlist.id]); + return Number(rows[0] && rows[0].ref_count) > 0 ? 'This playlist is still assigned to one or more screens.' : ''; + } + + return { + forwardPlayerCommand: forwardPlayerCommand, + getScreenDeleteBlockMessage: getScreenDeleteBlockMessage, + getSlideDeleteBlockMessage: getSlideDeleteBlockMessage, + getTemplateDeleteBlockMessage: getTemplateDeleteBlockMessage, + getCanvasSizeDeleteBlockMessage: getCanvasSizeDeleteBlockMessage, + getPlaylistDeleteBlockMessage: getPlaylistDeleteBlockMessage + }; +} + +module.exports = { createPlayerActionService }; \ No newline at end of file diff --git a/src/web/public/adminlte/bootstrap-icons/css/bootstrap-icons.min.css b/src/web/public/adminlte/bootstrap-icons/css/bootstrap-icons.min.css new file mode 100644 index 0000000..dadd6dc --- /dev/null +++ b/src/web/public/adminlte/bootstrap-icons/css/bootstrap-icons.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap Icons v1.11.3 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */@font-face{font-display:block;font-family:bootstrap-icons;src:url("fonts/bootstrap-icons.woff2?dd67030699838ea613ee6dbda90effa6") format("woff2"),url("fonts/bootstrap-icons.woff?dd67030699838ea613ee6dbda90effa6") format("woff")}.bi::before,[class*=" bi-"]::before,[class^=bi-]::before{display:inline-block;font-family:bootstrap-icons!important;font-style:normal;font-weight:400!important;font-variant:normal;text-transform:none;line-height:1;vertical-align:-.125em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.bi-123::before{content:"\f67f"}.bi-alarm-fill::before{content:"\f101"}.bi-alarm::before{content:"\f102"}.bi-align-bottom::before{content:"\f103"}.bi-align-center::before{content:"\f104"}.bi-align-end::before{content:"\f105"}.bi-align-middle::before{content:"\f106"}.bi-align-start::before{content:"\f107"}.bi-align-top::before{content:"\f108"}.bi-alt::before{content:"\f109"}.bi-app-indicator::before{content:"\f10a"}.bi-app::before{content:"\f10b"}.bi-archive-fill::before{content:"\f10c"}.bi-archive::before{content:"\f10d"}.bi-arrow-90deg-down::before{content:"\f10e"}.bi-arrow-90deg-left::before{content:"\f10f"}.bi-arrow-90deg-right::before{content:"\f110"}.bi-arrow-90deg-up::before{content:"\f111"}.bi-arrow-bar-down::before{content:"\f112"}.bi-arrow-bar-left::before{content:"\f113"}.bi-arrow-bar-right::before{content:"\f114"}.bi-arrow-bar-up::before{content:"\f115"}.bi-arrow-clockwise::before{content:"\f116"}.bi-arrow-counterclockwise::before{content:"\f117"}.bi-arrow-down-circle-fill::before{content:"\f118"}.bi-arrow-down-circle::before{content:"\f119"}.bi-arrow-down-left-circle-fill::before{content:"\f11a"}.bi-arrow-down-left-circle::before{content:"\f11b"}.bi-arrow-down-left-square-fill::before{content:"\f11c"}.bi-arrow-down-left-square::before{content:"\f11d"}.bi-arrow-down-left::before{content:"\f11e"}.bi-arrow-down-right-circle-fill::before{content:"\f11f"}.bi-arrow-down-right-circle::before{content:"\f120"}.bi-arrow-down-right-square-fill::before{content:"\f121"}.bi-arrow-down-right-square::before{content:"\f122"}.bi-arrow-down-right::before{content:"\f123"}.bi-arrow-down-short::before{content:"\f124"}.bi-arrow-down-square-fill::before{content:"\f125"}.bi-arrow-down-square::before{content:"\f126"}.bi-arrow-down-up::before{content:"\f127"}.bi-arrow-down::before{content:"\f128"}.bi-arrow-left-circle-fill::before{content:"\f129"}.bi-arrow-left-circle::before{content:"\f12a"}.bi-arrow-left-right::before{content:"\f12b"}.bi-arrow-left-short::before{content:"\f12c"}.bi-arrow-left-square-fill::before{content:"\f12d"}.bi-arrow-left-square::before{content:"\f12e"}.bi-arrow-left::before{content:"\f12f"}.bi-arrow-repeat::before{content:"\f130"}.bi-arrow-return-left::before{content:"\f131"}.bi-arrow-return-right::before{content:"\f132"}.bi-arrow-right-circle-fill::before{content:"\f133"}.bi-arrow-right-circle::before{content:"\f134"}.bi-arrow-right-short::before{content:"\f135"}.bi-arrow-right-square-fill::before{content:"\f136"}.bi-arrow-right-square::before{content:"\f137"}.bi-arrow-right::before{content:"\f138"}.bi-arrow-up-circle-fill::before{content:"\f139"}.bi-arrow-up-circle::before{content:"\f13a"}.bi-arrow-up-left-circle-fill::before{content:"\f13b"}.bi-arrow-up-left-circle::before{content:"\f13c"}.bi-arrow-up-left-square-fill::before{content:"\f13d"}.bi-arrow-up-left-square::before{content:"\f13e"}.bi-arrow-up-left::before{content:"\f13f"}.bi-arrow-up-right-circle-fill::before{content:"\f140"}.bi-arrow-up-right-circle::before{content:"\f141"}.bi-arrow-up-right-square-fill::before{content:"\f142"}.bi-arrow-up-right-square::before{content:"\f143"}.bi-arrow-up-right::before{content:"\f144"}.bi-arrow-up-short::before{content:"\f145"}.bi-arrow-up-square-fill::before{content:"\f146"}.bi-arrow-up-square::before{content:"\f147"}.bi-arrow-up::before{content:"\f148"}.bi-arrows-angle-contract::before{content:"\f149"}.bi-arrows-angle-expand::before{content:"\f14a"}.bi-arrows-collapse::before{content:"\f14b"}.bi-arrows-expand::before{content:"\f14c"}.bi-arrows-fullscreen::before{content:"\f14d"}.bi-arrows-move::before{content:"\f14e"}.bi-aspect-ratio-fill::before{content:"\f14f"}.bi-aspect-ratio::before{content:"\f150"}.bi-asterisk::before{content:"\f151"}.bi-at::before{content:"\f152"}.bi-award-fill::before{content:"\f153"}.bi-award::before{content:"\f154"}.bi-back::before{content:"\f155"}.bi-backspace-fill::before{content:"\f156"}.bi-backspace-reverse-fill::before{content:"\f157"}.bi-backspace-reverse::before{content:"\f158"}.bi-backspace::before{content:"\f159"}.bi-badge-3d-fill::before{content:"\f15a"}.bi-badge-3d::before{content:"\f15b"}.bi-badge-4k-fill::before{content:"\f15c"}.bi-badge-4k::before{content:"\f15d"}.bi-badge-8k-fill::before{content:"\f15e"}.bi-badge-8k::before{content:"\f15f"}.bi-badge-ad-fill::before{content:"\f160"}.bi-badge-ad::before{content:"\f161"}.bi-badge-ar-fill::before{content:"\f162"}.bi-badge-ar::before{content:"\f163"}.bi-badge-cc-fill::before{content:"\f164"}.bi-badge-cc::before{content:"\f165"}.bi-badge-hd-fill::before{content:"\f166"}.bi-badge-hd::before{content:"\f167"}.bi-badge-tm-fill::before{content:"\f168"}.bi-badge-tm::before{content:"\f169"}.bi-badge-vo-fill::before{content:"\f16a"}.bi-badge-vo::before{content:"\f16b"}.bi-badge-vr-fill::before{content:"\f16c"}.bi-badge-vr::before{content:"\f16d"}.bi-badge-wc-fill::before{content:"\f16e"}.bi-badge-wc::before{content:"\f16f"}.bi-bag-check-fill::before{content:"\f170"}.bi-bag-check::before{content:"\f171"}.bi-bag-dash-fill::before{content:"\f172"}.bi-bag-dash::before{content:"\f173"}.bi-bag-fill::before{content:"\f174"}.bi-bag-plus-fill::before{content:"\f175"}.bi-bag-plus::before{content:"\f176"}.bi-bag-x-fill::before{content:"\f177"}.bi-bag-x::before{content:"\f178"}.bi-bag::before{content:"\f179"}.bi-bar-chart-fill::before{content:"\f17a"}.bi-bar-chart-line-fill::before{content:"\f17b"}.bi-bar-chart-line::before{content:"\f17c"}.bi-bar-chart-steps::before{content:"\f17d"}.bi-bar-chart::before{content:"\f17e"}.bi-basket-fill::before{content:"\f17f"}.bi-basket::before{content:"\f180"}.bi-basket2-fill::before{content:"\f181"}.bi-basket2::before{content:"\f182"}.bi-basket3-fill::before{content:"\f183"}.bi-basket3::before{content:"\f184"}.bi-battery-charging::before{content:"\f185"}.bi-battery-full::before{content:"\f186"}.bi-battery-half::before{content:"\f187"}.bi-battery::before{content:"\f188"}.bi-bell-fill::before{content:"\f189"}.bi-bell::before{content:"\f18a"}.bi-bezier::before{content:"\f18b"}.bi-bezier2::before{content:"\f18c"}.bi-bicycle::before{content:"\f18d"}.bi-binoculars-fill::before{content:"\f18e"}.bi-binoculars::before{content:"\f18f"}.bi-blockquote-left::before{content:"\f190"}.bi-blockquote-right::before{content:"\f191"}.bi-book-fill::before{content:"\f192"}.bi-book-half::before{content:"\f193"}.bi-book::before{content:"\f194"}.bi-bookmark-check-fill::before{content:"\f195"}.bi-bookmark-check::before{content:"\f196"}.bi-bookmark-dash-fill::before{content:"\f197"}.bi-bookmark-dash::before{content:"\f198"}.bi-bookmark-fill::before{content:"\f199"}.bi-bookmark-heart-fill::before{content:"\f19a"}.bi-bookmark-heart::before{content:"\f19b"}.bi-bookmark-plus-fill::before{content:"\f19c"}.bi-bookmark-plus::before{content:"\f19d"}.bi-bookmark-star-fill::before{content:"\f19e"}.bi-bookmark-star::before{content:"\f19f"}.bi-bookmark-x-fill::before{content:"\f1a0"}.bi-bookmark-x::before{content:"\f1a1"}.bi-bookmark::before{content:"\f1a2"}.bi-bookmarks-fill::before{content:"\f1a3"}.bi-bookmarks::before{content:"\f1a4"}.bi-bookshelf::before{content:"\f1a5"}.bi-bootstrap-fill::before{content:"\f1a6"}.bi-bootstrap-reboot::before{content:"\f1a7"}.bi-bootstrap::before{content:"\f1a8"}.bi-border-all::before{content:"\f1a9"}.bi-border-bottom::before{content:"\f1aa"}.bi-border-center::before{content:"\f1ab"}.bi-border-inner::before{content:"\f1ac"}.bi-border-left::before{content:"\f1ad"}.bi-border-middle::before{content:"\f1ae"}.bi-border-outer::before{content:"\f1af"}.bi-border-right::before{content:"\f1b0"}.bi-border-style::before{content:"\f1b1"}.bi-border-top::before{content:"\f1b2"}.bi-border-width::before{content:"\f1b3"}.bi-border::before{content:"\f1b4"}.bi-bounding-box-circles::before{content:"\f1b5"}.bi-bounding-box::before{content:"\f1b6"}.bi-box-arrow-down-left::before{content:"\f1b7"}.bi-box-arrow-down-right::before{content:"\f1b8"}.bi-box-arrow-down::before{content:"\f1b9"}.bi-box-arrow-in-down-left::before{content:"\f1ba"}.bi-box-arrow-in-down-right::before{content:"\f1bb"}.bi-box-arrow-in-down::before{content:"\f1bc"}.bi-box-arrow-in-left::before{content:"\f1bd"}.bi-box-arrow-in-right::before{content:"\f1be"}.bi-box-arrow-in-up-left::before{content:"\f1bf"}.bi-box-arrow-in-up-right::before{content:"\f1c0"}.bi-box-arrow-in-up::before{content:"\f1c1"}.bi-box-arrow-left::before{content:"\f1c2"}.bi-box-arrow-right::before{content:"\f1c3"}.bi-box-arrow-up-left::before{content:"\f1c4"}.bi-box-arrow-up-right::before{content:"\f1c5"}.bi-box-arrow-up::before{content:"\f1c6"}.bi-box-seam::before{content:"\f1c7"}.bi-box::before{content:"\f1c8"}.bi-braces::before{content:"\f1c9"}.bi-bricks::before{content:"\f1ca"}.bi-briefcase-fill::before{content:"\f1cb"}.bi-briefcase::before{content:"\f1cc"}.bi-brightness-alt-high-fill::before{content:"\f1cd"}.bi-brightness-alt-high::before{content:"\f1ce"}.bi-brightness-alt-low-fill::before{content:"\f1cf"}.bi-brightness-alt-low::before{content:"\f1d0"}.bi-brightness-high-fill::before{content:"\f1d1"}.bi-brightness-high::before{content:"\f1d2"}.bi-brightness-low-fill::before{content:"\f1d3"}.bi-brightness-low::before{content:"\f1d4"}.bi-broadcast-pin::before{content:"\f1d5"}.bi-broadcast::before{content:"\f1d6"}.bi-brush-fill::before{content:"\f1d7"}.bi-brush::before{content:"\f1d8"}.bi-bucket-fill::before{content:"\f1d9"}.bi-bucket::before{content:"\f1da"}.bi-bug-fill::before{content:"\f1db"}.bi-bug::before{content:"\f1dc"}.bi-building::before{content:"\f1dd"}.bi-bullseye::before{content:"\f1de"}.bi-calculator-fill::before{content:"\f1df"}.bi-calculator::before{content:"\f1e0"}.bi-calendar-check-fill::before{content:"\f1e1"}.bi-calendar-check::before{content:"\f1e2"}.bi-calendar-date-fill::before{content:"\f1e3"}.bi-calendar-date::before{content:"\f1e4"}.bi-calendar-day-fill::before{content:"\f1e5"}.bi-calendar-day::before{content:"\f1e6"}.bi-calendar-event-fill::before{content:"\f1e7"}.bi-calendar-event::before{content:"\f1e8"}.bi-calendar-fill::before{content:"\f1e9"}.bi-calendar-minus-fill::before{content:"\f1ea"}.bi-calendar-minus::before{content:"\f1eb"}.bi-calendar-month-fill::before{content:"\f1ec"}.bi-calendar-month::before{content:"\f1ed"}.bi-calendar-plus-fill::before{content:"\f1ee"}.bi-calendar-plus::before{content:"\f1ef"}.bi-calendar-range-fill::before{content:"\f1f0"}.bi-calendar-range::before{content:"\f1f1"}.bi-calendar-week-fill::before{content:"\f1f2"}.bi-calendar-week::before{content:"\f1f3"}.bi-calendar-x-fill::before{content:"\f1f4"}.bi-calendar-x::before{content:"\f1f5"}.bi-calendar::before{content:"\f1f6"}.bi-calendar2-check-fill::before{content:"\f1f7"}.bi-calendar2-check::before{content:"\f1f8"}.bi-calendar2-date-fill::before{content:"\f1f9"}.bi-calendar2-date::before{content:"\f1fa"}.bi-calendar2-day-fill::before{content:"\f1fb"}.bi-calendar2-day::before{content:"\f1fc"}.bi-calendar2-event-fill::before{content:"\f1fd"}.bi-calendar2-event::before{content:"\f1fe"}.bi-calendar2-fill::before{content:"\f1ff"}.bi-calendar2-minus-fill::before{content:"\f200"}.bi-calendar2-minus::before{content:"\f201"}.bi-calendar2-month-fill::before{content:"\f202"}.bi-calendar2-month::before{content:"\f203"}.bi-calendar2-plus-fill::before{content:"\f204"}.bi-calendar2-plus::before{content:"\f205"}.bi-calendar2-range-fill::before{content:"\f206"}.bi-calendar2-range::before{content:"\f207"}.bi-calendar2-week-fill::before{content:"\f208"}.bi-calendar2-week::before{content:"\f209"}.bi-calendar2-x-fill::before{content:"\f20a"}.bi-calendar2-x::before{content:"\f20b"}.bi-calendar2::before{content:"\f20c"}.bi-calendar3-event-fill::before{content:"\f20d"}.bi-calendar3-event::before{content:"\f20e"}.bi-calendar3-fill::before{content:"\f20f"}.bi-calendar3-range-fill::before{content:"\f210"}.bi-calendar3-range::before{content:"\f211"}.bi-calendar3-week-fill::before{content:"\f212"}.bi-calendar3-week::before{content:"\f213"}.bi-calendar3::before{content:"\f214"}.bi-calendar4-event::before{content:"\f215"}.bi-calendar4-range::before{content:"\f216"}.bi-calendar4-week::before{content:"\f217"}.bi-calendar4::before{content:"\f218"}.bi-camera-fill::before{content:"\f219"}.bi-camera-reels-fill::before{content:"\f21a"}.bi-camera-reels::before{content:"\f21b"}.bi-camera-video-fill::before{content:"\f21c"}.bi-camera-video-off-fill::before{content:"\f21d"}.bi-camera-video-off::before{content:"\f21e"}.bi-camera-video::before{content:"\f21f"}.bi-camera::before{content:"\f220"}.bi-camera2::before{content:"\f221"}.bi-capslock-fill::before{content:"\f222"}.bi-capslock::before{content:"\f223"}.bi-card-checklist::before{content:"\f224"}.bi-card-heading::before{content:"\f225"}.bi-card-image::before{content:"\f226"}.bi-card-list::before{content:"\f227"}.bi-card-text::before{content:"\f228"}.bi-caret-down-fill::before{content:"\f229"}.bi-caret-down-square-fill::before{content:"\f22a"}.bi-caret-down-square::before{content:"\f22b"}.bi-caret-down::before{content:"\f22c"}.bi-caret-left-fill::before{content:"\f22d"}.bi-caret-left-square-fill::before{content:"\f22e"}.bi-caret-left-square::before{content:"\f22f"}.bi-caret-left::before{content:"\f230"}.bi-caret-right-fill::before{content:"\f231"}.bi-caret-right-square-fill::before{content:"\f232"}.bi-caret-right-square::before{content:"\f233"}.bi-caret-right::before{content:"\f234"}.bi-caret-up-fill::before{content:"\f235"}.bi-caret-up-square-fill::before{content:"\f236"}.bi-caret-up-square::before{content:"\f237"}.bi-caret-up::before{content:"\f238"}.bi-cart-check-fill::before{content:"\f239"}.bi-cart-check::before{content:"\f23a"}.bi-cart-dash-fill::before{content:"\f23b"}.bi-cart-dash::before{content:"\f23c"}.bi-cart-fill::before{content:"\f23d"}.bi-cart-plus-fill::before{content:"\f23e"}.bi-cart-plus::before{content:"\f23f"}.bi-cart-x-fill::before{content:"\f240"}.bi-cart-x::before{content:"\f241"}.bi-cart::before{content:"\f242"}.bi-cart2::before{content:"\f243"}.bi-cart3::before{content:"\f244"}.bi-cart4::before{content:"\f245"}.bi-cash-stack::before{content:"\f246"}.bi-cash::before{content:"\f247"}.bi-cast::before{content:"\f248"}.bi-chat-dots-fill::before{content:"\f249"}.bi-chat-dots::before{content:"\f24a"}.bi-chat-fill::before{content:"\f24b"}.bi-chat-left-dots-fill::before{content:"\f24c"}.bi-chat-left-dots::before{content:"\f24d"}.bi-chat-left-fill::before{content:"\f24e"}.bi-chat-left-quote-fill::before{content:"\f24f"}.bi-chat-left-quote::before{content:"\f250"}.bi-chat-left-text-fill::before{content:"\f251"}.bi-chat-left-text::before{content:"\f252"}.bi-chat-left::before{content:"\f253"}.bi-chat-quote-fill::before{content:"\f254"}.bi-chat-quote::before{content:"\f255"}.bi-chat-right-dots-fill::before{content:"\f256"}.bi-chat-right-dots::before{content:"\f257"}.bi-chat-right-fill::before{content:"\f258"}.bi-chat-right-quote-fill::before{content:"\f259"}.bi-chat-right-quote::before{content:"\f25a"}.bi-chat-right-text-fill::before{content:"\f25b"}.bi-chat-right-text::before{content:"\f25c"}.bi-chat-right::before{content:"\f25d"}.bi-chat-square-dots-fill::before{content:"\f25e"}.bi-chat-square-dots::before{content:"\f25f"}.bi-chat-square-fill::before{content:"\f260"}.bi-chat-square-quote-fill::before{content:"\f261"}.bi-chat-square-quote::before{content:"\f262"}.bi-chat-square-text-fill::before{content:"\f263"}.bi-chat-square-text::before{content:"\f264"}.bi-chat-square::before{content:"\f265"}.bi-chat-text-fill::before{content:"\f266"}.bi-chat-text::before{content:"\f267"}.bi-chat::before{content:"\f268"}.bi-check-all::before{content:"\f269"}.bi-check-circle-fill::before{content:"\f26a"}.bi-check-circle::before{content:"\f26b"}.bi-check-square-fill::before{content:"\f26c"}.bi-check-square::before{content:"\f26d"}.bi-check::before{content:"\f26e"}.bi-check2-all::before{content:"\f26f"}.bi-check2-circle::before{content:"\f270"}.bi-check2-square::before{content:"\f271"}.bi-check2::before{content:"\f272"}.bi-chevron-bar-contract::before{content:"\f273"}.bi-chevron-bar-down::before{content:"\f274"}.bi-chevron-bar-expand::before{content:"\f275"}.bi-chevron-bar-left::before{content:"\f276"}.bi-chevron-bar-right::before{content:"\f277"}.bi-chevron-bar-up::before{content:"\f278"}.bi-chevron-compact-down::before{content:"\f279"}.bi-chevron-compact-left::before{content:"\f27a"}.bi-chevron-compact-right::before{content:"\f27b"}.bi-chevron-compact-up::before{content:"\f27c"}.bi-chevron-contract::before{content:"\f27d"}.bi-chevron-double-down::before{content:"\f27e"}.bi-chevron-double-left::before{content:"\f27f"}.bi-chevron-double-right::before{content:"\f280"}.bi-chevron-double-up::before{content:"\f281"}.bi-chevron-down::before{content:"\f282"}.bi-chevron-expand::before{content:"\f283"}.bi-chevron-left::before{content:"\f284"}.bi-chevron-right::before{content:"\f285"}.bi-chevron-up::before{content:"\f286"}.bi-circle-fill::before{content:"\f287"}.bi-circle-half::before{content:"\f288"}.bi-circle-square::before{content:"\f289"}.bi-circle::before{content:"\f28a"}.bi-clipboard-check::before{content:"\f28b"}.bi-clipboard-data::before{content:"\f28c"}.bi-clipboard-minus::before{content:"\f28d"}.bi-clipboard-plus::before{content:"\f28e"}.bi-clipboard-x::before{content:"\f28f"}.bi-clipboard::before{content:"\f290"}.bi-clock-fill::before{content:"\f291"}.bi-clock-history::before{content:"\f292"}.bi-clock::before{content:"\f293"}.bi-cloud-arrow-down-fill::before{content:"\f294"}.bi-cloud-arrow-down::before{content:"\f295"}.bi-cloud-arrow-up-fill::before{content:"\f296"}.bi-cloud-arrow-up::before{content:"\f297"}.bi-cloud-check-fill::before{content:"\f298"}.bi-cloud-check::before{content:"\f299"}.bi-cloud-download-fill::before{content:"\f29a"}.bi-cloud-download::before{content:"\f29b"}.bi-cloud-drizzle-fill::before{content:"\f29c"}.bi-cloud-drizzle::before{content:"\f29d"}.bi-cloud-fill::before{content:"\f29e"}.bi-cloud-fog-fill::before{content:"\f29f"}.bi-cloud-fog::before{content:"\f2a0"}.bi-cloud-fog2-fill::before{content:"\f2a1"}.bi-cloud-fog2::before{content:"\f2a2"}.bi-cloud-hail-fill::before{content:"\f2a3"}.bi-cloud-hail::before{content:"\f2a4"}.bi-cloud-haze-fill::before{content:"\f2a6"}.bi-cloud-haze::before{content:"\f2a7"}.bi-cloud-haze2-fill::before{content:"\f2a8"}.bi-cloud-lightning-fill::before{content:"\f2a9"}.bi-cloud-lightning-rain-fill::before{content:"\f2aa"}.bi-cloud-lightning-rain::before{content:"\f2ab"}.bi-cloud-lightning::before{content:"\f2ac"}.bi-cloud-minus-fill::before{content:"\f2ad"}.bi-cloud-minus::before{content:"\f2ae"}.bi-cloud-moon-fill::before{content:"\f2af"}.bi-cloud-moon::before{content:"\f2b0"}.bi-cloud-plus-fill::before{content:"\f2b1"}.bi-cloud-plus::before{content:"\f2b2"}.bi-cloud-rain-fill::before{content:"\f2b3"}.bi-cloud-rain-heavy-fill::before{content:"\f2b4"}.bi-cloud-rain-heavy::before{content:"\f2b5"}.bi-cloud-rain::before{content:"\f2b6"}.bi-cloud-slash-fill::before{content:"\f2b7"}.bi-cloud-slash::before{content:"\f2b8"}.bi-cloud-sleet-fill::before{content:"\f2b9"}.bi-cloud-sleet::before{content:"\f2ba"}.bi-cloud-snow-fill::before{content:"\f2bb"}.bi-cloud-snow::before{content:"\f2bc"}.bi-cloud-sun-fill::before{content:"\f2bd"}.bi-cloud-sun::before{content:"\f2be"}.bi-cloud-upload-fill::before{content:"\f2bf"}.bi-cloud-upload::before{content:"\f2c0"}.bi-cloud::before{content:"\f2c1"}.bi-clouds-fill::before{content:"\f2c2"}.bi-clouds::before{content:"\f2c3"}.bi-cloudy-fill::before{content:"\f2c4"}.bi-cloudy::before{content:"\f2c5"}.bi-code-slash::before{content:"\f2c6"}.bi-code-square::before{content:"\f2c7"}.bi-code::before{content:"\f2c8"}.bi-collection-fill::before{content:"\f2c9"}.bi-collection-play-fill::before{content:"\f2ca"}.bi-collection-play::before{content:"\f2cb"}.bi-collection::before{content:"\f2cc"}.bi-columns-gap::before{content:"\f2cd"}.bi-columns::before{content:"\f2ce"}.bi-command::before{content:"\f2cf"}.bi-compass-fill::before{content:"\f2d0"}.bi-compass::before{content:"\f2d1"}.bi-cone-striped::before{content:"\f2d2"}.bi-cone::before{content:"\f2d3"}.bi-controller::before{content:"\f2d4"}.bi-cpu-fill::before{content:"\f2d5"}.bi-cpu::before{content:"\f2d6"}.bi-credit-card-2-back-fill::before{content:"\f2d7"}.bi-credit-card-2-back::before{content:"\f2d8"}.bi-credit-card-2-front-fill::before{content:"\f2d9"}.bi-credit-card-2-front::before{content:"\f2da"}.bi-credit-card-fill::before{content:"\f2db"}.bi-credit-card::before{content:"\f2dc"}.bi-crop::before{content:"\f2dd"}.bi-cup-fill::before{content:"\f2de"}.bi-cup-straw::before{content:"\f2df"}.bi-cup::before{content:"\f2e0"}.bi-cursor-fill::before{content:"\f2e1"}.bi-cursor-text::before{content:"\f2e2"}.bi-cursor::before{content:"\f2e3"}.bi-dash-circle-dotted::before{content:"\f2e4"}.bi-dash-circle-fill::before{content:"\f2e5"}.bi-dash-circle::before{content:"\f2e6"}.bi-dash-square-dotted::before{content:"\f2e7"}.bi-dash-square-fill::before{content:"\f2e8"}.bi-dash-square::before{content:"\f2e9"}.bi-dash::before{content:"\f2ea"}.bi-diagram-2-fill::before{content:"\f2eb"}.bi-diagram-2::before{content:"\f2ec"}.bi-diagram-3-fill::before{content:"\f2ed"}.bi-diagram-3::before{content:"\f2ee"}.bi-diamond-fill::before{content:"\f2ef"}.bi-diamond-half::before{content:"\f2f0"}.bi-diamond::before{content:"\f2f1"}.bi-dice-1-fill::before{content:"\f2f2"}.bi-dice-1::before{content:"\f2f3"}.bi-dice-2-fill::before{content:"\f2f4"}.bi-dice-2::before{content:"\f2f5"}.bi-dice-3-fill::before{content:"\f2f6"}.bi-dice-3::before{content:"\f2f7"}.bi-dice-4-fill::before{content:"\f2f8"}.bi-dice-4::before{content:"\f2f9"}.bi-dice-5-fill::before{content:"\f2fa"}.bi-dice-5::before{content:"\f2fb"}.bi-dice-6-fill::before{content:"\f2fc"}.bi-dice-6::before{content:"\f2fd"}.bi-disc-fill::before{content:"\f2fe"}.bi-disc::before{content:"\f2ff"}.bi-discord::before{content:"\f300"}.bi-display-fill::before{content:"\f301"}.bi-display::before{content:"\f302"}.bi-distribute-horizontal::before{content:"\f303"}.bi-distribute-vertical::before{content:"\f304"}.bi-door-closed-fill::before{content:"\f305"}.bi-door-closed::before{content:"\f306"}.bi-door-open-fill::before{content:"\f307"}.bi-door-open::before{content:"\f308"}.bi-dot::before{content:"\f309"}.bi-download::before{content:"\f30a"}.bi-droplet-fill::before{content:"\f30b"}.bi-droplet-half::before{content:"\f30c"}.bi-droplet::before{content:"\f30d"}.bi-earbuds::before{content:"\f30e"}.bi-easel-fill::before{content:"\f30f"}.bi-easel::before{content:"\f310"}.bi-egg-fill::before{content:"\f311"}.bi-egg-fried::before{content:"\f312"}.bi-egg::before{content:"\f313"}.bi-eject-fill::before{content:"\f314"}.bi-eject::before{content:"\f315"}.bi-emoji-angry-fill::before{content:"\f316"}.bi-emoji-angry::before{content:"\f317"}.bi-emoji-dizzy-fill::before{content:"\f318"}.bi-emoji-dizzy::before{content:"\f319"}.bi-emoji-expressionless-fill::before{content:"\f31a"}.bi-emoji-expressionless::before{content:"\f31b"}.bi-emoji-frown-fill::before{content:"\f31c"}.bi-emoji-frown::before{content:"\f31d"}.bi-emoji-heart-eyes-fill::before{content:"\f31e"}.bi-emoji-heart-eyes::before{content:"\f31f"}.bi-emoji-laughing-fill::before{content:"\f320"}.bi-emoji-laughing::before{content:"\f321"}.bi-emoji-neutral-fill::before{content:"\f322"}.bi-emoji-neutral::before{content:"\f323"}.bi-emoji-smile-fill::before{content:"\f324"}.bi-emoji-smile-upside-down-fill::before{content:"\f325"}.bi-emoji-smile-upside-down::before{content:"\f326"}.bi-emoji-smile::before{content:"\f327"}.bi-emoji-sunglasses-fill::before{content:"\f328"}.bi-emoji-sunglasses::before{content:"\f329"}.bi-emoji-wink-fill::before{content:"\f32a"}.bi-emoji-wink::before{content:"\f32b"}.bi-envelope-fill::before{content:"\f32c"}.bi-envelope-open-fill::before{content:"\f32d"}.bi-envelope-open::before{content:"\f32e"}.bi-envelope::before{content:"\f32f"}.bi-eraser-fill::before{content:"\f330"}.bi-eraser::before{content:"\f331"}.bi-exclamation-circle-fill::before{content:"\f332"}.bi-exclamation-circle::before{content:"\f333"}.bi-exclamation-diamond-fill::before{content:"\f334"}.bi-exclamation-diamond::before{content:"\f335"}.bi-exclamation-octagon-fill::before{content:"\f336"}.bi-exclamation-octagon::before{content:"\f337"}.bi-exclamation-square-fill::before{content:"\f338"}.bi-exclamation-square::before{content:"\f339"}.bi-exclamation-triangle-fill::before{content:"\f33a"}.bi-exclamation-triangle::before{content:"\f33b"}.bi-exclamation::before{content:"\f33c"}.bi-exclude::before{content:"\f33d"}.bi-eye-fill::before{content:"\f33e"}.bi-eye-slash-fill::before{content:"\f33f"}.bi-eye-slash::before{content:"\f340"}.bi-eye::before{content:"\f341"}.bi-eyedropper::before{content:"\f342"}.bi-eyeglasses::before{content:"\f343"}.bi-facebook::before{content:"\f344"}.bi-file-arrow-down-fill::before{content:"\f345"}.bi-file-arrow-down::before{content:"\f346"}.bi-file-arrow-up-fill::before{content:"\f347"}.bi-file-arrow-up::before{content:"\f348"}.bi-file-bar-graph-fill::before{content:"\f349"}.bi-file-bar-graph::before{content:"\f34a"}.bi-file-binary-fill::before{content:"\f34b"}.bi-file-binary::before{content:"\f34c"}.bi-file-break-fill::before{content:"\f34d"}.bi-file-break::before{content:"\f34e"}.bi-file-check-fill::before{content:"\f34f"}.bi-file-check::before{content:"\f350"}.bi-file-code-fill::before{content:"\f351"}.bi-file-code::before{content:"\f352"}.bi-file-diff-fill::before{content:"\f353"}.bi-file-diff::before{content:"\f354"}.bi-file-earmark-arrow-down-fill::before{content:"\f355"}.bi-file-earmark-arrow-down::before{content:"\f356"}.bi-file-earmark-arrow-up-fill::before{content:"\f357"}.bi-file-earmark-arrow-up::before{content:"\f358"}.bi-file-earmark-bar-graph-fill::before{content:"\f359"}.bi-file-earmark-bar-graph::before{content:"\f35a"}.bi-file-earmark-binary-fill::before{content:"\f35b"}.bi-file-earmark-binary::before{content:"\f35c"}.bi-file-earmark-break-fill::before{content:"\f35d"}.bi-file-earmark-break::before{content:"\f35e"}.bi-file-earmark-check-fill::before{content:"\f35f"}.bi-file-earmark-check::before{content:"\f360"}.bi-file-earmark-code-fill::before{content:"\f361"}.bi-file-earmark-code::before{content:"\f362"}.bi-file-earmark-diff-fill::before{content:"\f363"}.bi-file-earmark-diff::before{content:"\f364"}.bi-file-earmark-easel-fill::before{content:"\f365"}.bi-file-earmark-easel::before{content:"\f366"}.bi-file-earmark-excel-fill::before{content:"\f367"}.bi-file-earmark-excel::before{content:"\f368"}.bi-file-earmark-fill::before{content:"\f369"}.bi-file-earmark-font-fill::before{content:"\f36a"}.bi-file-earmark-font::before{content:"\f36b"}.bi-file-earmark-image-fill::before{content:"\f36c"}.bi-file-earmark-image::before{content:"\f36d"}.bi-file-earmark-lock-fill::before{content:"\f36e"}.bi-file-earmark-lock::before{content:"\f36f"}.bi-file-earmark-lock2-fill::before{content:"\f370"}.bi-file-earmark-lock2::before{content:"\f371"}.bi-file-earmark-medical-fill::before{content:"\f372"}.bi-file-earmark-medical::before{content:"\f373"}.bi-file-earmark-minus-fill::before{content:"\f374"}.bi-file-earmark-minus::before{content:"\f375"}.bi-file-earmark-music-fill::before{content:"\f376"}.bi-file-earmark-music::before{content:"\f377"}.bi-file-earmark-person-fill::before{content:"\f378"}.bi-file-earmark-person::before{content:"\f379"}.bi-file-earmark-play-fill::before{content:"\f37a"}.bi-file-earmark-play::before{content:"\f37b"}.bi-file-earmark-plus-fill::before{content:"\f37c"}.bi-file-earmark-plus::before{content:"\f37d"}.bi-file-earmark-post-fill::before{content:"\f37e"}.bi-file-earmark-post::before{content:"\f37f"}.bi-file-earmark-ppt-fill::before{content:"\f380"}.bi-file-earmark-ppt::before{content:"\f381"}.bi-file-earmark-richtext-fill::before{content:"\f382"}.bi-file-earmark-richtext::before{content:"\f383"}.bi-file-earmark-ruled-fill::before{content:"\f384"}.bi-file-earmark-ruled::before{content:"\f385"}.bi-file-earmark-slides-fill::before{content:"\f386"}.bi-file-earmark-slides::before{content:"\f387"}.bi-file-earmark-spreadsheet-fill::before{content:"\f388"}.bi-file-earmark-spreadsheet::before{content:"\f389"}.bi-file-earmark-text-fill::before{content:"\f38a"}.bi-file-earmark-text::before{content:"\f38b"}.bi-file-earmark-word-fill::before{content:"\f38c"}.bi-file-earmark-word::before{content:"\f38d"}.bi-file-earmark-x-fill::before{content:"\f38e"}.bi-file-earmark-x::before{content:"\f38f"}.bi-file-earmark-zip-fill::before{content:"\f390"}.bi-file-earmark-zip::before{content:"\f391"}.bi-file-earmark::before{content:"\f392"}.bi-file-easel-fill::before{content:"\f393"}.bi-file-easel::before{content:"\f394"}.bi-file-excel-fill::before{content:"\f395"}.bi-file-excel::before{content:"\f396"}.bi-file-fill::before{content:"\f397"}.bi-file-font-fill::before{content:"\f398"}.bi-file-font::before{content:"\f399"}.bi-file-image-fill::before{content:"\f39a"}.bi-file-image::before{content:"\f39b"}.bi-file-lock-fill::before{content:"\f39c"}.bi-file-lock::before{content:"\f39d"}.bi-file-lock2-fill::before{content:"\f39e"}.bi-file-lock2::before{content:"\f39f"}.bi-file-medical-fill::before{content:"\f3a0"}.bi-file-medical::before{content:"\f3a1"}.bi-file-minus-fill::before{content:"\f3a2"}.bi-file-minus::before{content:"\f3a3"}.bi-file-music-fill::before{content:"\f3a4"}.bi-file-music::before{content:"\f3a5"}.bi-file-person-fill::before{content:"\f3a6"}.bi-file-person::before{content:"\f3a7"}.bi-file-play-fill::before{content:"\f3a8"}.bi-file-play::before{content:"\f3a9"}.bi-file-plus-fill::before{content:"\f3aa"}.bi-file-plus::before{content:"\f3ab"}.bi-file-post-fill::before{content:"\f3ac"}.bi-file-post::before{content:"\f3ad"}.bi-file-ppt-fill::before{content:"\f3ae"}.bi-file-ppt::before{content:"\f3af"}.bi-file-richtext-fill::before{content:"\f3b0"}.bi-file-richtext::before{content:"\f3b1"}.bi-file-ruled-fill::before{content:"\f3b2"}.bi-file-ruled::before{content:"\f3b3"}.bi-file-slides-fill::before{content:"\f3b4"}.bi-file-slides::before{content:"\f3b5"}.bi-file-spreadsheet-fill::before{content:"\f3b6"}.bi-file-spreadsheet::before{content:"\f3b7"}.bi-file-text-fill::before{content:"\f3b8"}.bi-file-text::before{content:"\f3b9"}.bi-file-word-fill::before{content:"\f3ba"}.bi-file-word::before{content:"\f3bb"}.bi-file-x-fill::before{content:"\f3bc"}.bi-file-x::before{content:"\f3bd"}.bi-file-zip-fill::before{content:"\f3be"}.bi-file-zip::before{content:"\f3bf"}.bi-file::before{content:"\f3c0"}.bi-files-alt::before{content:"\f3c1"}.bi-files::before{content:"\f3c2"}.bi-film::before{content:"\f3c3"}.bi-filter-circle-fill::before{content:"\f3c4"}.bi-filter-circle::before{content:"\f3c5"}.bi-filter-left::before{content:"\f3c6"}.bi-filter-right::before{content:"\f3c7"}.bi-filter-square-fill::before{content:"\f3c8"}.bi-filter-square::before{content:"\f3c9"}.bi-filter::before{content:"\f3ca"}.bi-flag-fill::before{content:"\f3cb"}.bi-flag::before{content:"\f3cc"}.bi-flower1::before{content:"\f3cd"}.bi-flower2::before{content:"\f3ce"}.bi-flower3::before{content:"\f3cf"}.bi-folder-check::before{content:"\f3d0"}.bi-folder-fill::before{content:"\f3d1"}.bi-folder-minus::before{content:"\f3d2"}.bi-folder-plus::before{content:"\f3d3"}.bi-folder-symlink-fill::before{content:"\f3d4"}.bi-folder-symlink::before{content:"\f3d5"}.bi-folder-x::before{content:"\f3d6"}.bi-folder::before{content:"\f3d7"}.bi-folder2-open::before{content:"\f3d8"}.bi-folder2::before{content:"\f3d9"}.bi-fonts::before{content:"\f3da"}.bi-forward-fill::before{content:"\f3db"}.bi-forward::before{content:"\f3dc"}.bi-front::before{content:"\f3dd"}.bi-fullscreen-exit::before{content:"\f3de"}.bi-fullscreen::before{content:"\f3df"}.bi-funnel-fill::before{content:"\f3e0"}.bi-funnel::before{content:"\f3e1"}.bi-gear-fill::before{content:"\f3e2"}.bi-gear-wide-connected::before{content:"\f3e3"}.bi-gear-wide::before{content:"\f3e4"}.bi-gear::before{content:"\f3e5"}.bi-gem::before{content:"\f3e6"}.bi-geo-alt-fill::before{content:"\f3e7"}.bi-geo-alt::before{content:"\f3e8"}.bi-geo-fill::before{content:"\f3e9"}.bi-geo::before{content:"\f3ea"}.bi-gift-fill::before{content:"\f3eb"}.bi-gift::before{content:"\f3ec"}.bi-github::before{content:"\f3ed"}.bi-globe::before{content:"\f3ee"}.bi-globe2::before{content:"\f3ef"}.bi-google::before{content:"\f3f0"}.bi-graph-down::before{content:"\f3f1"}.bi-graph-up::before{content:"\f3f2"}.bi-grid-1x2-fill::before{content:"\f3f3"}.bi-grid-1x2::before{content:"\f3f4"}.bi-grid-3x2-gap-fill::before{content:"\f3f5"}.bi-grid-3x2-gap::before{content:"\f3f6"}.bi-grid-3x2::before{content:"\f3f7"}.bi-grid-3x3-gap-fill::before{content:"\f3f8"}.bi-grid-3x3-gap::before{content:"\f3f9"}.bi-grid-3x3::before{content:"\f3fa"}.bi-grid-fill::before{content:"\f3fb"}.bi-grid::before{content:"\f3fc"}.bi-grip-horizontal::before{content:"\f3fd"}.bi-grip-vertical::before{content:"\f3fe"}.bi-hammer::before{content:"\f3ff"}.bi-hand-index-fill::before{content:"\f400"}.bi-hand-index-thumb-fill::before{content:"\f401"}.bi-hand-index-thumb::before{content:"\f402"}.bi-hand-index::before{content:"\f403"}.bi-hand-thumbs-down-fill::before{content:"\f404"}.bi-hand-thumbs-down::before{content:"\f405"}.bi-hand-thumbs-up-fill::before{content:"\f406"}.bi-hand-thumbs-up::before{content:"\f407"}.bi-handbag-fill::before{content:"\f408"}.bi-handbag::before{content:"\f409"}.bi-hash::before{content:"\f40a"}.bi-hdd-fill::before{content:"\f40b"}.bi-hdd-network-fill::before{content:"\f40c"}.bi-hdd-network::before{content:"\f40d"}.bi-hdd-rack-fill::before{content:"\f40e"}.bi-hdd-rack::before{content:"\f40f"}.bi-hdd-stack-fill::before{content:"\f410"}.bi-hdd-stack::before{content:"\f411"}.bi-hdd::before{content:"\f412"}.bi-headphones::before{content:"\f413"}.bi-headset::before{content:"\f414"}.bi-heart-fill::before{content:"\f415"}.bi-heart-half::before{content:"\f416"}.bi-heart::before{content:"\f417"}.bi-heptagon-fill::before{content:"\f418"}.bi-heptagon-half::before{content:"\f419"}.bi-heptagon::before{content:"\f41a"}.bi-hexagon-fill::before{content:"\f41b"}.bi-hexagon-half::before{content:"\f41c"}.bi-hexagon::before{content:"\f41d"}.bi-hourglass-bottom::before{content:"\f41e"}.bi-hourglass-split::before{content:"\f41f"}.bi-hourglass-top::before{content:"\f420"}.bi-hourglass::before{content:"\f421"}.bi-house-door-fill::before{content:"\f422"}.bi-house-door::before{content:"\f423"}.bi-house-fill::before{content:"\f424"}.bi-house::before{content:"\f425"}.bi-hr::before{content:"\f426"}.bi-hurricane::before{content:"\f427"}.bi-image-alt::before{content:"\f428"}.bi-image-fill::before{content:"\f429"}.bi-image::before{content:"\f42a"}.bi-images::before{content:"\f42b"}.bi-inbox-fill::before{content:"\f42c"}.bi-inbox::before{content:"\f42d"}.bi-inboxes-fill::before{content:"\f42e"}.bi-inboxes::before{content:"\f42f"}.bi-info-circle-fill::before{content:"\f430"}.bi-info-circle::before{content:"\f431"}.bi-info-square-fill::before{content:"\f432"}.bi-info-square::before{content:"\f433"}.bi-info::before{content:"\f434"}.bi-input-cursor-text::before{content:"\f435"}.bi-input-cursor::before{content:"\f436"}.bi-instagram::before{content:"\f437"}.bi-intersect::before{content:"\f438"}.bi-journal-album::before{content:"\f439"}.bi-journal-arrow-down::before{content:"\f43a"}.bi-journal-arrow-up::before{content:"\f43b"}.bi-journal-bookmark-fill::before{content:"\f43c"}.bi-journal-bookmark::before{content:"\f43d"}.bi-journal-check::before{content:"\f43e"}.bi-journal-code::before{content:"\f43f"}.bi-journal-medical::before{content:"\f440"}.bi-journal-minus::before{content:"\f441"}.bi-journal-plus::before{content:"\f442"}.bi-journal-richtext::before{content:"\f443"}.bi-journal-text::before{content:"\f444"}.bi-journal-x::before{content:"\f445"}.bi-journal::before{content:"\f446"}.bi-journals::before{content:"\f447"}.bi-joystick::before{content:"\f448"}.bi-justify-left::before{content:"\f449"}.bi-justify-right::before{content:"\f44a"}.bi-justify::before{content:"\f44b"}.bi-kanban-fill::before{content:"\f44c"}.bi-kanban::before{content:"\f44d"}.bi-key-fill::before{content:"\f44e"}.bi-key::before{content:"\f44f"}.bi-keyboard-fill::before{content:"\f450"}.bi-keyboard::before{content:"\f451"}.bi-ladder::before{content:"\f452"}.bi-lamp-fill::before{content:"\f453"}.bi-lamp::before{content:"\f454"}.bi-laptop-fill::before{content:"\f455"}.bi-laptop::before{content:"\f456"}.bi-layer-backward::before{content:"\f457"}.bi-layer-forward::before{content:"\f458"}.bi-layers-fill::before{content:"\f459"}.bi-layers-half::before{content:"\f45a"}.bi-layers::before{content:"\f45b"}.bi-layout-sidebar-inset-reverse::before{content:"\f45c"}.bi-layout-sidebar-inset::before{content:"\f45d"}.bi-layout-sidebar-reverse::before{content:"\f45e"}.bi-layout-sidebar::before{content:"\f45f"}.bi-layout-split::before{content:"\f460"}.bi-layout-text-sidebar-reverse::before{content:"\f461"}.bi-layout-text-sidebar::before{content:"\f462"}.bi-layout-text-window-reverse::before{content:"\f463"}.bi-layout-text-window::before{content:"\f464"}.bi-layout-three-columns::before{content:"\f465"}.bi-layout-wtf::before{content:"\f466"}.bi-life-preserver::before{content:"\f467"}.bi-lightbulb-fill::before{content:"\f468"}.bi-lightbulb-off-fill::before{content:"\f469"}.bi-lightbulb-off::before{content:"\f46a"}.bi-lightbulb::before{content:"\f46b"}.bi-lightning-charge-fill::before{content:"\f46c"}.bi-lightning-charge::before{content:"\f46d"}.bi-lightning-fill::before{content:"\f46e"}.bi-lightning::before{content:"\f46f"}.bi-link-45deg::before{content:"\f470"}.bi-link::before{content:"\f471"}.bi-linkedin::before{content:"\f472"}.bi-list-check::before{content:"\f473"}.bi-list-nested::before{content:"\f474"}.bi-list-ol::before{content:"\f475"}.bi-list-stars::before{content:"\f476"}.bi-list-task::before{content:"\f477"}.bi-list-ul::before{content:"\f478"}.bi-list::before{content:"\f479"}.bi-lock-fill::before{content:"\f47a"}.bi-lock::before{content:"\f47b"}.bi-mailbox::before{content:"\f47c"}.bi-mailbox2::before{content:"\f47d"}.bi-map-fill::before{content:"\f47e"}.bi-map::before{content:"\f47f"}.bi-markdown-fill::before{content:"\f480"}.bi-markdown::before{content:"\f481"}.bi-mask::before{content:"\f482"}.bi-megaphone-fill::before{content:"\f483"}.bi-megaphone::before{content:"\f484"}.bi-menu-app-fill::before{content:"\f485"}.bi-menu-app::before{content:"\f486"}.bi-menu-button-fill::before{content:"\f487"}.bi-menu-button-wide-fill::before{content:"\f488"}.bi-menu-button-wide::before{content:"\f489"}.bi-menu-button::before{content:"\f48a"}.bi-menu-down::before{content:"\f48b"}.bi-menu-up::before{content:"\f48c"}.bi-mic-fill::before{content:"\f48d"}.bi-mic-mute-fill::before{content:"\f48e"}.bi-mic-mute::before{content:"\f48f"}.bi-mic::before{content:"\f490"}.bi-minecart-loaded::before{content:"\f491"}.bi-minecart::before{content:"\f492"}.bi-moisture::before{content:"\f493"}.bi-moon-fill::before{content:"\f494"}.bi-moon-stars-fill::before{content:"\f495"}.bi-moon-stars::before{content:"\f496"}.bi-moon::before{content:"\f497"}.bi-mouse-fill::before{content:"\f498"}.bi-mouse::before{content:"\f499"}.bi-mouse2-fill::before{content:"\f49a"}.bi-mouse2::before{content:"\f49b"}.bi-mouse3-fill::before{content:"\f49c"}.bi-mouse3::before{content:"\f49d"}.bi-music-note-beamed::before{content:"\f49e"}.bi-music-note-list::before{content:"\f49f"}.bi-music-note::before{content:"\f4a0"}.bi-music-player-fill::before{content:"\f4a1"}.bi-music-player::before{content:"\f4a2"}.bi-newspaper::before{content:"\f4a3"}.bi-node-minus-fill::before{content:"\f4a4"}.bi-node-minus::before{content:"\f4a5"}.bi-node-plus-fill::before{content:"\f4a6"}.bi-node-plus::before{content:"\f4a7"}.bi-nut-fill::before{content:"\f4a8"}.bi-nut::before{content:"\f4a9"}.bi-octagon-fill::before{content:"\f4aa"}.bi-octagon-half::before{content:"\f4ab"}.bi-octagon::before{content:"\f4ac"}.bi-option::before{content:"\f4ad"}.bi-outlet::before{content:"\f4ae"}.bi-paint-bucket::before{content:"\f4af"}.bi-palette-fill::before{content:"\f4b0"}.bi-palette::before{content:"\f4b1"}.bi-palette2::before{content:"\f4b2"}.bi-paperclip::before{content:"\f4b3"}.bi-paragraph::before{content:"\f4b4"}.bi-patch-check-fill::before{content:"\f4b5"}.bi-patch-check::before{content:"\f4b6"}.bi-patch-exclamation-fill::before{content:"\f4b7"}.bi-patch-exclamation::before{content:"\f4b8"}.bi-patch-minus-fill::before{content:"\f4b9"}.bi-patch-minus::before{content:"\f4ba"}.bi-patch-plus-fill::before{content:"\f4bb"}.bi-patch-plus::before{content:"\f4bc"}.bi-patch-question-fill::before{content:"\f4bd"}.bi-patch-question::before{content:"\f4be"}.bi-pause-btn-fill::before{content:"\f4bf"}.bi-pause-btn::before{content:"\f4c0"}.bi-pause-circle-fill::before{content:"\f4c1"}.bi-pause-circle::before{content:"\f4c2"}.bi-pause-fill::before{content:"\f4c3"}.bi-pause::before{content:"\f4c4"}.bi-peace-fill::before{content:"\f4c5"}.bi-peace::before{content:"\f4c6"}.bi-pen-fill::before{content:"\f4c7"}.bi-pen::before{content:"\f4c8"}.bi-pencil-fill::before{content:"\f4c9"}.bi-pencil-square::before{content:"\f4ca"}.bi-pencil::before{content:"\f4cb"}.bi-pentagon-fill::before{content:"\f4cc"}.bi-pentagon-half::before{content:"\f4cd"}.bi-pentagon::before{content:"\f4ce"}.bi-people-fill::before{content:"\f4cf"}.bi-people::before{content:"\f4d0"}.bi-percent::before{content:"\f4d1"}.bi-person-badge-fill::before{content:"\f4d2"}.bi-person-badge::before{content:"\f4d3"}.bi-person-bounding-box::before{content:"\f4d4"}.bi-person-check-fill::before{content:"\f4d5"}.bi-person-check::before{content:"\f4d6"}.bi-person-circle::before{content:"\f4d7"}.bi-person-dash-fill::before{content:"\f4d8"}.bi-person-dash::before{content:"\f4d9"}.bi-person-fill::before{content:"\f4da"}.bi-person-lines-fill::before{content:"\f4db"}.bi-person-plus-fill::before{content:"\f4dc"}.bi-person-plus::before{content:"\f4dd"}.bi-person-square::before{content:"\f4de"}.bi-person-x-fill::before{content:"\f4df"}.bi-person-x::before{content:"\f4e0"}.bi-person::before{content:"\f4e1"}.bi-phone-fill::before{content:"\f4e2"}.bi-phone-landscape-fill::before{content:"\f4e3"}.bi-phone-landscape::before{content:"\f4e4"}.bi-phone-vibrate-fill::before{content:"\f4e5"}.bi-phone-vibrate::before{content:"\f4e6"}.bi-phone::before{content:"\f4e7"}.bi-pie-chart-fill::before{content:"\f4e8"}.bi-pie-chart::before{content:"\f4e9"}.bi-pin-angle-fill::before{content:"\f4ea"}.bi-pin-angle::before{content:"\f4eb"}.bi-pin-fill::before{content:"\f4ec"}.bi-pin::before{content:"\f4ed"}.bi-pip-fill::before{content:"\f4ee"}.bi-pip::before{content:"\f4ef"}.bi-play-btn-fill::before{content:"\f4f0"}.bi-play-btn::before{content:"\f4f1"}.bi-play-circle-fill::before{content:"\f4f2"}.bi-play-circle::before{content:"\f4f3"}.bi-play-fill::before{content:"\f4f4"}.bi-play::before{content:"\f4f5"}.bi-plug-fill::before{content:"\f4f6"}.bi-plug::before{content:"\f4f7"}.bi-plus-circle-dotted::before{content:"\f4f8"}.bi-plus-circle-fill::before{content:"\f4f9"}.bi-plus-circle::before{content:"\f4fa"}.bi-plus-square-dotted::before{content:"\f4fb"}.bi-plus-square-fill::before{content:"\f4fc"}.bi-plus-square::before{content:"\f4fd"}.bi-plus::before{content:"\f4fe"}.bi-power::before{content:"\f4ff"}.bi-printer-fill::before{content:"\f500"}.bi-printer::before{content:"\f501"}.bi-puzzle-fill::before{content:"\f502"}.bi-puzzle::before{content:"\f503"}.bi-question-circle-fill::before{content:"\f504"}.bi-question-circle::before{content:"\f505"}.bi-question-diamond-fill::before{content:"\f506"}.bi-question-diamond::before{content:"\f507"}.bi-question-octagon-fill::before{content:"\f508"}.bi-question-octagon::before{content:"\f509"}.bi-question-square-fill::before{content:"\f50a"}.bi-question-square::before{content:"\f50b"}.bi-question::before{content:"\f50c"}.bi-rainbow::before{content:"\f50d"}.bi-receipt-cutoff::before{content:"\f50e"}.bi-receipt::before{content:"\f50f"}.bi-reception-0::before{content:"\f510"}.bi-reception-1::before{content:"\f511"}.bi-reception-2::before{content:"\f512"}.bi-reception-3::before{content:"\f513"}.bi-reception-4::before{content:"\f514"}.bi-record-btn-fill::before{content:"\f515"}.bi-record-btn::before{content:"\f516"}.bi-record-circle-fill::before{content:"\f517"}.bi-record-circle::before{content:"\f518"}.bi-record-fill::before{content:"\f519"}.bi-record::before{content:"\f51a"}.bi-record2-fill::before{content:"\f51b"}.bi-record2::before{content:"\f51c"}.bi-reply-all-fill::before{content:"\f51d"}.bi-reply-all::before{content:"\f51e"}.bi-reply-fill::before{content:"\f51f"}.bi-reply::before{content:"\f520"}.bi-rss-fill::before{content:"\f521"}.bi-rss::before{content:"\f522"}.bi-rulers::before{content:"\f523"}.bi-save-fill::before{content:"\f524"}.bi-save::before{content:"\f525"}.bi-save2-fill::before{content:"\f526"}.bi-save2::before{content:"\f527"}.bi-scissors::before{content:"\f528"}.bi-screwdriver::before{content:"\f529"}.bi-search::before{content:"\f52a"}.bi-segmented-nav::before{content:"\f52b"}.bi-server::before{content:"\f52c"}.bi-share-fill::before{content:"\f52d"}.bi-share::before{content:"\f52e"}.bi-shield-check::before{content:"\f52f"}.bi-shield-exclamation::before{content:"\f530"}.bi-shield-fill-check::before{content:"\f531"}.bi-shield-fill-exclamation::before{content:"\f532"}.bi-shield-fill-minus::before{content:"\f533"}.bi-shield-fill-plus::before{content:"\f534"}.bi-shield-fill-x::before{content:"\f535"}.bi-shield-fill::before{content:"\f536"}.bi-shield-lock-fill::before{content:"\f537"}.bi-shield-lock::before{content:"\f538"}.bi-shield-minus::before{content:"\f539"}.bi-shield-plus::before{content:"\f53a"}.bi-shield-shaded::before{content:"\f53b"}.bi-shield-slash-fill::before{content:"\f53c"}.bi-shield-slash::before{content:"\f53d"}.bi-shield-x::before{content:"\f53e"}.bi-shield::before{content:"\f53f"}.bi-shift-fill::before{content:"\f540"}.bi-shift::before{content:"\f541"}.bi-shop-window::before{content:"\f542"}.bi-shop::before{content:"\f543"}.bi-shuffle::before{content:"\f544"}.bi-signpost-2-fill::before{content:"\f545"}.bi-signpost-2::before{content:"\f546"}.bi-signpost-fill::before{content:"\f547"}.bi-signpost-split-fill::before{content:"\f548"}.bi-signpost-split::before{content:"\f549"}.bi-signpost::before{content:"\f54a"}.bi-sim-fill::before{content:"\f54b"}.bi-sim::before{content:"\f54c"}.bi-skip-backward-btn-fill::before{content:"\f54d"}.bi-skip-backward-btn::before{content:"\f54e"}.bi-skip-backward-circle-fill::before{content:"\f54f"}.bi-skip-backward-circle::before{content:"\f550"}.bi-skip-backward-fill::before{content:"\f551"}.bi-skip-backward::before{content:"\f552"}.bi-skip-end-btn-fill::before{content:"\f553"}.bi-skip-end-btn::before{content:"\f554"}.bi-skip-end-circle-fill::before{content:"\f555"}.bi-skip-end-circle::before{content:"\f556"}.bi-skip-end-fill::before{content:"\f557"}.bi-skip-end::before{content:"\f558"}.bi-skip-forward-btn-fill::before{content:"\f559"}.bi-skip-forward-btn::before{content:"\f55a"}.bi-skip-forward-circle-fill::before{content:"\f55b"}.bi-skip-forward-circle::before{content:"\f55c"}.bi-skip-forward-fill::before{content:"\f55d"}.bi-skip-forward::before{content:"\f55e"}.bi-skip-start-btn-fill::before{content:"\f55f"}.bi-skip-start-btn::before{content:"\f560"}.bi-skip-start-circle-fill::before{content:"\f561"}.bi-skip-start-circle::before{content:"\f562"}.bi-skip-start-fill::before{content:"\f563"}.bi-skip-start::before{content:"\f564"}.bi-slack::before{content:"\f565"}.bi-slash-circle-fill::before{content:"\f566"}.bi-slash-circle::before{content:"\f567"}.bi-slash-square-fill::before{content:"\f568"}.bi-slash-square::before{content:"\f569"}.bi-slash::before{content:"\f56a"}.bi-sliders::before{content:"\f56b"}.bi-smartwatch::before{content:"\f56c"}.bi-snow::before{content:"\f56d"}.bi-snow2::before{content:"\f56e"}.bi-snow3::before{content:"\f56f"}.bi-sort-alpha-down-alt::before{content:"\f570"}.bi-sort-alpha-down::before{content:"\f571"}.bi-sort-alpha-up-alt::before{content:"\f572"}.bi-sort-alpha-up::before{content:"\f573"}.bi-sort-down-alt::before{content:"\f574"}.bi-sort-down::before{content:"\f575"}.bi-sort-numeric-down-alt::before{content:"\f576"}.bi-sort-numeric-down::before{content:"\f577"}.bi-sort-numeric-up-alt::before{content:"\f578"}.bi-sort-numeric-up::before{content:"\f579"}.bi-sort-up-alt::before{content:"\f57a"}.bi-sort-up::before{content:"\f57b"}.bi-soundwave::before{content:"\f57c"}.bi-speaker-fill::before{content:"\f57d"}.bi-speaker::before{content:"\f57e"}.bi-speedometer::before{content:"\f57f"}.bi-speedometer2::before{content:"\f580"}.bi-spellcheck::before{content:"\f581"}.bi-square-fill::before{content:"\f582"}.bi-square-half::before{content:"\f583"}.bi-square::before{content:"\f584"}.bi-stack::before{content:"\f585"}.bi-star-fill::before{content:"\f586"}.bi-star-half::before{content:"\f587"}.bi-star::before{content:"\f588"}.bi-stars::before{content:"\f589"}.bi-stickies-fill::before{content:"\f58a"}.bi-stickies::before{content:"\f58b"}.bi-sticky-fill::before{content:"\f58c"}.bi-sticky::before{content:"\f58d"}.bi-stop-btn-fill::before{content:"\f58e"}.bi-stop-btn::before{content:"\f58f"}.bi-stop-circle-fill::before{content:"\f590"}.bi-stop-circle::before{content:"\f591"}.bi-stop-fill::before{content:"\f592"}.bi-stop::before{content:"\f593"}.bi-stoplights-fill::before{content:"\f594"}.bi-stoplights::before{content:"\f595"}.bi-stopwatch-fill::before{content:"\f596"}.bi-stopwatch::before{content:"\f597"}.bi-subtract::before{content:"\f598"}.bi-suit-club-fill::before{content:"\f599"}.bi-suit-club::before{content:"\f59a"}.bi-suit-diamond-fill::before{content:"\f59b"}.bi-suit-diamond::before{content:"\f59c"}.bi-suit-heart-fill::before{content:"\f59d"}.bi-suit-heart::before{content:"\f59e"}.bi-suit-spade-fill::before{content:"\f59f"}.bi-suit-spade::before{content:"\f5a0"}.bi-sun-fill::before{content:"\f5a1"}.bi-sun::before{content:"\f5a2"}.bi-sunglasses::before{content:"\f5a3"}.bi-sunrise-fill::before{content:"\f5a4"}.bi-sunrise::before{content:"\f5a5"}.bi-sunset-fill::before{content:"\f5a6"}.bi-sunset::before{content:"\f5a7"}.bi-symmetry-horizontal::before{content:"\f5a8"}.bi-symmetry-vertical::before{content:"\f5a9"}.bi-table::before{content:"\f5aa"}.bi-tablet-fill::before{content:"\f5ab"}.bi-tablet-landscape-fill::before{content:"\f5ac"}.bi-tablet-landscape::before{content:"\f5ad"}.bi-tablet::before{content:"\f5ae"}.bi-tag-fill::before{content:"\f5af"}.bi-tag::before{content:"\f5b0"}.bi-tags-fill::before{content:"\f5b1"}.bi-tags::before{content:"\f5b2"}.bi-telegram::before{content:"\f5b3"}.bi-telephone-fill::before{content:"\f5b4"}.bi-telephone-forward-fill::before{content:"\f5b5"}.bi-telephone-forward::before{content:"\f5b6"}.bi-telephone-inbound-fill::before{content:"\f5b7"}.bi-telephone-inbound::before{content:"\f5b8"}.bi-telephone-minus-fill::before{content:"\f5b9"}.bi-telephone-minus::before{content:"\f5ba"}.bi-telephone-outbound-fill::before{content:"\f5bb"}.bi-telephone-outbound::before{content:"\f5bc"}.bi-telephone-plus-fill::before{content:"\f5bd"}.bi-telephone-plus::before{content:"\f5be"}.bi-telephone-x-fill::before{content:"\f5bf"}.bi-telephone-x::before{content:"\f5c0"}.bi-telephone::before{content:"\f5c1"}.bi-terminal-fill::before{content:"\f5c2"}.bi-terminal::before{content:"\f5c3"}.bi-text-center::before{content:"\f5c4"}.bi-text-indent-left::before{content:"\f5c5"}.bi-text-indent-right::before{content:"\f5c6"}.bi-text-left::before{content:"\f5c7"}.bi-text-paragraph::before{content:"\f5c8"}.bi-text-right::before{content:"\f5c9"}.bi-textarea-resize::before{content:"\f5ca"}.bi-textarea-t::before{content:"\f5cb"}.bi-textarea::before{content:"\f5cc"}.bi-thermometer-half::before{content:"\f5cd"}.bi-thermometer-high::before{content:"\f5ce"}.bi-thermometer-low::before{content:"\f5cf"}.bi-thermometer-snow::before{content:"\f5d0"}.bi-thermometer-sun::before{content:"\f5d1"}.bi-thermometer::before{content:"\f5d2"}.bi-three-dots-vertical::before{content:"\f5d3"}.bi-three-dots::before{content:"\f5d4"}.bi-toggle-off::before{content:"\f5d5"}.bi-toggle-on::before{content:"\f5d6"}.bi-toggle2-off::before{content:"\f5d7"}.bi-toggle2-on::before{content:"\f5d8"}.bi-toggles::before{content:"\f5d9"}.bi-toggles2::before{content:"\f5da"}.bi-tools::before{content:"\f5db"}.bi-tornado::before{content:"\f5dc"}.bi-trash-fill::before{content:"\f5dd"}.bi-trash::before{content:"\f5de"}.bi-trash2-fill::before{content:"\f5df"}.bi-trash2::before{content:"\f5e0"}.bi-tree-fill::before{content:"\f5e1"}.bi-tree::before{content:"\f5e2"}.bi-triangle-fill::before{content:"\f5e3"}.bi-triangle-half::before{content:"\f5e4"}.bi-triangle::before{content:"\f5e5"}.bi-trophy-fill::before{content:"\f5e6"}.bi-trophy::before{content:"\f5e7"}.bi-tropical-storm::before{content:"\f5e8"}.bi-truck-flatbed::before{content:"\f5e9"}.bi-truck::before{content:"\f5ea"}.bi-tsunami::before{content:"\f5eb"}.bi-tv-fill::before{content:"\f5ec"}.bi-tv::before{content:"\f5ed"}.bi-twitch::before{content:"\f5ee"}.bi-twitter::before{content:"\f5ef"}.bi-type-bold::before{content:"\f5f0"}.bi-type-h1::before{content:"\f5f1"}.bi-type-h2::before{content:"\f5f2"}.bi-type-h3::before{content:"\f5f3"}.bi-type-italic::before{content:"\f5f4"}.bi-type-strikethrough::before{content:"\f5f5"}.bi-type-underline::before{content:"\f5f6"}.bi-type::before{content:"\f5f7"}.bi-ui-checks-grid::before{content:"\f5f8"}.bi-ui-checks::before{content:"\f5f9"}.bi-ui-radios-grid::before{content:"\f5fa"}.bi-ui-radios::before{content:"\f5fb"}.bi-umbrella-fill::before{content:"\f5fc"}.bi-umbrella::before{content:"\f5fd"}.bi-union::before{content:"\f5fe"}.bi-unlock-fill::before{content:"\f5ff"}.bi-unlock::before{content:"\f600"}.bi-upc-scan::before{content:"\f601"}.bi-upc::before{content:"\f602"}.bi-upload::before{content:"\f603"}.bi-vector-pen::before{content:"\f604"}.bi-view-list::before{content:"\f605"}.bi-view-stacked::before{content:"\f606"}.bi-vinyl-fill::before{content:"\f607"}.bi-vinyl::before{content:"\f608"}.bi-voicemail::before{content:"\f609"}.bi-volume-down-fill::before{content:"\f60a"}.bi-volume-down::before{content:"\f60b"}.bi-volume-mute-fill::before{content:"\f60c"}.bi-volume-mute::before{content:"\f60d"}.bi-volume-off-fill::before{content:"\f60e"}.bi-volume-off::before{content:"\f60f"}.bi-volume-up-fill::before{content:"\f610"}.bi-volume-up::before{content:"\f611"}.bi-vr::before{content:"\f612"}.bi-wallet-fill::before{content:"\f613"}.bi-wallet::before{content:"\f614"}.bi-wallet2::before{content:"\f615"}.bi-watch::before{content:"\f616"}.bi-water::before{content:"\f617"}.bi-whatsapp::before{content:"\f618"}.bi-wifi-1::before{content:"\f619"}.bi-wifi-2::before{content:"\f61a"}.bi-wifi-off::before{content:"\f61b"}.bi-wifi::before{content:"\f61c"}.bi-wind::before{content:"\f61d"}.bi-window-dock::before{content:"\f61e"}.bi-window-sidebar::before{content:"\f61f"}.bi-window::before{content:"\f620"}.bi-wrench::before{content:"\f621"}.bi-x-circle-fill::before{content:"\f622"}.bi-x-circle::before{content:"\f623"}.bi-x-diamond-fill::before{content:"\f624"}.bi-x-diamond::before{content:"\f625"}.bi-x-octagon-fill::before{content:"\f626"}.bi-x-octagon::before{content:"\f627"}.bi-x-square-fill::before{content:"\f628"}.bi-x-square::before{content:"\f629"}.bi-x::before{content:"\f62a"}.bi-youtube::before{content:"\f62b"}.bi-zoom-in::before{content:"\f62c"}.bi-zoom-out::before{content:"\f62d"}.bi-bank::before{content:"\f62e"}.bi-bank2::before{content:"\f62f"}.bi-bell-slash-fill::before{content:"\f630"}.bi-bell-slash::before{content:"\f631"}.bi-cash-coin::before{content:"\f632"}.bi-check-lg::before{content:"\f633"}.bi-coin::before{content:"\f634"}.bi-currency-bitcoin::before{content:"\f635"}.bi-currency-dollar::before{content:"\f636"}.bi-currency-euro::before{content:"\f637"}.bi-currency-exchange::before{content:"\f638"}.bi-currency-pound::before{content:"\f639"}.bi-currency-yen::before{content:"\f63a"}.bi-dash-lg::before{content:"\f63b"}.bi-exclamation-lg::before{content:"\f63c"}.bi-file-earmark-pdf-fill::before{content:"\f63d"}.bi-file-earmark-pdf::before{content:"\f63e"}.bi-file-pdf-fill::before{content:"\f63f"}.bi-file-pdf::before{content:"\f640"}.bi-gender-ambiguous::before{content:"\f641"}.bi-gender-female::before{content:"\f642"}.bi-gender-male::before{content:"\f643"}.bi-gender-trans::before{content:"\f644"}.bi-headset-vr::before{content:"\f645"}.bi-info-lg::before{content:"\f646"}.bi-mastodon::before{content:"\f647"}.bi-messenger::before{content:"\f648"}.bi-piggy-bank-fill::before{content:"\f649"}.bi-piggy-bank::before{content:"\f64a"}.bi-pin-map-fill::before{content:"\f64b"}.bi-pin-map::before{content:"\f64c"}.bi-plus-lg::before{content:"\f64d"}.bi-question-lg::before{content:"\f64e"}.bi-recycle::before{content:"\f64f"}.bi-reddit::before{content:"\f650"}.bi-safe-fill::before{content:"\f651"}.bi-safe2-fill::before{content:"\f652"}.bi-safe2::before{content:"\f653"}.bi-sd-card-fill::before{content:"\f654"}.bi-sd-card::before{content:"\f655"}.bi-skype::before{content:"\f656"}.bi-slash-lg::before{content:"\f657"}.bi-translate::before{content:"\f658"}.bi-x-lg::before{content:"\f659"}.bi-safe::before{content:"\f65a"}.bi-apple::before{content:"\f65b"}.bi-microsoft::before{content:"\f65d"}.bi-windows::before{content:"\f65e"}.bi-behance::before{content:"\f65c"}.bi-dribbble::before{content:"\f65f"}.bi-line::before{content:"\f660"}.bi-medium::before{content:"\f661"}.bi-paypal::before{content:"\f662"}.bi-pinterest::before{content:"\f663"}.bi-signal::before{content:"\f664"}.bi-snapchat::before{content:"\f665"}.bi-spotify::before{content:"\f666"}.bi-stack-overflow::before{content:"\f667"}.bi-strava::before{content:"\f668"}.bi-wordpress::before{content:"\f669"}.bi-vimeo::before{content:"\f66a"}.bi-activity::before{content:"\f66b"}.bi-easel2-fill::before{content:"\f66c"}.bi-easel2::before{content:"\f66d"}.bi-easel3-fill::before{content:"\f66e"}.bi-easel3::before{content:"\f66f"}.bi-fan::before{content:"\f670"}.bi-fingerprint::before{content:"\f671"}.bi-graph-down-arrow::before{content:"\f672"}.bi-graph-up-arrow::before{content:"\f673"}.bi-hypnotize::before{content:"\f674"}.bi-magic::before{content:"\f675"}.bi-person-rolodex::before{content:"\f676"}.bi-person-video::before{content:"\f677"}.bi-person-video2::before{content:"\f678"}.bi-person-video3::before{content:"\f679"}.bi-person-workspace::before{content:"\f67a"}.bi-radioactive::before{content:"\f67b"}.bi-webcam-fill::before{content:"\f67c"}.bi-webcam::before{content:"\f67d"}.bi-yin-yang::before{content:"\f67e"}.bi-bandaid-fill::before{content:"\f680"}.bi-bandaid::before{content:"\f681"}.bi-bluetooth::before{content:"\f682"}.bi-body-text::before{content:"\f683"}.bi-boombox::before{content:"\f684"}.bi-boxes::before{content:"\f685"}.bi-dpad-fill::before{content:"\f686"}.bi-dpad::before{content:"\f687"}.bi-ear-fill::before{content:"\f688"}.bi-ear::before{content:"\f689"}.bi-envelope-check-fill::before{content:"\f68b"}.bi-envelope-check::before{content:"\f68c"}.bi-envelope-dash-fill::before{content:"\f68e"}.bi-envelope-dash::before{content:"\f68f"}.bi-envelope-exclamation-fill::before{content:"\f691"}.bi-envelope-exclamation::before{content:"\f692"}.bi-envelope-plus-fill::before{content:"\f693"}.bi-envelope-plus::before{content:"\f694"}.bi-envelope-slash-fill::before{content:"\f696"}.bi-envelope-slash::before{content:"\f697"}.bi-envelope-x-fill::before{content:"\f699"}.bi-envelope-x::before{content:"\f69a"}.bi-explicit-fill::before{content:"\f69b"}.bi-explicit::before{content:"\f69c"}.bi-git::before{content:"\f69d"}.bi-infinity::before{content:"\f69e"}.bi-list-columns-reverse::before{content:"\f69f"}.bi-list-columns::before{content:"\f6a0"}.bi-meta::before{content:"\f6a1"}.bi-nintendo-switch::before{content:"\f6a4"}.bi-pc-display-horizontal::before{content:"\f6a5"}.bi-pc-display::before{content:"\f6a6"}.bi-pc-horizontal::before{content:"\f6a7"}.bi-pc::before{content:"\f6a8"}.bi-playstation::before{content:"\f6a9"}.bi-plus-slash-minus::before{content:"\f6aa"}.bi-projector-fill::before{content:"\f6ab"}.bi-projector::before{content:"\f6ac"}.bi-qr-code-scan::before{content:"\f6ad"}.bi-qr-code::before{content:"\f6ae"}.bi-quora::before{content:"\f6af"}.bi-quote::before{content:"\f6b0"}.bi-robot::before{content:"\f6b1"}.bi-send-check-fill::before{content:"\f6b2"}.bi-send-check::before{content:"\f6b3"}.bi-send-dash-fill::before{content:"\f6b4"}.bi-send-dash::before{content:"\f6b5"}.bi-send-exclamation-fill::before{content:"\f6b7"}.bi-send-exclamation::before{content:"\f6b8"}.bi-send-fill::before{content:"\f6b9"}.bi-send-plus-fill::before{content:"\f6ba"}.bi-send-plus::before{content:"\f6bb"}.bi-send-slash-fill::before{content:"\f6bc"}.bi-send-slash::before{content:"\f6bd"}.bi-send-x-fill::before{content:"\f6be"}.bi-send-x::before{content:"\f6bf"}.bi-send::before{content:"\f6c0"}.bi-steam::before{content:"\f6c1"}.bi-terminal-dash::before{content:"\f6c3"}.bi-terminal-plus::before{content:"\f6c4"}.bi-terminal-split::before{content:"\f6c5"}.bi-ticket-detailed-fill::before{content:"\f6c6"}.bi-ticket-detailed::before{content:"\f6c7"}.bi-ticket-fill::before{content:"\f6c8"}.bi-ticket-perforated-fill::before{content:"\f6c9"}.bi-ticket-perforated::before{content:"\f6ca"}.bi-ticket::before{content:"\f6cb"}.bi-tiktok::before{content:"\f6cc"}.bi-window-dash::before{content:"\f6cd"}.bi-window-desktop::before{content:"\f6ce"}.bi-window-fullscreen::before{content:"\f6cf"}.bi-window-plus::before{content:"\f6d0"}.bi-window-split::before{content:"\f6d1"}.bi-window-stack::before{content:"\f6d2"}.bi-window-x::before{content:"\f6d3"}.bi-xbox::before{content:"\f6d4"}.bi-ethernet::before{content:"\f6d5"}.bi-hdmi-fill::before{content:"\f6d6"}.bi-hdmi::before{content:"\f6d7"}.bi-usb-c-fill::before{content:"\f6d8"}.bi-usb-c::before{content:"\f6d9"}.bi-usb-fill::before{content:"\f6da"}.bi-usb-plug-fill::before{content:"\f6db"}.bi-usb-plug::before{content:"\f6dc"}.bi-usb-symbol::before{content:"\f6dd"}.bi-usb::before{content:"\f6de"}.bi-boombox-fill::before{content:"\f6df"}.bi-displayport::before{content:"\f6e1"}.bi-gpu-card::before{content:"\f6e2"}.bi-memory::before{content:"\f6e3"}.bi-modem-fill::before{content:"\f6e4"}.bi-modem::before{content:"\f6e5"}.bi-motherboard-fill::before{content:"\f6e6"}.bi-motherboard::before{content:"\f6e7"}.bi-optical-audio-fill::before{content:"\f6e8"}.bi-optical-audio::before{content:"\f6e9"}.bi-pci-card::before{content:"\f6ea"}.bi-router-fill::before{content:"\f6eb"}.bi-router::before{content:"\f6ec"}.bi-thunderbolt-fill::before{content:"\f6ef"}.bi-thunderbolt::before{content:"\f6f0"}.bi-usb-drive-fill::before{content:"\f6f1"}.bi-usb-drive::before{content:"\f6f2"}.bi-usb-micro-fill::before{content:"\f6f3"}.bi-usb-micro::before{content:"\f6f4"}.bi-usb-mini-fill::before{content:"\f6f5"}.bi-usb-mini::before{content:"\f6f6"}.bi-cloud-haze2::before{content:"\f6f7"}.bi-device-hdd-fill::before{content:"\f6f8"}.bi-device-hdd::before{content:"\f6f9"}.bi-device-ssd-fill::before{content:"\f6fa"}.bi-device-ssd::before{content:"\f6fb"}.bi-displayport-fill::before{content:"\f6fc"}.bi-mortarboard-fill::before{content:"\f6fd"}.bi-mortarboard::before{content:"\f6fe"}.bi-terminal-x::before{content:"\f6ff"}.bi-arrow-through-heart-fill::before{content:"\f700"}.bi-arrow-through-heart::before{content:"\f701"}.bi-badge-sd-fill::before{content:"\f702"}.bi-badge-sd::before{content:"\f703"}.bi-bag-heart-fill::before{content:"\f704"}.bi-bag-heart::before{content:"\f705"}.bi-balloon-fill::before{content:"\f706"}.bi-balloon-heart-fill::before{content:"\f707"}.bi-balloon-heart::before{content:"\f708"}.bi-balloon::before{content:"\f709"}.bi-box2-fill::before{content:"\f70a"}.bi-box2-heart-fill::before{content:"\f70b"}.bi-box2-heart::before{content:"\f70c"}.bi-box2::before{content:"\f70d"}.bi-braces-asterisk::before{content:"\f70e"}.bi-calendar-heart-fill::before{content:"\f70f"}.bi-calendar-heart::before{content:"\f710"}.bi-calendar2-heart-fill::before{content:"\f711"}.bi-calendar2-heart::before{content:"\f712"}.bi-chat-heart-fill::before{content:"\f713"}.bi-chat-heart::before{content:"\f714"}.bi-chat-left-heart-fill::before{content:"\f715"}.bi-chat-left-heart::before{content:"\f716"}.bi-chat-right-heart-fill::before{content:"\f717"}.bi-chat-right-heart::before{content:"\f718"}.bi-chat-square-heart-fill::before{content:"\f719"}.bi-chat-square-heart::before{content:"\f71a"}.bi-clipboard-check-fill::before{content:"\f71b"}.bi-clipboard-data-fill::before{content:"\f71c"}.bi-clipboard-fill::before{content:"\f71d"}.bi-clipboard-heart-fill::before{content:"\f71e"}.bi-clipboard-heart::before{content:"\f71f"}.bi-clipboard-minus-fill::before{content:"\f720"}.bi-clipboard-plus-fill::before{content:"\f721"}.bi-clipboard-pulse::before{content:"\f722"}.bi-clipboard-x-fill::before{content:"\f723"}.bi-clipboard2-check-fill::before{content:"\f724"}.bi-clipboard2-check::before{content:"\f725"}.bi-clipboard2-data-fill::before{content:"\f726"}.bi-clipboard2-data::before{content:"\f727"}.bi-clipboard2-fill::before{content:"\f728"}.bi-clipboard2-heart-fill::before{content:"\f729"}.bi-clipboard2-heart::before{content:"\f72a"}.bi-clipboard2-minus-fill::before{content:"\f72b"}.bi-clipboard2-minus::before{content:"\f72c"}.bi-clipboard2-plus-fill::before{content:"\f72d"}.bi-clipboard2-plus::before{content:"\f72e"}.bi-clipboard2-pulse-fill::before{content:"\f72f"}.bi-clipboard2-pulse::before{content:"\f730"}.bi-clipboard2-x-fill::before{content:"\f731"}.bi-clipboard2-x::before{content:"\f732"}.bi-clipboard2::before{content:"\f733"}.bi-emoji-kiss-fill::before{content:"\f734"}.bi-emoji-kiss::before{content:"\f735"}.bi-envelope-heart-fill::before{content:"\f736"}.bi-envelope-heart::before{content:"\f737"}.bi-envelope-open-heart-fill::before{content:"\f738"}.bi-envelope-open-heart::before{content:"\f739"}.bi-envelope-paper-fill::before{content:"\f73a"}.bi-envelope-paper-heart-fill::before{content:"\f73b"}.bi-envelope-paper-heart::before{content:"\f73c"}.bi-envelope-paper::before{content:"\f73d"}.bi-filetype-aac::before{content:"\f73e"}.bi-filetype-ai::before{content:"\f73f"}.bi-filetype-bmp::before{content:"\f740"}.bi-filetype-cs::before{content:"\f741"}.bi-filetype-css::before{content:"\f742"}.bi-filetype-csv::before{content:"\f743"}.bi-filetype-doc::before{content:"\f744"}.bi-filetype-docx::before{content:"\f745"}.bi-filetype-exe::before{content:"\f746"}.bi-filetype-gif::before{content:"\f747"}.bi-filetype-heic::before{content:"\f748"}.bi-filetype-html::before{content:"\f749"}.bi-filetype-java::before{content:"\f74a"}.bi-filetype-jpg::before{content:"\f74b"}.bi-filetype-js::before{content:"\f74c"}.bi-filetype-jsx::before{content:"\f74d"}.bi-filetype-key::before{content:"\f74e"}.bi-filetype-m4p::before{content:"\f74f"}.bi-filetype-md::before{content:"\f750"}.bi-filetype-mdx::before{content:"\f751"}.bi-filetype-mov::before{content:"\f752"}.bi-filetype-mp3::before{content:"\f753"}.bi-filetype-mp4::before{content:"\f754"}.bi-filetype-otf::before{content:"\f755"}.bi-filetype-pdf::before{content:"\f756"}.bi-filetype-php::before{content:"\f757"}.bi-filetype-png::before{content:"\f758"}.bi-filetype-ppt::before{content:"\f75a"}.bi-filetype-psd::before{content:"\f75b"}.bi-filetype-py::before{content:"\f75c"}.bi-filetype-raw::before{content:"\f75d"}.bi-filetype-rb::before{content:"\f75e"}.bi-filetype-sass::before{content:"\f75f"}.bi-filetype-scss::before{content:"\f760"}.bi-filetype-sh::before{content:"\f761"}.bi-filetype-svg::before{content:"\f762"}.bi-filetype-tiff::before{content:"\f763"}.bi-filetype-tsx::before{content:"\f764"}.bi-filetype-ttf::before{content:"\f765"}.bi-filetype-txt::before{content:"\f766"}.bi-filetype-wav::before{content:"\f767"}.bi-filetype-woff::before{content:"\f768"}.bi-filetype-xls::before{content:"\f76a"}.bi-filetype-xml::before{content:"\f76b"}.bi-filetype-yml::before{content:"\f76c"}.bi-heart-arrow::before{content:"\f76d"}.bi-heart-pulse-fill::before{content:"\f76e"}.bi-heart-pulse::before{content:"\f76f"}.bi-heartbreak-fill::before{content:"\f770"}.bi-heartbreak::before{content:"\f771"}.bi-hearts::before{content:"\f772"}.bi-hospital-fill::before{content:"\f773"}.bi-hospital::before{content:"\f774"}.bi-house-heart-fill::before{content:"\f775"}.bi-house-heart::before{content:"\f776"}.bi-incognito::before{content:"\f777"}.bi-magnet-fill::before{content:"\f778"}.bi-magnet::before{content:"\f779"}.bi-person-heart::before{content:"\f77a"}.bi-person-hearts::before{content:"\f77b"}.bi-phone-flip::before{content:"\f77c"}.bi-plugin::before{content:"\f77d"}.bi-postage-fill::before{content:"\f77e"}.bi-postage-heart-fill::before{content:"\f77f"}.bi-postage-heart::before{content:"\f780"}.bi-postage::before{content:"\f781"}.bi-postcard-fill::before{content:"\f782"}.bi-postcard-heart-fill::before{content:"\f783"}.bi-postcard-heart::before{content:"\f784"}.bi-postcard::before{content:"\f785"}.bi-search-heart-fill::before{content:"\f786"}.bi-search-heart::before{content:"\f787"}.bi-sliders2-vertical::before{content:"\f788"}.bi-sliders2::before{content:"\f789"}.bi-trash3-fill::before{content:"\f78a"}.bi-trash3::before{content:"\f78b"}.bi-valentine::before{content:"\f78c"}.bi-valentine2::before{content:"\f78d"}.bi-wrench-adjustable-circle-fill::before{content:"\f78e"}.bi-wrench-adjustable-circle::before{content:"\f78f"}.bi-wrench-adjustable::before{content:"\f790"}.bi-filetype-json::before{content:"\f791"}.bi-filetype-pptx::before{content:"\f792"}.bi-filetype-xlsx::before{content:"\f793"}.bi-1-circle-fill::before{content:"\f796"}.bi-1-circle::before{content:"\f797"}.bi-1-square-fill::before{content:"\f798"}.bi-1-square::before{content:"\f799"}.bi-2-circle-fill::before{content:"\f79c"}.bi-2-circle::before{content:"\f79d"}.bi-2-square-fill::before{content:"\f79e"}.bi-2-square::before{content:"\f79f"}.bi-3-circle-fill::before{content:"\f7a2"}.bi-3-circle::before{content:"\f7a3"}.bi-3-square-fill::before{content:"\f7a4"}.bi-3-square::before{content:"\f7a5"}.bi-4-circle-fill::before{content:"\f7a8"}.bi-4-circle::before{content:"\f7a9"}.bi-4-square-fill::before{content:"\f7aa"}.bi-4-square::before{content:"\f7ab"}.bi-5-circle-fill::before{content:"\f7ae"}.bi-5-circle::before{content:"\f7af"}.bi-5-square-fill::before{content:"\f7b0"}.bi-5-square::before{content:"\f7b1"}.bi-6-circle-fill::before{content:"\f7b4"}.bi-6-circle::before{content:"\f7b5"}.bi-6-square-fill::before{content:"\f7b6"}.bi-6-square::before{content:"\f7b7"}.bi-7-circle-fill::before{content:"\f7ba"}.bi-7-circle::before{content:"\f7bb"}.bi-7-square-fill::before{content:"\f7bc"}.bi-7-square::before{content:"\f7bd"}.bi-8-circle-fill::before{content:"\f7c0"}.bi-8-circle::before{content:"\f7c1"}.bi-8-square-fill::before{content:"\f7c2"}.bi-8-square::before{content:"\f7c3"}.bi-9-circle-fill::before{content:"\f7c6"}.bi-9-circle::before{content:"\f7c7"}.bi-9-square-fill::before{content:"\f7c8"}.bi-9-square::before{content:"\f7c9"}.bi-airplane-engines-fill::before{content:"\f7ca"}.bi-airplane-engines::before{content:"\f7cb"}.bi-airplane-fill::before{content:"\f7cc"}.bi-airplane::before{content:"\f7cd"}.bi-alexa::before{content:"\f7ce"}.bi-alipay::before{content:"\f7cf"}.bi-android::before{content:"\f7d0"}.bi-android2::before{content:"\f7d1"}.bi-box-fill::before{content:"\f7d2"}.bi-box-seam-fill::before{content:"\f7d3"}.bi-browser-chrome::before{content:"\f7d4"}.bi-browser-edge::before{content:"\f7d5"}.bi-browser-firefox::before{content:"\f7d6"}.bi-browser-safari::before{content:"\f7d7"}.bi-c-circle-fill::before{content:"\f7da"}.bi-c-circle::before{content:"\f7db"}.bi-c-square-fill::before{content:"\f7dc"}.bi-c-square::before{content:"\f7dd"}.bi-capsule-pill::before{content:"\f7de"}.bi-capsule::before{content:"\f7df"}.bi-car-front-fill::before{content:"\f7e0"}.bi-car-front::before{content:"\f7e1"}.bi-cassette-fill::before{content:"\f7e2"}.bi-cassette::before{content:"\f7e3"}.bi-cc-circle-fill::before{content:"\f7e6"}.bi-cc-circle::before{content:"\f7e7"}.bi-cc-square-fill::before{content:"\f7e8"}.bi-cc-square::before{content:"\f7e9"}.bi-cup-hot-fill::before{content:"\f7ea"}.bi-cup-hot::before{content:"\f7eb"}.bi-currency-rupee::before{content:"\f7ec"}.bi-dropbox::before{content:"\f7ed"}.bi-escape::before{content:"\f7ee"}.bi-fast-forward-btn-fill::before{content:"\f7ef"}.bi-fast-forward-btn::before{content:"\f7f0"}.bi-fast-forward-circle-fill::before{content:"\f7f1"}.bi-fast-forward-circle::before{content:"\f7f2"}.bi-fast-forward-fill::before{content:"\f7f3"}.bi-fast-forward::before{content:"\f7f4"}.bi-filetype-sql::before{content:"\f7f5"}.bi-fire::before{content:"\f7f6"}.bi-google-play::before{content:"\f7f7"}.bi-h-circle-fill::before{content:"\f7fa"}.bi-h-circle::before{content:"\f7fb"}.bi-h-square-fill::before{content:"\f7fc"}.bi-h-square::before{content:"\f7fd"}.bi-indent::before{content:"\f7fe"}.bi-lungs-fill::before{content:"\f7ff"}.bi-lungs::before{content:"\f800"}.bi-microsoft-teams::before{content:"\f801"}.bi-p-circle-fill::before{content:"\f804"}.bi-p-circle::before{content:"\f805"}.bi-p-square-fill::before{content:"\f806"}.bi-p-square::before{content:"\f807"}.bi-pass-fill::before{content:"\f808"}.bi-pass::before{content:"\f809"}.bi-prescription::before{content:"\f80a"}.bi-prescription2::before{content:"\f80b"}.bi-r-circle-fill::before{content:"\f80e"}.bi-r-circle::before{content:"\f80f"}.bi-r-square-fill::before{content:"\f810"}.bi-r-square::before{content:"\f811"}.bi-repeat-1::before{content:"\f812"}.bi-repeat::before{content:"\f813"}.bi-rewind-btn-fill::before{content:"\f814"}.bi-rewind-btn::before{content:"\f815"}.bi-rewind-circle-fill::before{content:"\f816"}.bi-rewind-circle::before{content:"\f817"}.bi-rewind-fill::before{content:"\f818"}.bi-rewind::before{content:"\f819"}.bi-train-freight-front-fill::before{content:"\f81a"}.bi-train-freight-front::before{content:"\f81b"}.bi-train-front-fill::before{content:"\f81c"}.bi-train-front::before{content:"\f81d"}.bi-train-lightrail-front-fill::before{content:"\f81e"}.bi-train-lightrail-front::before{content:"\f81f"}.bi-truck-front-fill::before{content:"\f820"}.bi-truck-front::before{content:"\f821"}.bi-ubuntu::before{content:"\f822"}.bi-unindent::before{content:"\f823"}.bi-unity::before{content:"\f824"}.bi-universal-access-circle::before{content:"\f825"}.bi-universal-access::before{content:"\f826"}.bi-virus::before{content:"\f827"}.bi-virus2::before{content:"\f828"}.bi-wechat::before{content:"\f829"}.bi-yelp::before{content:"\f82a"}.bi-sign-stop-fill::before{content:"\f82b"}.bi-sign-stop-lights-fill::before{content:"\f82c"}.bi-sign-stop-lights::before{content:"\f82d"}.bi-sign-stop::before{content:"\f82e"}.bi-sign-turn-left-fill::before{content:"\f82f"}.bi-sign-turn-left::before{content:"\f830"}.bi-sign-turn-right-fill::before{content:"\f831"}.bi-sign-turn-right::before{content:"\f832"}.bi-sign-turn-slight-left-fill::before{content:"\f833"}.bi-sign-turn-slight-left::before{content:"\f834"}.bi-sign-turn-slight-right-fill::before{content:"\f835"}.bi-sign-turn-slight-right::before{content:"\f836"}.bi-sign-yield-fill::before{content:"\f837"}.bi-sign-yield::before{content:"\f838"}.bi-ev-station-fill::before{content:"\f839"}.bi-ev-station::before{content:"\f83a"}.bi-fuel-pump-diesel-fill::before{content:"\f83b"}.bi-fuel-pump-diesel::before{content:"\f83c"}.bi-fuel-pump-fill::before{content:"\f83d"}.bi-fuel-pump::before{content:"\f83e"}.bi-0-circle-fill::before{content:"\f83f"}.bi-0-circle::before{content:"\f840"}.bi-0-square-fill::before{content:"\f841"}.bi-0-square::before{content:"\f842"}.bi-rocket-fill::before{content:"\f843"}.bi-rocket-takeoff-fill::before{content:"\f844"}.bi-rocket-takeoff::before{content:"\f845"}.bi-rocket::before{content:"\f846"}.bi-stripe::before{content:"\f847"}.bi-subscript::before{content:"\f848"}.bi-superscript::before{content:"\f849"}.bi-trello::before{content:"\f84a"}.bi-envelope-at-fill::before{content:"\f84b"}.bi-envelope-at::before{content:"\f84c"}.bi-regex::before{content:"\f84d"}.bi-text-wrap::before{content:"\f84e"}.bi-sign-dead-end-fill::before{content:"\f84f"}.bi-sign-dead-end::before{content:"\f850"}.bi-sign-do-not-enter-fill::before{content:"\f851"}.bi-sign-do-not-enter::before{content:"\f852"}.bi-sign-intersection-fill::before{content:"\f853"}.bi-sign-intersection-side-fill::before{content:"\f854"}.bi-sign-intersection-side::before{content:"\f855"}.bi-sign-intersection-t-fill::before{content:"\f856"}.bi-sign-intersection-t::before{content:"\f857"}.bi-sign-intersection-y-fill::before{content:"\f858"}.bi-sign-intersection-y::before{content:"\f859"}.bi-sign-intersection::before{content:"\f85a"}.bi-sign-merge-left-fill::before{content:"\f85b"}.bi-sign-merge-left::before{content:"\f85c"}.bi-sign-merge-right-fill::before{content:"\f85d"}.bi-sign-merge-right::before{content:"\f85e"}.bi-sign-no-left-turn-fill::before{content:"\f85f"}.bi-sign-no-left-turn::before{content:"\f860"}.bi-sign-no-parking-fill::before{content:"\f861"}.bi-sign-no-parking::before{content:"\f862"}.bi-sign-no-right-turn-fill::before{content:"\f863"}.bi-sign-no-right-turn::before{content:"\f864"}.bi-sign-railroad-fill::before{content:"\f865"}.bi-sign-railroad::before{content:"\f866"}.bi-building-add::before{content:"\f867"}.bi-building-check::before{content:"\f868"}.bi-building-dash::before{content:"\f869"}.bi-building-down::before{content:"\f86a"}.bi-building-exclamation::before{content:"\f86b"}.bi-building-fill-add::before{content:"\f86c"}.bi-building-fill-check::before{content:"\f86d"}.bi-building-fill-dash::before{content:"\f86e"}.bi-building-fill-down::before{content:"\f86f"}.bi-building-fill-exclamation::before{content:"\f870"}.bi-building-fill-gear::before{content:"\f871"}.bi-building-fill-lock::before{content:"\f872"}.bi-building-fill-slash::before{content:"\f873"}.bi-building-fill-up::before{content:"\f874"}.bi-building-fill-x::before{content:"\f875"}.bi-building-fill::before{content:"\f876"}.bi-building-gear::before{content:"\f877"}.bi-building-lock::before{content:"\f878"}.bi-building-slash::before{content:"\f879"}.bi-building-up::before{content:"\f87a"}.bi-building-x::before{content:"\f87b"}.bi-buildings-fill::before{content:"\f87c"}.bi-buildings::before{content:"\f87d"}.bi-bus-front-fill::before{content:"\f87e"}.bi-bus-front::before{content:"\f87f"}.bi-ev-front-fill::before{content:"\f880"}.bi-ev-front::before{content:"\f881"}.bi-globe-americas::before{content:"\f882"}.bi-globe-asia-australia::before{content:"\f883"}.bi-globe-central-south-asia::before{content:"\f884"}.bi-globe-europe-africa::before{content:"\f885"}.bi-house-add-fill::before{content:"\f886"}.bi-house-add::before{content:"\f887"}.bi-house-check-fill::before{content:"\f888"}.bi-house-check::before{content:"\f889"}.bi-house-dash-fill::before{content:"\f88a"}.bi-house-dash::before{content:"\f88b"}.bi-house-down-fill::before{content:"\f88c"}.bi-house-down::before{content:"\f88d"}.bi-house-exclamation-fill::before{content:"\f88e"}.bi-house-exclamation::before{content:"\f88f"}.bi-house-gear-fill::before{content:"\f890"}.bi-house-gear::before{content:"\f891"}.bi-house-lock-fill::before{content:"\f892"}.bi-house-lock::before{content:"\f893"}.bi-house-slash-fill::before{content:"\f894"}.bi-house-slash::before{content:"\f895"}.bi-house-up-fill::before{content:"\f896"}.bi-house-up::before{content:"\f897"}.bi-house-x-fill::before{content:"\f898"}.bi-house-x::before{content:"\f899"}.bi-person-add::before{content:"\f89a"}.bi-person-down::before{content:"\f89b"}.bi-person-exclamation::before{content:"\f89c"}.bi-person-fill-add::before{content:"\f89d"}.bi-person-fill-check::before{content:"\f89e"}.bi-person-fill-dash::before{content:"\f89f"}.bi-person-fill-down::before{content:"\f8a0"}.bi-person-fill-exclamation::before{content:"\f8a1"}.bi-person-fill-gear::before{content:"\f8a2"}.bi-person-fill-lock::before{content:"\f8a3"}.bi-person-fill-slash::before{content:"\f8a4"}.bi-person-fill-up::before{content:"\f8a5"}.bi-person-fill-x::before{content:"\f8a6"}.bi-person-gear::before{content:"\f8a7"}.bi-person-lock::before{content:"\f8a8"}.bi-person-slash::before{content:"\f8a9"}.bi-person-up::before{content:"\f8aa"}.bi-scooter::before{content:"\f8ab"}.bi-taxi-front-fill::before{content:"\f8ac"}.bi-taxi-front::before{content:"\f8ad"}.bi-amd::before{content:"\f8ae"}.bi-database-add::before{content:"\f8af"}.bi-database-check::before{content:"\f8b0"}.bi-database-dash::before{content:"\f8b1"}.bi-database-down::before{content:"\f8b2"}.bi-database-exclamation::before{content:"\f8b3"}.bi-database-fill-add::before{content:"\f8b4"}.bi-database-fill-check::before{content:"\f8b5"}.bi-database-fill-dash::before{content:"\f8b6"}.bi-database-fill-down::before{content:"\f8b7"}.bi-database-fill-exclamation::before{content:"\f8b8"}.bi-database-fill-gear::before{content:"\f8b9"}.bi-database-fill-lock::before{content:"\f8ba"}.bi-database-fill-slash::before{content:"\f8bb"}.bi-database-fill-up::before{content:"\f8bc"}.bi-database-fill-x::before{content:"\f8bd"}.bi-database-fill::before{content:"\f8be"}.bi-database-gear::before{content:"\f8bf"}.bi-database-lock::before{content:"\f8c0"}.bi-database-slash::before{content:"\f8c1"}.bi-database-up::before{content:"\f8c2"}.bi-database-x::before{content:"\f8c3"}.bi-database::before{content:"\f8c4"}.bi-houses-fill::before{content:"\f8c5"}.bi-houses::before{content:"\f8c6"}.bi-nvidia::before{content:"\f8c7"}.bi-person-vcard-fill::before{content:"\f8c8"}.bi-person-vcard::before{content:"\f8c9"}.bi-sina-weibo::before{content:"\f8ca"}.bi-tencent-qq::before{content:"\f8cb"}.bi-wikipedia::before{content:"\f8cc"}.bi-alphabet-uppercase::before{content:"\f2a5"}.bi-alphabet::before{content:"\f68a"}.bi-amazon::before{content:"\f68d"}.bi-arrows-collapse-vertical::before{content:"\f690"}.bi-arrows-expand-vertical::before{content:"\f695"}.bi-arrows-vertical::before{content:"\f698"}.bi-arrows::before{content:"\f6a2"}.bi-ban-fill::before{content:"\f6a3"}.bi-ban::before{content:"\f6b6"}.bi-bing::before{content:"\f6c2"}.bi-cake::before{content:"\f6e0"}.bi-cake2::before{content:"\f6ed"}.bi-cookie::before{content:"\f6ee"}.bi-copy::before{content:"\f759"}.bi-crosshair::before{content:"\f769"}.bi-crosshair2::before{content:"\f794"}.bi-emoji-astonished-fill::before{content:"\f795"}.bi-emoji-astonished::before{content:"\f79a"}.bi-emoji-grimace-fill::before{content:"\f79b"}.bi-emoji-grimace::before{content:"\f7a0"}.bi-emoji-grin-fill::before{content:"\f7a1"}.bi-emoji-grin::before{content:"\f7a6"}.bi-emoji-surprise-fill::before{content:"\f7a7"}.bi-emoji-surprise::before{content:"\f7ac"}.bi-emoji-tear-fill::before{content:"\f7ad"}.bi-emoji-tear::before{content:"\f7b2"}.bi-envelope-arrow-down-fill::before{content:"\f7b3"}.bi-envelope-arrow-down::before{content:"\f7b8"}.bi-envelope-arrow-up-fill::before{content:"\f7b9"}.bi-envelope-arrow-up::before{content:"\f7be"}.bi-feather::before{content:"\f7bf"}.bi-feather2::before{content:"\f7c4"}.bi-floppy-fill::before{content:"\f7c5"}.bi-floppy::before{content:"\f7d8"}.bi-floppy2-fill::before{content:"\f7d9"}.bi-floppy2::before{content:"\f7e4"}.bi-gitlab::before{content:"\f7e5"}.bi-highlighter::before{content:"\f7f8"}.bi-marker-tip::before{content:"\f802"}.bi-nvme-fill::before{content:"\f803"}.bi-nvme::before{content:"\f80c"}.bi-opencollective::before{content:"\f80d"}.bi-pci-card-network::before{content:"\f8cd"}.bi-pci-card-sound::before{content:"\f8ce"}.bi-radar::before{content:"\f8cf"}.bi-send-arrow-down-fill::before{content:"\f8d0"}.bi-send-arrow-down::before{content:"\f8d1"}.bi-send-arrow-up-fill::before{content:"\f8d2"}.bi-send-arrow-up::before{content:"\f8d3"}.bi-sim-slash-fill::before{content:"\f8d4"}.bi-sim-slash::before{content:"\f8d5"}.bi-sourceforge::before{content:"\f8d6"}.bi-substack::before{content:"\f8d7"}.bi-threads-fill::before{content:"\f8d8"}.bi-threads::before{content:"\f8d9"}.bi-transparency::before{content:"\f8da"}.bi-twitter-x::before{content:"\f8db"}.bi-type-h4::before{content:"\f8dc"}.bi-type-h5::before{content:"\f8dd"}.bi-type-h6::before{content:"\f8de"}.bi-backpack-fill::before{content:"\f8df"}.bi-backpack::before{content:"\f8e0"}.bi-backpack2-fill::before{content:"\f8e1"}.bi-backpack2::before{content:"\f8e2"}.bi-backpack3-fill::before{content:"\f8e3"}.bi-backpack3::before{content:"\f8e4"}.bi-backpack4-fill::before{content:"\f8e5"}.bi-backpack4::before{content:"\f8e6"}.bi-brilliance::before{content:"\f8e7"}.bi-cake-fill::before{content:"\f8e8"}.bi-cake2-fill::before{content:"\f8e9"}.bi-duffle-fill::before{content:"\f8ea"}.bi-duffle::before{content:"\f8eb"}.bi-exposure::before{content:"\f8ec"}.bi-gender-neuter::before{content:"\f8ed"}.bi-highlights::before{content:"\f8ee"}.bi-luggage-fill::before{content:"\f8ef"}.bi-luggage::before{content:"\f8f0"}.bi-mailbox-flag::before{content:"\f8f1"}.bi-mailbox2-flag::before{content:"\f8f2"}.bi-noise-reduction::before{content:"\f8f3"}.bi-passport-fill::before{content:"\f8f4"}.bi-passport::before{content:"\f8f5"}.bi-person-arms-up::before{content:"\f8f6"}.bi-person-raised-hand::before{content:"\f8f7"}.bi-person-standing-dress::before{content:"\f8f8"}.bi-person-standing::before{content:"\f8f9"}.bi-person-walking::before{content:"\f8fa"}.bi-person-wheelchair::before{content:"\f8fb"}.bi-shadows::before{content:"\f8fc"}.bi-suitcase-fill::before{content:"\f8fd"}.bi-suitcase-lg-fill::before{content:"\f8fe"}.bi-suitcase-lg::before{content:"\f8ff"}.bi-suitcase::before{content:"\f900"}.bi-suitcase2-fill::before{content:"\f901"}.bi-suitcase2::before{content:"\f902"}.bi-vignette::before{content:"\f903"} \ No newline at end of file diff --git a/src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff b/src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..51204d27de92c7bb0f8bed6165b9dc888f38ff38 GIT binary patch literal 176032 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 literal 0 HcmV?d00001 diff --git a/src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff2 b/src/web/public/adminlte/bootstrap-icons/css/fonts/bootstrap-icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..92c4830216044ba21db9f4294b887312e80da38e GIT binary patch literal 130396 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Ã=hYmg-7dH4?&*NqqtUL18qtx> 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 z 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 literal 0 HcmV?d00001 diff --git a/src/web/public/adminlte/bootstrap-icons/fonts/bootstrap-icons.woff2 b/src/web/public/adminlte/bootstrap-icons/fonts/bootstrap-icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..92c4830216044ba21db9f4294b887312e80da38e GIT binary patch literal 130396 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Ã=hYmg-7dH4?&*NqqtUL18qtx> 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 z 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 + * License: Open source - MIT + */:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:rgb(5.2, 44, 101.2);--bs-secondary-text-emphasis:rgb(43.2, 46.8, 50);--bs-success-text-emphasis:rgb(10, 54, 33.6);--bs-info-text-emphasis:rgb(5.2, 80.8, 96);--bs-warning-text-emphasis:rgb(102, 77.2, 2.8);--bs-danger-text-emphasis:rgb(88, 21.2, 27.6);--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:rgb(206.6, 226, 254.6);--bs-secondary-bg-subtle:rgb(225.6, 227.4, 229);--bs-success-bg-subtle:rgb(209, 231, 220.8);--bs-info-bg-subtle:rgb(206.6, 244.4, 252);--bs-warning-bg-subtle:rgb(255, 242.6, 205.4);--bs-danger-bg-subtle:rgb(248, 214.6, 217.8);--bs-light-bg-subtle:rgb(251.5, 252, 252.5);--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:rgb(158.2, 197, 254.2);--bs-secondary-border-subtle:rgb(196.2, 199.8, 203);--bs-success-border-subtle:rgb(163, 207, 186.6);--bs-info-border-subtle:rgb(158.2, 233.8, 249);--bs-warning-border-subtle:rgb(255, 230.2, 155.8);--bs-danger-border-subtle:rgb(241, 174.2, 180.6);--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:"Source Sans 3",system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33, 37, 41, 0.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33, 37, 41, 0.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:rgb(10.4, 88, 202.4);--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:rgb(255, 242.6, 205.4);--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(13, 110, 253, 0.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:rgb(42.5, 47.5, 52.5);--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:rgb(109.8, 168, 253.8);--bs-secondary-text-emphasis:rgb(166.8, 172.2, 177);--bs-success-text-emphasis:rgb(117, 183, 152.4);--bs-info-text-emphasis:rgb(109.8, 223.2, 246);--bs-warning-text-emphasis:rgb(255, 217.8, 106.2);--bs-danger-text-emphasis:rgb(234, 133.8, 143.4);--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:rgb(2.6, 22, 50.6);--bs-secondary-bg-subtle:rgb(21.6, 23.4, 25);--bs-success-bg-subtle:rgb(5, 27, 16.8);--bs-info-bg-subtle:rgb(2.6, 40.4, 48);--bs-warning-bg-subtle:rgb(51, 38.6, 1.4);--bs-danger-bg-subtle:rgb(44, 10.6, 13.8);--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:rgb(7.8, 66, 151.8);--bs-secondary-border-subtle:rgb(64.8, 70.2, 75);--bs-success-border-subtle:rgb(15, 81, 50.4);--bs-info-border-subtle:rgb(7.8, 121.2, 144);--bs-warning-border-subtle:rgb(153, 115.8, 4.2);--bs-danger-border-subtle:rgb(132, 31.8, 41.4);--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:rgb(109.8, 168, 253.8);--bs-link-hover-color:rgb(138.84, 185.4, 254.04);--bs-link-color-rgb:110,168,254;--bs-link-hover-color-rgb:139,185,254;--bs-code-color:rgb(230.4, 132.6, 181.2);--bs-highlight-color:#dee2e6;--bs-highlight-bg:rgb(102, 77.2, 2.8);--bs-border-color:#495057;--bs-border-color-translucent:rgba(255, 255, 255, 0.15);--bs-form-valid-color:rgb(117, 183, 152.4);--bs-form-valid-border-color:rgb(117, 183, 152.4);--bs-form-invalid-color:rgb(234, 133.8, 143.4);--bs-form-invalid-border-color:rgb(234, 133.8, 143.4)}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;color:var(--bs-highlight-color);background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button{cursor:pointer;filter:grayscale(1)}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-weight:300;line-height:1.2;font-size:calc(1.625rem + 4.5vw)}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-weight:300;line-height:1.2;font-size:calc(1.575rem + 3.9vw)}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-weight:300;line-height:1.2;font-size:calc(1.525rem + 3.3vw)}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-weight:300;line-height:1.2;font-size:calc(1.475rem + 2.7vw)}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-weight:300;line-height:1.2;font-size:calc(1.425rem + 2.1vw)}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-weight:300;line-height:1.2;font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);box-shadow:var(--bs-box-shadow-sm);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb), 0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb), 0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb), 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-active{--bs-table-color-state:var(--bs-table-active-color);--bs-table-bg-state:var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:rgb(206.6, 226, 254.6);--bs-table-border-color:rgb(165.28, 180.8, 203.68);--bs-table-striped-bg:rgb(196.27, 214.7, 241.87);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(185.94, 203.4, 229.14);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(191.105, 209.05, 235.505);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:rgb(225.6, 227.4, 229);--bs-table-border-color:rgb(180.48, 181.92, 183.2);--bs-table-striped-bg:rgb(214.32, 216.03, 217.55);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(203.04, 204.66, 206.1);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(208.68, 210.345, 211.825);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:rgb(209, 231, 220.8);--bs-table-border-color:rgb(167.2, 184.8, 176.64);--bs-table-striped-bg:rgb(198.55, 219.45, 209.76);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(188.1, 207.9, 198.72);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(193.325, 213.675, 204.24);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:rgb(206.6, 244.4, 252);--bs-table-border-color:rgb(165.28, 195.52, 201.6);--bs-table-striped-bg:rgb(196.27, 232.18, 239.4);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(185.94, 219.96, 226.8);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(191.105, 226.07, 233.1);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:rgb(255, 242.6, 205.4);--bs-table-border-color:rgb(204, 194.08, 164.32);--bs-table-striped-bg:rgb(242.25, 230.47, 195.13);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(229.5, 218.34, 184.86);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(235.875, 224.405, 189.995);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:rgb(248, 214.6, 217.8);--bs-table-border-color:rgb(198.4, 171.68, 174.24);--bs-table-striped-bg:rgb(235.6, 203.87, 206.91);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(223.2, 193.14, 196.02);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(229.4, 198.505, 201.465);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:rgb(198.4, 199.2, 200);--bs-table-striped-bg:rgb(235.6, 236.55, 237.5);--bs-table-striped-color:#000;--bs-table-active-bg:rgb(223.2, 224.1, 225);--bs-table-active-color:#000;--bs-table-hover-bg:rgb(229.4, 230.325, 231.25);--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:rgb(77.4, 80.6, 83.8);--bs-table-striped-bg:rgb(44.1, 47.9, 51.7);--bs-table-striped-color:#fff;--bs-table-active-bg:rgb(55.2, 58.8, 62.4);--bs-table-active-color:#fff;--bs-table-hover-bg:rgb(49.65, 53.35, 57.05);--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);box-shadow:var(--bs-box-shadow-inset);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:rgb(134,182.5,254);outline:0;box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon,none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);box-shadow:var(--bs-box-shadow-inset);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:rgb(134,182.5,254);outline:0;box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);flex-shrink:0;width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);-webkit-print-color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:rgb(134,182.5,254);outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28134, 182.5, 254%29'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;-webkit-appearance:none;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:rgb(182.4,211.5,254.4)}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem;box-shadow:var(--bs-box-shadow-inset)}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;box-shadow:0 .1rem .25rem rgba(0,0,0,.1);-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:rgb(182.4,211.5,254.4)}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem;box-shadow:var(--bs-box-shadow-inset)}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem .75rem;overflow:hidden;color:rgba(var(--bs-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:.75rem}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>textarea:focus~label::after,.form-floating>textarea:not(:placeholder-shown)~label::after{position:absolute;inset:1rem 0.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>textarea:disabled~label::after{background-color:var(--bs-secondary-bg)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>.form-control:disabled~label,.form-floating>:disabled~label{color:#6c757d}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius)}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--bs-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:var(--bs-form-valid-border-color)}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:var(--bs-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:var(--bs-form-invalid-border-color)}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:var(--bs-box-shadow-inset),0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);box-shadow:var(--bs-btn-box-shadow);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-box-shadow),var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-box-shadow),var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color);box-shadow:var(--bs-btn-active-shadow)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-active-shadow),var(--bs-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--bs-btn-active-shadow),var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity);box-shadow:none}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:rgb(11.05, 93.5, 215.05);--bs-btn-hover-border-color:rgb(10.4, 88, 202.4);--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:rgb(10.4, 88, 202.4);--bs-btn-active-border-color:rgb(9.75, 82.5, 189.75);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:rgb(91.8, 99.45, 106.25);--bs-btn-hover-border-color:rgb(86.4, 93.6, 100);--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:rgb(86.4, 93.6, 100);--bs-btn-active-border-color:rgb(81, 87.75, 93.75);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:rgb(21.25, 114.75, 71.4);--bs-btn-hover-border-color:rgb(20, 108, 67.2);--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:rgb(20, 108, 67.2);--bs-btn-active-border-color:rgb(18.75, 101.25, 63);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:rgb(49.3, 209.95, 242.25);--bs-btn-hover-border-color:rgb(37.2, 207.3, 241.5);--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:rgb(61.4, 212.6, 243);--bs-btn-active-border-color:rgb(37.2, 207.3, 241.5);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:rgb(255, 202.3, 44.2);--bs-btn-hover-border-color:rgb(255, 199.2, 31.8);--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:rgb(255, 205.4, 56.6);--bs-btn-active-border-color:rgb(255, 199.2, 31.8);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:rgb(187, 45.05, 58.65);--bs-btn-hover-border-color:rgb(176, 42.4, 55.2);--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:rgb(176, 42.4, 55.2);--bs-btn-active-border-color:rgb(165, 39.75, 51.75);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:rgb(210.8, 211.65, 212.5);--bs-btn-hover-border-color:rgb(198.4, 199.2, 200);--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:rgb(198.4, 199.2, 200);--bs-btn-active-border-color:rgb(186, 186.75, 187.5);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:rgb(66.3, 69.7, 73.1);--bs-btn-hover-border-color:rgb(55.2, 58.8, 62.4);--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:rgb(77.4, 80.6, 83.8);--bs-btn-active-border-color:rgb(55.2, 58.8, 62.4);--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:0 0 0 #000;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:var(--bs-border-radius-lg)}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:var(--bs-body-color);--bs-dropdown-bg:var(--bs-body-bg);--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:var(--bs-border-radius);--bs-dropdown-border-width:var(--bs-border-width);--bs-dropdown-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:var(--bs-box-shadow);--bs-dropdown-link-color:var(--bs-body-color);--bs-dropdown-link-hover-color:var(--bs-body-color);--bs-dropdown-link-hover-bg:var(--bs-tertiary-bg);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:var(--bs-tertiary-color);--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius);box-shadow:var(--bs-dropdown-box-shadow)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius,0)}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--bs-border-radius)}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:calc(-1 * var(--bs-border-width))}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group.show .dropdown-toggle{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.show .dropdown-toggle.btn-link{box-shadow:none}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:calc(-1 * var(--bs-border-width))}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:var(--bs-border-width);--bs-nav-tabs-border-color:var(--bs-border-color);--bs-nav-tabs-border-radius:var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color:var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color:var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg:var(--bs-body-bg);--bs-nav-tabs-link-active-border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:var(--bs-border-radius);--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap:1rem;--bs-nav-underline-border-width:0.125rem;--bs-nav-underline-link-active-color:var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:focus,.nav-underline .nav-link:hover{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), 0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), 0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), 0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:1rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), 0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;box-shadow:none;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color:rgba(255, 255, 255, 0.55);--bs-navbar-hover-color:rgba(255, 255, 255, 0.75);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius);box-shadow:var(--bs-card-box-shadow)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child)>.card-header,.card-group>.card:not(:last-child)>.card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child)>.card-footer,.card-group>.card:not(:last-child)>.card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child)>.card-header,.card-group>.card:not(:first-child)>.card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child)>.card-footer,.card-group>.card:not(:first-child)>.card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:var(--bs-body-color);--bs-accordion-bg:var(--bs-body-bg);--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:var(--bs-border-width);--bs-accordion-border-radius:var(--bs-border-radius);--bs-accordion-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:var(--bs-body-color);--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='rgb%285.2, 44, 101.2%29' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:var(--bs-primary-text-emphasis);--bs-accordion-active-bg:var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28109.8, 168, 253.8%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28109.8, 168, 253.8%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:var(--bs-secondary-color);--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:var(--bs-body-bg);--bs-pagination-border-width:var(--bs-border-width);--bs-pagination-border-color:var(--bs-border-color);--bs-pagination-border-radius:var(--bs-border-radius);--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:var(--bs-tertiary-bg);--bs-pagination-hover-border-color:var(--bs-border-color);--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:var(--bs-secondary-bg);--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:var(--bs-secondary-color);--bs-pagination-disabled-bg:var(--bs-secondary-bg);--bs-pagination-disabled-border-color:var(--bs-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(-1 * var(--bs-border-width))}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:var(--bs-progress-height)}}.progress,.progress-stacked{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius);box-shadow:var(--bs-progress-box-shadow)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:var(--bs-body-color);--bs-list-group-bg:var(--bs-body-bg);--bs-list-group-border-color:var(--bs-border-color);--bs-list-group-border-width:var(--bs-border-width);--bs-list-group-border-radius:var(--bs-border-radius);--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:var(--bs-secondary-color);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-tertiary-bg);--bs-list-group-action-active-color:var(--bs-body-color);--bs-list-group-action-active-bg:var(--bs-secondary-bg);--bs-list-group-disabled-color:var(--bs-secondary-color);--bs-list-group-disabled-bg:var(--bs-body-bg);--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):focus,.list-group-item-action:not(.active):hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--bs-list-group-color:var(--bs-primary-text-emphasis);--bs-list-group-bg:var(--bs-primary-bg-subtle);--bs-list-group-border-color:var(--bs-primary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-primary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-primary-border-subtle);--bs-list-group-active-color:var(--bs-primary-bg-subtle);--bs-list-group-active-bg:var(--bs-primary-text-emphasis);--bs-list-group-active-border-color:var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color:var(--bs-secondary-text-emphasis);--bs-list-group-bg:var(--bs-secondary-bg-subtle);--bs-list-group-border-color:var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-secondary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-secondary-border-subtle);--bs-list-group-active-color:var(--bs-secondary-bg-subtle);--bs-list-group-active-bg:var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color:var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color:var(--bs-success-text-emphasis);--bs-list-group-bg:var(--bs-success-bg-subtle);--bs-list-group-border-color:var(--bs-success-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-success-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-success-border-subtle);--bs-list-group-active-color:var(--bs-success-bg-subtle);--bs-list-group-active-bg:var(--bs-success-text-emphasis);--bs-list-group-active-border-color:var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color:var(--bs-info-text-emphasis);--bs-list-group-bg:var(--bs-info-bg-subtle);--bs-list-group-border-color:var(--bs-info-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-info-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-info-border-subtle);--bs-list-group-active-color:var(--bs-info-bg-subtle);--bs-list-group-active-bg:var(--bs-info-text-emphasis);--bs-list-group-active-border-color:var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color:var(--bs-warning-text-emphasis);--bs-list-group-bg:var(--bs-warning-bg-subtle);--bs-list-group-border-color:var(--bs-warning-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-warning-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-warning-border-subtle);--bs-list-group-active-color:var(--bs-warning-bg-subtle);--bs-list-group-active-bg:var(--bs-warning-text-emphasis);--bs-list-group-active-border-color:var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color:var(--bs-danger-text-emphasis);--bs-list-group-bg:var(--bs-danger-bg-subtle);--bs-list-group-border-color:var(--bs-danger-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-danger-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-danger-border-subtle);--bs-list-group-active-color:var(--bs-danger-bg-subtle);--bs-list-group-active-bg:var(--bs-danger-text-emphasis);--bs-list-group-active-border-color:var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color:var(--bs-light-text-emphasis);--bs-list-group-bg:var(--bs-light-bg-subtle);--bs-list-group-border-color:var(--bs-light-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-light-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-light-border-subtle);--bs-list-group-active-color:var(--bs-light-bg-subtle);--bs-list-group-active-bg:var(--bs-light-text-emphasis);--bs-list-group-active-border-color:var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color:var(--bs-dark-text-emphasis);--bs-list-group-bg:var(--bs-dark-bg-subtle);--bs-list-group-border-color:var(--bs-dark-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-dark-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-dark-border-subtle);--bs-list-group-active-color:var(--bs-dark-bg-subtle);--bs-list-group-active-bg:var(--bs-dark-text-emphasis);--bs-list-group-active-border-color:var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;filter:var(--bs-btn-close-filter);border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}:root,[data-bs-theme=light]{--bs-btn-close-filter: }[data-bs-theme=dark]{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color:var(--bs-body-color);--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translate(0,-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);box-shadow:var(--bs-modal-box-shadow);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--bs-modal-header-padding-y));margin-right:calc(-.5 * var(--bs-modal-header-padding-x));margin-bottom:calc(-.5 * var(--bs-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:var(--bs-body-bg);--bs-popover-border-width:var(--bs-border-width);--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:var(--bs-border-radius-lg);--bs-popover-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow:var(--bs-box-shadow);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color:inherit;--bs-popover-header-bg:var(--bs-secondary-bg);--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:var(--bs-body-color);--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius);box-shadow:var(--bs-popover-box-shadow)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;filter:var(--bs-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--bs-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--bs-carousel-caption-color);text-align:center}.carousel-dark{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}:root,[data-bs-theme=light]{--bs-carousel-indicator-active-bg:#fff;--bs-carousel-caption-color:#fff;--bs-carousel-control-icon-filter: }[data-bs-theme=dark]{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}.spinner-border,.spinner-grow{display:inline-block;flex-shrink:0;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color:var(--bs-body-color);--bs-offcanvas-bg:var(--bs-body-bg);--bs-offcanvas-border-width:var(--bs-border-width);--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:var(--bs-box-shadow-sm);--bs-offcanvas-transition:transform 0.3s ease-in-out;--bs-offcanvas-title-line-height:1.5}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;box-shadow:var(--bs-offcanvas-box-shadow);transition:var(--bs-offcanvas-transition)}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(var(--bs-primary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(var(--bs-secondary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(var(--bs-success-rgb),var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(var(--bs-info-rgb),var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(var(--bs-warning-rgb),var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(var(--bs-danger-rgb),var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(var(--bs-light-rgb),var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(var(--bs-dark-rgb),var(--bs-bg-opacity,1))!important}.link-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important}.link-primary:focus,.link-primary:hover{color:RGBA(10,88,202,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important}.link-secondary:focus,.link-secondary:hover{color:RGBA(86,94,100,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important}.link-success:focus,.link-success:hover{color:RGBA(20,108,67,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important}.link-info:focus,.link-info:hover{color:RGBA(61,213,243,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important}.link-warning:focus,.link-warning:hover{color:RGBA(255,205,57,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important}.link-danger:focus,.link-danger:hover{color:RGBA(176,42,55,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important}.link-light:focus,.link-light:hover{color:RGBA(249,250,251,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important}.link-dark:focus,.link-dark:hover{color:RGBA(26,30,33,var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-body-emphasis:focus,.link-body-emphasis:hover{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,.75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x,0) var(--bs-focus-ring-y,0) var(--bs-focus-ring-blur,0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-underline-offset:0.25em;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion:reduce){.icon-link>.bi{transition:none}}.icon-link-hover:focus-visible>.bi,.icon-link-hover:hover>.bi{transform:var(--bs-icon-link-transform,translate3d(.25em,0,0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption),.visually-hidden:not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--bs-border-width);min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-none{-o-object-fit:none!important;object-fit:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--bs-box-shadow)!important}.shadow-sm{box-shadow:var(--bs-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--bs-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--bs-focus-ring-color:rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color:rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color:rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color:rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color:rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color:rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color:rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color:rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-black{--bs-border-opacity:1;border-color:rgba(var(--bs-black-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--bs-success-border-subtle)!important}.border-info-subtle{border-color:var(--bs-info-border-subtle)!important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle)!important}.border-light-subtle{border-color:var(--bs-light-border-subtle)!important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.m-n1{margin:-.25rem!important}.m-n2{margin:-.5rem!important}.m-n3{margin:-1rem!important}.m-n4{margin:-1.5rem!important}.m-n5{margin:-3rem!important}.mx-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-n1{margin-top:-.25rem!important}.mt-n2{margin-top:-.5rem!important}.mt-n3{margin-top:-1rem!important}.mt-n4{margin-top:-1.5rem!important}.mt-n5{margin-top:-3rem!important}.me-n1{margin-right:-.25rem!important}.me-n2{margin-right:-.5rem!important}.me-n3{margin-right:-1rem!important}.me-n4{margin-right:-1.5rem!important}.me-n5{margin-right:-3rem!important}.mb-n1{margin-bottom:-.25rem!important}.mb-n2{margin-bottom:-.5rem!important}.mb-n3{margin-bottom:-1rem!important}.mb-n4{margin-bottom:-1.5rem!important}.mb-n5{margin-bottom:-3rem!important}.ms-n1{margin-left:-.25rem!important}.ms-n2{margin-left:-.5rem!important}.ms-n3{margin-left:-1rem!important}.ms-n4{margin-left:-1.5rem!important}.ms-n5{margin-left:-3rem!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:3rem!important}.column-gap-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fs-7{font-size:.875rem!important}.fs-8{font-size:.75rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold{font-weight:600!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.link-opacity-10{--bs-link-opacity:0.1}.link-opacity-10-hover:hover{--bs-link-opacity:0.1}.link-opacity-25{--bs-link-opacity:0.25}.link-opacity-25-hover:hover{--bs-link-opacity:0.25}.link-opacity-50{--bs-link-opacity:0.5}.link-opacity-50-hover:hover{--bs-link-opacity:0.5}.link-opacity-75{--bs-link-opacity:0.75}.link-opacity-75-hover:hover{--bs-link-opacity:0.75}.link-opacity-100{--bs-link-opacity:1}.link-opacity-100-hover:hover{--bs-link-opacity:1}.link-offset-1{text-underline-offset:0.125em!important}.link-offset-1-hover:hover{text-underline-offset:0.125em!important}.link-offset-2{text-underline-offset:0.25em!important}.link-offset-2-hover:hover{text-underline-offset:0.25em!important}.link-offset-3{text-underline-offset:0.375em!important}.link-offset-3-hover:hover{text-underline-offset:0.375em!important}.link-underline-primary{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-secondary{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-success{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important}.link-underline-info{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important}.link-underline-warning{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important}.link-underline-danger{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important}.link-underline-light{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important}.link-underline-dark{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important}.link-underline{--bs-link-underline-opacity:1;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-underline-opacity-0{--bs-link-underline-opacity:0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity:0}.link-underline-opacity-10{--bs-link-underline-opacity:0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity:0.1}.link-underline-opacity-25{--bs-link-underline-opacity:0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity:0.25}.link-underline-opacity-50{--bs-link-underline-opacity:0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity:0.5}.link-underline-opacity-75{--bs-link-underline-opacity:0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity:0.75}.link-underline-opacity-100{--bs-link-underline-opacity:1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-body-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-bg-rgb),var(--bs-bg-opacity))!important}.bg-body-tertiary{--bs-bg-opacity:1;background-color:rgba(var(--bs-tertiary-bg-rgb),var(--bs-bg-opacity))!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle)!important}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm)!important;border-top-right-radius:var(--bs-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg)!important;border-top-right-radius:var(--bs-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl)!important;border-top-right-radius:var(--bs-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl)!important;border-top-right-radius:var(--bs-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill)!important;border-top-right-radius:var(--bs-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm)!important;border-bottom-right-radius:var(--bs-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg)!important;border-bottom-right-radius:var(--bs-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl)!important;border-bottom-right-radius:var(--bs-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-right-radius:var(--bs-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill)!important;border-bottom-right-radius:var(--bs-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm)!important;border-bottom-left-radius:var(--bs-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg)!important;border-bottom-left-radius:var(--bs-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl)!important;border-bottom-left-radius:var(--bs-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-left-radius:var(--bs-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill)!important;border-bottom-left-radius:var(--bs-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm)!important;border-top-left-radius:var(--bs-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg)!important;border-top-left-radius:var(--bs-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl)!important;border-top-left-radius:var(--bs-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl)!important;border-top-left-radius:var(--bs-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill)!important;border-top-left-radius:var(--bs-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-sm-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-sm-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-sm-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-sm-none{-o-object-fit:none!important;object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.m-sm-n1{margin:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.m-sm-n3{margin:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mx-sm-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-sm-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-sm-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-sm-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-sm-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-sm-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-sm-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-sm-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-sm-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-sm-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-sm-n1{margin-top:-.25rem!important}.mt-sm-n2{margin-top:-.5rem!important}.mt-sm-n3{margin-top:-1rem!important}.mt-sm-n4{margin-top:-1.5rem!important}.mt-sm-n5{margin-top:-3rem!important}.me-sm-n1{margin-right:-.25rem!important}.me-sm-n2{margin-right:-.5rem!important}.me-sm-n3{margin-right:-1rem!important}.me-sm-n4{margin-right:-1.5rem!important}.me-sm-n5{margin-right:-3rem!important}.mb-sm-n1{margin-bottom:-.25rem!important}.mb-sm-n2{margin-bottom:-.5rem!important}.mb-sm-n3{margin-bottom:-1rem!important}.mb-sm-n4{margin-bottom:-1.5rem!important}.mb-sm-n5{margin-bottom:-3rem!important}.ms-sm-n1{margin-left:-.25rem!important}.ms-sm-n2{margin-left:-.5rem!important}.ms-sm-n3{margin-left:-1rem!important}.ms-sm-n4{margin-left:-1.5rem!important}.ms-sm-n5{margin-left:-3rem!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:3rem!important}.column-gap-sm-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-sm-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-sm-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-sm-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-sm-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-sm-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-md-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-md-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-md-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-md-none{-o-object-fit:none!important;object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.m-md-n1{margin:-.25rem!important}.m-md-n2{margin:-.5rem!important}.m-md-n3{margin:-1rem!important}.m-md-n4{margin:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mx-md-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-md-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-md-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-md-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-md-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-md-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-md-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-md-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-md-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-md-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-md-n1{margin-top:-.25rem!important}.mt-md-n2{margin-top:-.5rem!important}.mt-md-n3{margin-top:-1rem!important}.mt-md-n4{margin-top:-1.5rem!important}.mt-md-n5{margin-top:-3rem!important}.me-md-n1{margin-right:-.25rem!important}.me-md-n2{margin-right:-.5rem!important}.me-md-n3{margin-right:-1rem!important}.me-md-n4{margin-right:-1.5rem!important}.me-md-n5{margin-right:-3rem!important}.mb-md-n1{margin-bottom:-.25rem!important}.mb-md-n2{margin-bottom:-.5rem!important}.mb-md-n3{margin-bottom:-1rem!important}.mb-md-n4{margin-bottom:-1.5rem!important}.mb-md-n5{margin-bottom:-3rem!important}.ms-md-n1{margin-left:-.25rem!important}.ms-md-n2{margin-left:-.5rem!important}.ms-md-n3{margin-left:-1rem!important}.ms-md-n4{margin-left:-1.5rem!important}.ms-md-n5{margin-left:-3rem!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:3rem!important}.column-gap-md-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-md-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-md-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-md-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-md-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-md-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-lg-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-lg-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-lg-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-lg-none{-o-object-fit:none!important;object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.m-lg-n1{margin:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.m-lg-n3{margin:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mx-lg-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-lg-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-lg-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-lg-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-lg-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-lg-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-lg-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-lg-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-lg-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-lg-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-lg-n1{margin-top:-.25rem!important}.mt-lg-n2{margin-top:-.5rem!important}.mt-lg-n3{margin-top:-1rem!important}.mt-lg-n4{margin-top:-1.5rem!important}.mt-lg-n5{margin-top:-3rem!important}.me-lg-n1{margin-right:-.25rem!important}.me-lg-n2{margin-right:-.5rem!important}.me-lg-n3{margin-right:-1rem!important}.me-lg-n4{margin-right:-1.5rem!important}.me-lg-n5{margin-right:-3rem!important}.mb-lg-n1{margin-bottom:-.25rem!important}.mb-lg-n2{margin-bottom:-.5rem!important}.mb-lg-n3{margin-bottom:-1rem!important}.mb-lg-n4{margin-bottom:-1.5rem!important}.mb-lg-n5{margin-bottom:-3rem!important}.ms-lg-n1{margin-left:-.25rem!important}.ms-lg-n2{margin-left:-.5rem!important}.ms-lg-n3{margin-left:-1rem!important}.ms-lg-n4{margin-left:-1.5rem!important}.ms-lg-n5{margin-left:-3rem!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:3rem!important}.column-gap-lg-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-lg-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-lg-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-lg-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-lg-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-lg-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xl-none{-o-object-fit:none!important;object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.m-xl-n1{margin:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.m-xl-n3{margin:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mx-xl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xl-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-xl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xl-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-xl-n1{margin-top:-.25rem!important}.mt-xl-n2{margin-top:-.5rem!important}.mt-xl-n3{margin-top:-1rem!important}.mt-xl-n4{margin-top:-1.5rem!important}.mt-xl-n5{margin-top:-3rem!important}.me-xl-n1{margin-right:-.25rem!important}.me-xl-n2{margin-right:-.5rem!important}.me-xl-n3{margin-right:-1rem!important}.me-xl-n4{margin-right:-1.5rem!important}.me-xl-n5{margin-right:-3rem!important}.mb-xl-n1{margin-bottom:-.25rem!important}.mb-xl-n2{margin-bottom:-.5rem!important}.mb-xl-n3{margin-bottom:-1rem!important}.mb-xl-n4{margin-bottom:-1.5rem!important}.mb-xl-n5{margin-bottom:-3rem!important}.ms-xl-n1{margin-left:-.25rem!important}.ms-xl-n2{margin-left:-.5rem!important}.ms-xl-n3{margin-left:-1rem!important}.ms-xl-n4{margin-left:-1.5rem!important}.ms-xl-n5{margin-left:-3rem!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:3rem!important}.column-gap-xl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xxl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xxl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xxl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xxl-none{-o-object-fit:none!important;object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.m-xxl-n1{margin:-.25rem!important}.m-xxl-n2{margin:-.5rem!important}.m-xxl-n3{margin:-1rem!important}.m-xxl-n4{margin:-1.5rem!important}.m-xxl-n5{margin:-3rem!important}.mx-xxl-n1{margin-right:-.25rem!important;margin-left:-.25rem!important}.mx-xxl-n2{margin-right:-.5rem!important;margin-left:-.5rem!important}.mx-xxl-n3{margin-right:-1rem!important;margin-left:-1rem!important}.mx-xxl-n4{margin-right:-1.5rem!important;margin-left:-1.5rem!important}.mx-xxl-n5{margin-right:-3rem!important;margin-left:-3rem!important}.my-xxl-n1{margin-top:-.25rem!important;margin-bottom:-.25rem!important}.my-xxl-n2{margin-top:-.5rem!important;margin-bottom:-.5rem!important}.my-xxl-n3{margin-top:-1rem!important;margin-bottom:-1rem!important}.my-xxl-n4{margin-top:-1.5rem!important;margin-bottom:-1.5rem!important}.my-xxl-n5{margin-top:-3rem!important;margin-bottom:-3rem!important}.mt-xxl-n1{margin-top:-.25rem!important}.mt-xxl-n2{margin-top:-.5rem!important}.mt-xxl-n3{margin-top:-1rem!important}.mt-xxl-n4{margin-top:-1.5rem!important}.mt-xxl-n5{margin-top:-3rem!important}.me-xxl-n1{margin-right:-.25rem!important}.me-xxl-n2{margin-right:-.5rem!important}.me-xxl-n3{margin-right:-1rem!important}.me-xxl-n4{margin-right:-1.5rem!important}.me-xxl-n5{margin-right:-3rem!important}.mb-xxl-n1{margin-bottom:-.25rem!important}.mb-xxl-n2{margin-bottom:-.5rem!important}.mb-xxl-n3{margin-bottom:-1rem!important}.mb-xxl-n4{margin-bottom:-1.5rem!important}.mb-xxl-n5{margin-bottom:-3rem!important}.ms-xxl-n1{margin-left:-.25rem!important}.ms-xxl-n2{margin-left:-.5rem!important}.ms-xxl-n3{margin-left:-1rem!important}.ms-xxl-n4{margin-left:-1.5rem!important}.ms-xxl-n5{margin-left:-3rem!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:3rem!important}.column-gap-xxl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xxl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xxl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xxl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xxl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xxl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}}@keyframes flipInX{0%{opacity:0;transition-timing-function:ease-in;transform:perspective(400px) rotate3d(1,0,0,90deg)}40%{transition-timing-function:ease-in;transform:perspective(400px) rotate3d(1,0,0,-20deg)}60%{opacity:1;transform:perspective(400px) rotate3d(1,0,0,10deg)}80%{transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{transform:perspective(400px)}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes shake{0%{transform:translate(2px,1px) rotate(0)}10%{transform:translate(-1px,-2px) rotate(-2deg)}20%{transform:translate(-3px,0) rotate(3deg)}30%{transform:translate(0,2px) rotate(0)}40%{transform:translate(1px,-1px) rotate(1deg)}50%{transform:translate(-1px,2px) rotate(-1deg)}60%{transform:translate(-3px,1px) rotate(0)}70%{transform:translate(2px,1px) rotate(-2deg)}80%{transform:translate(-1px,-1px) rotate(4deg)}90%{transform:translate(2px,2px) rotate(0)}100%{transform:translate(1px,-2px) rotate(-1deg)}}@keyframes wobble{0%{transform:none}15%{transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{transform:none}}:root,[data-bs-theme=light]{--lte-sidebar-width:250px}.app-wrapper{position:relative;display:grid;grid-template-areas:"lte-app-sidebar lte-app-header" "lte-app-sidebar lte-app-main" "lte-app-sidebar lte-app-footer";grid-template-rows:min-content 1fr min-content;grid-template-columns:auto 1fr;grid-gap:0;align-content:stretch;align-items:stretch;max-width:100vw;min-height:100vh}.app-wrapper>*{min-width:0}.app-content{padding:0 .5rem}.app-header{z-index:1034;grid-area:lte-app-header;max-width:100vw;border-bottom:1px solid var(--bs-border-color);transition:.3s ease-in-out}@media (prefers-reduced-motion:reduce){.app-header{transition:none}}.app-header .nav-link{position:relative;height:2.5rem}.navbar-badge{position:absolute;top:9px;right:5px;padding:2px 4px;font-size:.6rem;font-weight:400}.fixed-header .app-header{position:sticky;top:0;z-index:1030}@media (min-width:576px){.fixed-header.sidebar-expand-sm .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand-sm .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}}@media (min-width:768px){.fixed-header.sidebar-expand-md .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand-md .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}}@media (min-width:992px){.fixed-header.sidebar-expand-lg .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand-lg .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}}@media (min-width:1200px){.fixed-header.sidebar-expand-xl .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand-xl .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}}@media (min-width:1400px){.fixed-header.sidebar-expand-xxl .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand-xxl .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}}.fixed-header.sidebar-expand .app-sidebar{position:sticky;top:0;max-height:100vh}.fixed-header.sidebar-expand .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.app-sidebar{--lte-sidebar-hover-bg:rgba(0, 0, 0, 0.1);--lte-sidebar-color:#343a40;--lte-sidebar-hover-color:#212529;--lte-sidebar-active-color:#000;--lte-sidebar-menu-active-bg:rgba(0, 0, 0, 0.1);--lte-sidebar-menu-active-color:#000;--lte-sidebar-submenu-bg:transparent;--lte-sidebar-submenu-color:#777;--lte-sidebar-submenu-hover-color:#000;--lte-sidebar-submenu-hover-bg:rgba(0, 0, 0, 0.1);--lte-sidebar-submenu-active-color:#212529;--lte-sidebar-submenu-active-bg:rgba(0, 0, 0, 0.1);--lte-sidebar-header-color:rgb(49.4, 55.1, 60.8);z-index:1038;grid-area:lte-app-sidebar;min-width:var(--lte-sidebar-width);max-width:var(--lte-sidebar-width);transition:min-width .3s ease-in-out,max-width .3s ease-in-out,margin-left .3s ease-in-out,margin-right .3s ease-in-out}@media (prefers-reduced-motion:reduce){.app-sidebar{transition:none}}.sidebar-brand{display:flex;align-items:center;justify-content:center;height:3.5rem;padding:.8125rem .5rem;overflow:hidden;font-size:1.25rem;white-space:nowrap;border-bottom:1px solid var(--bs-border-color);transition:width .3s ease-in-out}@media (prefers-reduced-motion:reduce){.sidebar-brand{transition:none}}.sidebar-brand .brand-link{display:flex;align-items:center;text-decoration:none}.sidebar-brand .brand-link .brand-image{float:left;width:auto;max-height:33px;line-height:.8}.sidebar-brand .brand-link .brand-image-xs{float:left;width:auto;max-height:33px;margin-top:-.1rem;line-height:.8}.sidebar-brand .brand-link .brand-image-xl{width:auto;max-height:40px;line-height:.8}.sidebar-brand .brand-link .brand-image-xl.single{margin-top:-.3rem}.sidebar-brand .brand-text{margin-left:.5rem;color:rgba(var(--bs-emphasis-color-rgb),.8);transition:flex .3s ease-in-out,width .3s ease-in-out}@media (prefers-reduced-motion:reduce){.sidebar-brand .brand-text{transition:none}}.sidebar-brand .brand-text:hover{color:var(--bs-emphasis-color)}.sidebar-wrapper{padding-top:.5rem;padding-right:.5rem;padding-bottom:.5rem;padding-left:.5rem;overscroll-behavior:contain;scrollbar-color:var(--bs-secondary-bg) transparent}.sidebar-wrapper::-webkit-scrollbar-thumb{background-color:var(--bs-secondary-bg)}.sidebar-wrapper::-webkit-scrollbar-track{background-color:transparent}.sidebar-wrapper::-webkit-scrollbar-corner{background-color:transparent}.sidebar-wrapper{scrollbar-width:thin}.sidebar-wrapper::-webkit-scrollbar{width:.5rem;height:.5rem}.sidebar-wrapper .nav-item{max-width:100%}.sidebar-wrapper .nav-link{display:flex;justify-content:flex-start}.sidebar-wrapper .nav-link p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar-wrapper .nav-icon{display:flex;align-items:center;justify-content:center;min-width:1.5rem;max-width:1.5rem}.sidebar-wrapper .sidebar-menu>.nav-item>.nav-link{color:var(--lte-sidebar-color)}.sidebar-wrapper .sidebar-menu>.nav-item>.nav-link:focus,.sidebar-wrapper .sidebar-menu>.nav-item>.nav-link:hover{color:var(--lte-sidebar-hover-color);background-color:var(--lte-sidebar-hover-bg)}.sidebar-wrapper .sidebar-menu>.nav-item>.nav-link.active{color:var(--lte-sidebar-menu-active-color);background-color:var(--lte-sidebar-menu-active-bg)}.sidebar-wrapper .sidebar-menu>.nav-item.menu-open>.nav-link{color:var(--lte-sidebar-hover-color);background-color:var(--lte-sidebar-hover-bg)}.sidebar-wrapper .sidebar-menu>.nav-item.menu-open>.nav-link.active{color:var(--lte-sidebar-menu-active-color);background-color:var(--lte-sidebar-menu-active-bg)}.sidebar-wrapper .sidebar-menu>.nav-item>.nav-treeview{background-color:var(--lte-sidebar-submenu-bg)}.sidebar-wrapper .nav-header{display:inline;overflow:hidden;color:var(--lte-sidebar-header-color);text-overflow:ellipsis;background-color:inherit}.sidebar-wrapper a{color:var(--lte-sidebar-color)}.sidebar-wrapper .nav-treeview>.nav-item>.nav-link{color:var(--lte-sidebar-submenu-color)}.sidebar-wrapper .nav-treeview>.nav-item>.nav-link:focus,.sidebar-wrapper .nav-treeview>.nav-item>.nav-link:hover{color:var(--lte-sidebar-submenu-hover-color);background-color:var(--lte-sidebar-submenu-hover-bg)}.sidebar-wrapper .nav-treeview>.nav-item>.nav-link.active{color:var(--lte-sidebar-submenu-active-color);background-color:var(--lte-sidebar-submenu-active-bg)}.sidebar-menu .nav-item>.nav-link{margin-bottom:.2rem}.sidebar-menu .nav-item>.nav-link .nav-arrow{transition:transform ease-in-out .3s}@media (prefers-reduced-motion:reduce){.sidebar-menu .nav-item>.nav-link .nav-arrow{transition:none}}.sidebar-menu .nav-item>.nav-link .nav-arrow{transform:translateY(-50%);animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both}.sidebar-menu .nav-link>.nav-badge,.sidebar-menu .nav-link>p>.nav-badge{position:absolute;top:50%;right:1rem;transform:translateY(-50%)}.sidebar-menu .nav-link>.nav-arrow,.sidebar-menu .nav-link>p>.nav-arrow{position:absolute;top:50%;right:1rem}.sidebar-menu .nav-link{position:relative;width:100%;transition:width ease-in-out .3s}@media (prefers-reduced-motion:reduce){.sidebar-menu .nav-link{transition:none}}.sidebar-menu .nav-link{border-radius:.375rem}.sidebar-menu .nav-link p{display:inline;padding-left:.5rem;margin:0}.sidebar-menu .nav-header{position:relative;width:100%;padding:.5rem .75rem;font-size:.9rem;transition:width ease-in-out .3s}@media (prefers-reduced-motion:reduce){.sidebar-menu .nav-header{transition:none}}.sidebar-menu .nav-treeview{display:none;padding:0;list-style:none}.sidebar-menu .menu-open>.nav-treeview{display:block}.sidebar-menu .menu-open>.nav-link .nav-arrow{transform:translateY(-50%) rotate(90deg)}.sidebar-menu .nav-link>.nav-arrow,.sidebar-menu .nav-link>.nav-badge,.sidebar-menu .nav-link>p>.nav-arrow,.sidebar-menu .nav-link>p>.nav-badge{right:1rem!important;left:auto!important}.nav-indent .nav-treeview{padding-left:.5rem}.nav-compact.nav-indent .nav-treeview{padding-left:0}.nav-compact.nav-indent .nav-treeview .nav-item{padding-left:.5rem}.sidebar-mini.sidebar-collapse.nav-indent .app-sidebar:hover .nav-treeview{padding-left:0}.sidebar-mini.sidebar-collapse.nav-indent .app-sidebar:hover .nav-treeview .nav-item{padding-left:.5rem}.sidebar-collapse.nav-compact.nav-indent .nav-treeview .nav-item{padding-left:0}.nav-compact .nav-link{border-radius:0;margin-bottom:0!important}.sidebar-menu,.sidebar-menu .nav-link,.sidebar-menu>.nav-header{white-space:nowrap}.logo-xl,.logo-xs{position:absolute;visibility:visible;opacity:1}.logo-xl.brand-image-xs,.logo-xs.brand-image-xs{top:12px;left:18px}.logo-xl.brand-image-xl,.logo-xs.brand-image-xl{top:6px;left:12px}.logo-xs{visibility:hidden;opacity:0}.logo-xs.brand-image-xl{top:8px;left:16px}.brand-link.logo-switch::before{content:" "}.sidebar-mini.sidebar-collapse .app-sidebar{min-width:4.6rem;max-width:4.6rem}.sidebar-mini.sidebar-collapse .sidebar-menu .nav-header{display:none}.sidebar-mini.sidebar-collapse .sidebar-menu .nav-link{width:3.6rem}.sidebar-mini.sidebar-collapse .sidebar-menu .nav-link p{display:inline-block;width:0;white-space:nowrap}.sidebar-mini.sidebar-collapse .sidebar-menu .nav-arrow,.sidebar-mini.sidebar-collapse .sidebar-menu .nav-badge{display:none;animation-name:fadeOut;animation-duration:.3s;animation-fill-mode:both}.sidebar-mini.sidebar-collapse .brand-text{display:inline-block;max-width:0;overflow:hidden}.sidebar-mini.sidebar-collapse .brand-text,.sidebar-mini.sidebar-collapse .logo-xl,.sidebar-mini.sidebar-collapse .nav-arrow,.sidebar-mini.sidebar-collapse .sidebar-menu .nav-link p{visibility:hidden;animation-name:fadeOut;animation-duration:.3s;animation-fill-mode:both}.sidebar-mini.sidebar-collapse .logo-xs{display:inline-block;visibility:visible;animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover{min-width:var(--lte-sidebar-width);max-width:var(--lte-sidebar-width)}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .sidebar-menu .nav-header{display:inline}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .sidebar-menu .nav-link{width:auto}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .brand-text,.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .logo-xl,.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .sidebar-menu .nav-link p{width:auto;margin-left:0;visibility:visible;animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .brand-text{display:inline;max-width:inherit;margin-left:.5rem;animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .nav-arrow,.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .nav-badge{display:inline-block;visibility:visible;animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .nav-link p{padding-left:.5rem}.sidebar-mini.sidebar-collapse:not(.sidebar-without-hover) .app-sidebar:hover .logo-xs{visibility:hidden;animation-name:fadeOut;animation-duration:.3s;animation-fill-mode:both}.sidebar-collapse:not(.sidebar-mini) .app-sidebar{margin-left:calc(var(--lte-sidebar-width) * -1)}@media (min-width:576px){.sidebar-expand-sm.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand-sm.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand-sm.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand-sm.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand-sm.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-sm.sidebar-open .nav-link>.nav-badge,.sidebar-expand-sm.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand-sm.sidebar-open .nav-link>.nav-arrow,.sidebar-expand-sm.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}}@media (max-width:575.98px){.sidebar-expand-sm::before{display:none;content:"575.98px"}.sidebar-expand-sm .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand-sm .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-sm.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand-sm.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}}@media (min-width:768px){.sidebar-expand-md.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand-md.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand-md.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand-md.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand-md.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-md.sidebar-open .nav-link>.nav-badge,.sidebar-expand-md.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand-md.sidebar-open .nav-link>.nav-arrow,.sidebar-expand-md.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}}@media (max-width:767.98px){.sidebar-expand-md::before{display:none;content:"767.98px"}.sidebar-expand-md .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand-md .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-md.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand-md.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}}@media (min-width:992px){.sidebar-expand-lg.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand-lg.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand-lg.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand-lg.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand-lg.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-lg.sidebar-open .nav-link>.nav-badge,.sidebar-expand-lg.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand-lg.sidebar-open .nav-link>.nav-arrow,.sidebar-expand-lg.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}}@media (max-width:991.98px){.sidebar-expand-lg::before{display:none;content:"991.98px"}.sidebar-expand-lg .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand-lg .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-lg.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand-lg.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}}@media (min-width:1200px){.sidebar-expand-xl.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand-xl.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand-xl.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand-xl.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand-xl.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-xl.sidebar-open .nav-link>.nav-badge,.sidebar-expand-xl.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand-xl.sidebar-open .nav-link>.nav-arrow,.sidebar-expand-xl.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}}@media (max-width:1199.98px){.sidebar-expand-xl::before{display:none;content:"1199.98px"}.sidebar-expand-xl .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand-xl .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-xl.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand-xl.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}}@media (min-width:1400px){.sidebar-expand-xxl.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand-xxl.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand-xxl.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand-xxl.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand-xxl.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-xxl.sidebar-open .nav-link>.nav-badge,.sidebar-expand-xxl.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand-xxl.sidebar-open .nav-link>.nav-arrow,.sidebar-expand-xxl.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}}@media (max-width:1399.98px){.sidebar-expand-xxl::before{display:none;content:"1399.98px"}.sidebar-expand-xxl .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand-xxl .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand-xxl.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand-xxl.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}}.sidebar-expand.layout-fixed .app-main-wrapper{display:flex;flex-direction:column;min-height:100vh}.sidebar-expand.layout-fixed .app-sidebar-wrapper{position:relative}.sidebar-expand.layout-fixed .app-main{flex:1 1 auto;overflow:auto}.sidebar-expand.layout-fixed .app-sidebar{position:sticky;top:0;bottom:0;max-height:100vh}.sidebar-expand.layout-fixed .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand.sidebar-open .nav-link>.nav-badge,.sidebar-expand.sidebar-open .nav-link>p>.nav-badge{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand.sidebar-open .nav-link>.nav-arrow,.sidebar-expand.sidebar-open .nav-link>p>.nav-arrow{animation-name:fadeIn;animation-duration:.3s;animation-fill-mode:both;animation-delay:.3s}.sidebar-expand::before{display:none;content:""}.sidebar-expand .app-sidebar{position:fixed;top:0;bottom:0;max-height:100vh;margin-left:calc(var(--lte-sidebar-width) * -1)}.sidebar-expand .app-sidebar .sidebar-wrapper{height:calc(100vh - (calc(3.5rem + 1px)));overflow-x:hidden;overflow-y:auto}.sidebar-expand.sidebar-open .app-sidebar{margin-left:0}.sidebar-expand.sidebar-open .sidebar-overlay{position:absolute;inset:0;z-index:1037;width:100%;height:100%;cursor:pointer;visibility:visible;background-color:rgba(0,0,0,.2);animation-name:fadeIn;animation-fill-mode:both}.app-sidebar .brand-text,.app-sidebar .logo-xl,.app-sidebar .logo-xs,.sidebar-menu .nav-link p{transition:margin-left .3s linear,opacity .3s ease,visibility .3s ease}@media (prefers-reduced-motion:reduce){.app-sidebar .brand-text,.app-sidebar .logo-xl,.app-sidebar .logo-xs,.sidebar-menu .nav-link p{transition:none}}.app-loaded.sidebar-mini.sidebar-collapse .brand-text,.app-loaded.sidebar-mini.sidebar-collapse .sidebar-menu .nav-link p{animation-duration:.3s}body:not(.app-loaded) .app-footer,body:not(.app-loaded) .app-header,body:not(.app-loaded) .app-main,body:not(.app-loaded) .app-sidebar{transition:none!important}@media (prefers-reduced-motion:reduce){body:not(.app-loaded) .app-footer,body:not(.app-loaded) .app-header,body:not(.app-loaded) .app-main,body:not(.app-loaded) .app-sidebar{transition:none}}body:not(.app-loaded) .app-footer,body:not(.app-loaded) .app-header,body:not(.app-loaded) .app-main,body:not(.app-loaded) .app-sidebar{animation-duration:0s!important}.hold-transition .app-footer,.hold-transition .app-header,.hold-transition .app-main,.hold-transition .app-sidebar,.hold-transition .nav-arrow,.hold-transition .nav-badge{transition:none!important}@media (prefers-reduced-motion:reduce){.hold-transition .app-footer,.hold-transition .app-header,.hold-transition .app-main,.hold-transition .app-sidebar,.hold-transition .nav-arrow,.hold-transition .nav-badge{transition:none}}.hold-transition .app-footer,.hold-transition .app-header,.hold-transition .app-main,.hold-transition .app-sidebar,.hold-transition .nav-arrow,.hold-transition .nav-badge{animation-duration:0s!important}[data-bs-theme=dark] .app-sidebar,[data-bs-theme=dark].app-sidebar{--lte-sidebar-hover-bg:rgba(255, 255, 255, 0.1);--lte-sidebar-color:#c2c7d0;--lte-sidebar-hover-color:#fff;--lte-sidebar-active-color:#fff;--lte-sidebar-menu-active-bg:rgba(255, 255, 255, 0.1);--lte-sidebar-menu-active-color:#fff;--lte-sidebar-submenu-bg:transparent;--lte-sidebar-submenu-color:#c2c7d0;--lte-sidebar-submenu-hover-color:#fff;--lte-sidebar-submenu-hover-bg:rgba(255, 255, 255, 0.1);--lte-sidebar-submenu-active-color:#fff;--lte-sidebar-submenu-active-bg:rgba(255, 255, 255, 0.1);--lte-sidebar-header-color:rgb(197.05, 201.8, 210.35)}.app-main{position:relative;display:flex;flex-direction:column;grid-area:lte-app-main;max-width:100vw;padding-bottom:.75rem;transition:.3s ease-in-out}@media (prefers-reduced-motion:reduce){.app-main{transition:none}}.app-main .app-content-header{padding:1rem .5rem}.app-main .app-content-header .breadcrumb{padding:0;margin-bottom:0;line-height:2.5rem}.app-main .app-content-header .breadcrumb a{color:var(--bs-link-hover-color);text-decoration:none}.app-main .app-content-bottom-area,.app-main .app-content-top-area{color:var(--bs-secondary-color);background-color:var(--bs-body-bg)}.app-main .app-content-top-area{padding:1rem 0;border-bottom:1px solid var(--bs-border-color)}.app-main .app-content-bottom-area{padding:1rem 0;margin-top:auto;margin-bottom:-.75rem;border-top:1px solid var(--bs-border-color)}.app-footer{grid-area:lte-app-footer;width:inherit;max-width:100vw;min-height:3rem;padding:1rem;color:var(--bs-secondary-color);background-color:var(--bs-body-bg);border-top:1px solid var(--bs-border-color);transition:.3s ease-in-out}@media (prefers-reduced-motion:reduce){.app-footer{transition:none}}.fixed-footer .app-footer{position:sticky;bottom:0;z-index:1030}.fixed-footer.layout-fixed .app-main{min-height:0}.dropdown-menu{overflow:hidden}.fs-7 .dropdown-menu{font-size:.875rem!important}.fs-7 .dropdown-toggle::after{vertical-align:.2rem}.dropdown-item-title{margin:0;font-size:1rem}.dropdown-icon::after{margin-left:0}.dropdown-menu-lg{min-width:280px;max-width:300px;padding:0}.dropdown-menu-lg .dropdown-divider{margin:0}.dropdown-menu-lg .dropdown-item{padding:.5rem 1rem}.dropdown-menu-lg p{margin:0;word-wrap:break-word;white-space:normal}.dropdown-submenu{position:relative}.dropdown-submenu>a::after{border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid;float:right;margin-top:.5rem;margin-left:.5rem}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:0;margin-left:0}.dropdown-hover .dropdown-submenu:hover>.dropdown-menu,.dropdown-hover.dropdown-submenu:hover>.dropdown-menu,.dropdown-hover.nav-item.dropdown:hover>.dropdown-menu,.dropdown-hover:hover>.dropdown-menu{display:block}.dropdown-menu-xl{min-width:360px;max-width:420px;padding:0}.dropdown-menu-xl .dropdown-divider{margin:0}.dropdown-menu-xl .dropdown-item{padding:.5rem 1rem}.dropdown-menu-xl p{margin:0;word-wrap:break-word;white-space:normal}.dropdown-footer,.dropdown-header{display:block;padding:.5rem 1rem;font-size:.875rem;text-align:center}.open:not(.dropup)>.animated-dropdown-menu{animation:flipInX .7s both;backface-visibility:visible!important}.navbar-custom-menu>.navbar-nav>li{position:relative}.navbar-custom-menu>.navbar-nav>li>.dropdown-menu{position:absolute;right:0;left:auto}@media (max-width:575.98px){.navbar-custom-menu>.navbar-nav{float:right}.navbar-custom-menu>.navbar-nav>li{position:static}.navbar-custom-menu>.navbar-nav>li>.dropdown-menu{position:absolute;right:5%;left:auto;background-color:var(--bs-body-bg);border:1px solid var(--bs-border-color)}}.navbar-nav>.user-menu>.nav-link::after{content:none}.navbar-nav>.user-menu>.dropdown-menu{width:280px;padding:0}.navbar-nav>.user-menu>.dropdown-menu>li.user-header{min-height:175px;padding:10px;text-align:center}.navbar-nav>.user-menu>.dropdown-menu>li.user-header>img{z-index:5;width:90px;height:90px;border:3px solid;border-color:transparent;border-color:var(--bs-border-color-translucent)}.navbar-nav>.user-menu>.dropdown-menu>li.user-header>p{z-index:5;margin-top:10px;font-size:17px;word-wrap:break-word}.navbar-nav>.user-menu>.dropdown-menu>li.user-header>p>.small,.navbar-nav>.user-menu>.dropdown-menu>li.user-header>p>small{display:block;font-size:12px}.navbar-nav>.user-menu>.dropdown-menu>.user-body::after{display:block;clear:both;content:""}.navbar-nav>.user-menu>.dropdown-menu>.user-body{padding:15px;border-top:1px solid var(--bs-border-color);border-bottom:1px solid var(--bs-border-color-translucent)}.navbar-nav>.user-menu>.dropdown-menu>.user-body a{text-decoration:none}.navbar-nav>.user-menu>.dropdown-menu>.user-footer::after{display:block;clear:both;content:""}.navbar-nav>.user-menu>.dropdown-menu>.user-footer{padding:10px;background-color:var(--bs-tertiary-bg)}@media (min-width:576px){.navbar-nav>.user-menu .user-image{float:none;margin-top:-8px;margin-right:.4rem;line-height:10px}}.navbar-nav>.user-menu .user-image{float:left;width:2rem;height:2rem;margin-top:-2px;border-radius:50%}.callout{padding:1.25rem;color:var(--lte-callout-color,inherit);background-color:var(--lte-callout-bg,var(--bs-gray-100));border-left:.25rem solid var(--lte-callout-border,var(--bs-gray-300))}.callout a{color:var(--lte-callout-link,var(--bs-link-color))}.callout code{color:var(--lte-callout-code-color,var(--bs-code-color))}.callout .callout-link{font-weight:700;color:var(--bs-callout-link-color)}.callout .h4,.callout h4{margin-bottom:.25rem}.callout>:last-child{margin-bottom:0}.callout+.callout{margin-top:-.25rem}.callout-primary{--lte-callout-color:var(--bs-primary-text-emphasis);--lte-callout-bg:var(--bs-primary-bg-subtle);--lte-callout-border:var(--bs-primary-border-subtle);--lte-callout-link:var(--bs-primary-text-emphasis);--lte-callout-code-color:var(--bs-primary-text-emphasis);--bs-callout-link-color:var(--bs-primary-text-emphasis)}.callout-secondary{--lte-callout-color:var(--bs-secondary-text-emphasis);--lte-callout-bg:var(--bs-secondary-bg-subtle);--lte-callout-border:var(--bs-secondary-border-subtle);--lte-callout-link:var(--bs-secondary-text-emphasis);--lte-callout-code-color:var(--bs-secondary-text-emphasis);--bs-callout-link-color:var(--bs-secondary-text-emphasis)}.callout-success{--lte-callout-color:var(--bs-success-text-emphasis);--lte-callout-bg:var(--bs-success-bg-subtle);--lte-callout-border:var(--bs-success-border-subtle);--lte-callout-link:var(--bs-success-text-emphasis);--lte-callout-code-color:var(--bs-success-text-emphasis);--bs-callout-link-color:var(--bs-success-text-emphasis)}.callout-info{--lte-callout-color:var(--bs-info-text-emphasis);--lte-callout-bg:var(--bs-info-bg-subtle);--lte-callout-border:var(--bs-info-border-subtle);--lte-callout-link:var(--bs-info-text-emphasis);--lte-callout-code-color:var(--bs-info-text-emphasis);--bs-callout-link-color:var(--bs-info-text-emphasis)}.callout-warning{--lte-callout-color:var(--bs-warning-text-emphasis);--lte-callout-bg:var(--bs-warning-bg-subtle);--lte-callout-border:var(--bs-warning-border-subtle);--lte-callout-link:var(--bs-warning-text-emphasis);--lte-callout-code-color:var(--bs-warning-text-emphasis);--bs-callout-link-color:var(--bs-warning-text-emphasis)}.callout-danger{--lte-callout-color:var(--bs-danger-text-emphasis);--lte-callout-bg:var(--bs-danger-bg-subtle);--lte-callout-border:var(--bs-danger-border-subtle);--lte-callout-link:var(--bs-danger-text-emphasis);--lte-callout-code-color:var(--bs-danger-text-emphasis);--bs-callout-link-color:var(--bs-danger-text-emphasis)}.callout-light{--lte-callout-color:var(--bs-light-text-emphasis);--lte-callout-bg:var(--bs-light-bg-subtle);--lte-callout-border:var(--bs-light-border-subtle);--lte-callout-link:var(--bs-light-text-emphasis);--lte-callout-code-color:var(--bs-light-text-emphasis);--bs-callout-link-color:var(--bs-light-text-emphasis)}.callout-dark{--lte-callout-color:var(--bs-dark-text-emphasis);--lte-callout-bg:var(--bs-dark-bg-subtle);--lte-callout-border:var(--bs-dark-border-subtle);--lte-callout-link:var(--bs-dark-text-emphasis);--lte-callout-code-color:var(--bs-dark-text-emphasis);--bs-callout-link-color:var(--bs-dark-text-emphasis)}.compact-mode .app-header{max-height:2.75rem}.compact-mode .app-header .nav-link{max-height:1.75rem}.compact-mode .nav-link{--bs-nav-link-padding-y:.25rem;--bs-nav-link-padding-x:.5rem}.compact-mode.sidebar-mini.sidebar-collapse .app-sidebar:not(:hover){min-width:3.1rem;max-width:3.1rem}.compact-mode.sidebar-mini.sidebar-collapse .app-sidebar:not(:hover) .sidebar-menu .nav-link{width:2.1rem!important}.compact-mode .logo-xl,.compact-mode .logo-xs{max-height:2.75rem}.compact-mode .brand-image{width:1.75rem;height:1.75rem}.compact-mode .sidebar-brand{height:2.75rem}.compact-mode .app-footer{padding:.5rem}.compact-mode .sidebar-wrapper .nav-icon{min-width:1.1rem;max-width:1.1rem}.progress{border-radius:1px}.progress.vertical{position:relative;display:inline-block;width:30px;height:200px;margin-right:10px}.progress.vertical>.progress-bar{position:absolute;bottom:0;width:100%}.progress.vertical.progress-sm,.progress.vertical.sm{width:20px}.progress.vertical.progress-xs,.progress.vertical.xs{width:10px}.progress.vertical.progress-xxs,.progress.vertical.xxs{width:3px}.progress-group{margin-bottom:.5rem}.progress-sm{height:10px}.progress-xs{height:7px}.progress-xxs{height:3px}.table tr>td .progress{margin:0}.card{box-shadow:0 0 1px rgba(var(--bs-body-color-rgb),.125),0 1px 3px rgba(var(--bs-body-color-rgb),.2)}.card[class*=card-]:not(.card-outline)>.card-header,.card[class*=text-bg-]:not(.card-outline)>.card-header{color:var(--lte-card-variant-color);background-color:var(--lte-card-variant-bg)}.card[class*=card-]:not(.card-outline)>.card-header .btn-tool,.card[class*=text-bg-]:not(.card-outline)>.card-header .btn-tool{--bs-btn-color:rgba(var(--lte-card-variant-color-rgb), .8);--bs-btn-hover-color:var(--lte-card-variant-color)}.card.card-outline{border-top:3px solid var(--lte-card-variant-bg)}.card.maximized-card{position:fixed;top:0;left:0;z-index:1050;width:100%!important;max-width:100%!important;height:100%!important;max-height:100%!important}.card.maximized-card.was-collapsed .card-body{display:block!important}.card.maximized-card .card-body{overflow:auto}.card.maximized-card [data-lte-toggle=card-collapse]{display:none}.card.maximized-card [data-lte-icon=maximize]{display:none}.card.maximized-card .card-footer,.card.maximized-card .card-header{border-radius:0!important}.card:not(.maximized-card) [data-lte-icon=minimize]{display:none}.card.collapsed-card>.card-header [data-lte-icon=collapse]{display:none}.card.collapsed-card>.card-body,.card.collapsed-card>.card-footer{display:none}.card:not(.collapsed-card)>.card-header [data-lte-icon=expand]{display:none}.card .nav.flex-column>li{margin:0;border-bottom:1px solid var(--bs-border-color-translucent)}.card .nav.flex-column>li:last-of-type{border-bottom:0}.card.height-control .card-body{max-height:300px;overflow:auto}.card .border-end{border-right:1px solid var(--bs-border-color-translucent)}.card .border-start{border-left:1px solid var(--bs-border-color-translucent)}.card.card-tabs:not(.card-outline)>.card-header{border-bottom:0}.card.card-tabs:not(.card-outline)>.card-header .nav-item:first-child .nav-link{border-left-color:transparent}.card.card-tabs.card-outline .nav-item{border-bottom:0}.card.card-tabs.card-outline .nav-item:first-child .nav-link{margin-left:0;border-left:0}.card.card-tabs .card-tools{margin:.3rem .5rem}.card.card-tabs:not(.expanding-card).collapsed-card .card-header{border-bottom:0}.card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs{border-bottom:0}.card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item{margin-bottom:0}.card.card-tabs.expanding-card .card-header .nav-tabs .nav-item{margin-bottom:-1px}.card.card-outline-tabs{border-top:0}.card.card-outline-tabs .card-header .nav-item:first-child .nav-link{margin-left:0;border-left:0}.card.card-outline-tabs .card-header a{text-decoration:none;border-top:3px solid transparent}.card.card-outline-tabs .card-header a:hover{border-top:3px solid var(--bs-border-color)}.card.card-outline-tabs .card-header a.active:hover{margin-top:0}.card.card-outline-tabs .card-tools{margin:.5rem .5rem .3rem}.card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header{border-bottom:0}.card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs{border-bottom:0}.card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item{margin-bottom:0}.card.card-outline-tabs.expanding-card .card-header .nav-tabs .nav-item{margin-bottom:-1px}html.maximized-card{overflow:hidden}.card-body::after,.card-footer::after,.card-header::after{display:block;clear:both;content:""}.card-header{position:relative;padding:1rem 1rem;background-color:transparent;border-bottom:1px solid var(--bs-border-color-translucent);border-top-left-radius:.375rem;border-top-right-radius:.375rem}.collapsed-card .card-header{border-bottom:0}.card-header>.card-tools{float:right;margin-right:-.5rem}.card-header>.card-tools .input-group,.card-header>.card-tools .nav,.card-header>.card-tools .pagination{margin-top:-.4rem;margin-bottom:-.4rem}.card-header>.card-tools [data-bs-toggle=tooltip]{position:relative}.card-title{float:left;margin:0;font-size:1.1rem;font-weight:400}.btn-tool{--bs-btn-padding-x:.5rem;--bs-btn-padding-y:.25rem}.btn-tool:not(.btn-tool-custom){--bs-btn-color:var(--bs-tertiary-color);--bs-btn-bg:transparent;--bs-btn-box-shadow:none;--bs-btn-hover-color:var(--bs-secondary-color);--bs-btn-active-border-color:transparent}.btn-tool{margin:-1rem 0;font-size:.875rem}.bg-primary,.card-primary,.text-bg-primary{--lte-card-variant-bg:#0d6efd;--lte-card-variant-bg-rgb:13,110,253;--lte-card-variant-color:#fff;--lte-card-variant-color-rgb:255,255,255}.bg-secondary,.card-secondary,.text-bg-secondary{--lte-card-variant-bg:#6c757d;--lte-card-variant-bg-rgb:108,117,125;--lte-card-variant-color:#fff;--lte-card-variant-color-rgb:255,255,255}.bg-success,.card-success,.text-bg-success{--lte-card-variant-bg:#198754;--lte-card-variant-bg-rgb:25,135,84;--lte-card-variant-color:#fff;--lte-card-variant-color-rgb:255,255,255}.bg-info,.card-info,.text-bg-info{--lte-card-variant-bg:#0dcaf0;--lte-card-variant-bg-rgb:13,202,240;--lte-card-variant-color:#000;--lte-card-variant-color-rgb:0,0,0}.bg-warning,.card-warning,.text-bg-warning{--lte-card-variant-bg:#ffc107;--lte-card-variant-bg-rgb:255,193,7;--lte-card-variant-color:#000;--lte-card-variant-color-rgb:0,0,0}.bg-danger,.card-danger,.text-bg-danger{--lte-card-variant-bg:#dc3545;--lte-card-variant-bg-rgb:220,53,69;--lte-card-variant-color:#fff;--lte-card-variant-color-rgb:255,255,255}.bg-light,.card-light,.text-bg-light{--lte-card-variant-bg:#f8f9fa;--lte-card-variant-bg-rgb:248,249,250;--lte-card-variant-color:#000;--lte-card-variant-color-rgb:0,0,0}.bg-dark,.card-dark,.text-bg-dark{--lte-card-variant-bg:#212529;--lte-card-variant-bg-rgb:33,37,41;--lte-card-variant-color:#fff;--lte-card-variant-color-rgb:255,255,255}.card-body>.table{margin-bottom:0}.card-body>.table>thead>tr>td,.card-body>.table>thead>tr>th{border-top-width:0}.table:not(.table-dark){color:inherit}.table.table-head-fixed thead tr:first-child th{position:sticky;top:0;z-index:10;background-color:var(--bs-body-bg,#fff);border-bottom:0;box-shadow:inset 0 1px 0 var(--bs-border-color,var(--bs-border-color)),inset 0 -1px 0 var(--bs-border-color,var(--bs-border-color))}.table.no-border,.table.no-border td,.table.no-border th{border:0}.table.text-center,.table.text-center td,.table.text-center th{text-align:center}.table.table-valign-middle tbody>tr>td,.table.table-valign-middle tbody>tr>th,.table.table-valign-middle thead>tr>td,.table.table-valign-middle thead>tr>th{vertical-align:middle}.card-body.p-0 .table tbody>tr>td:first-of-type,.card-body.p-0 .table tbody>tr>th:first-of-type,.card-body.p-0 .table tfoot>tr>td:first-of-type,.card-body.p-0 .table tfoot>tr>th:first-of-type,.card-body.p-0 .table thead>tr>td:first-of-type,.card-body.p-0 .table thead>tr>th:first-of-type{padding-left:1.5rem}.card-body.p-0 .table tbody>tr>td:last-of-type,.card-body.p-0 .table tbody>tr>th:last-of-type,.card-body.p-0 .table tfoot>tr>td:last-of-type,.card-body.p-0 .table tfoot>tr>th:last-of-type,.card-body.p-0 .table thead>tr>td:last-of-type,.card-body.p-0 .table thead>tr>th:last-of-type{padding-right:1.5rem}.small-box{border-radius:.375rem;box-shadow:0 0 1px rgba(var(--bs-body-color-rgb),.125),0 1px 3px rgba(var(--bs-body-color-rgb),.2);position:relative;display:block;margin-bottom:1.25rem;--bs-link-color-rgb:none;--bs-link-hover-color-rgb:none;--bs-heading-color:none}.small-box>.inner{padding:10px}.small-box>.small-box-footer{position:relative;z-index:10;display:block;padding:3px 0;text-align:center;background-color:rgba(0,0,0,.07)}.small-box>.small-box-footer:hover{background-color:rgba(0,0,0,.1)}.small-box .h3,.small-box h3{font-size:calc(1.345rem + 1.14vw)}@media (min-width:1200px){.small-box .h3,.small-box h3{font-size:2.2rem}}.small-box .h3,.small-box h3{padding:0;margin:0 0 10px;font-weight:700;white-space:nowrap}@media (min-width:992px){.col-lg-2 .small-box .h3,.col-lg-2 .small-box h3,.col-md-2 .small-box .h3,.col-md-2 .small-box h3,.col-xl-2 .small-box .h3,.col-xl-2 .small-box h3{font-size:calc(1.285rem + .42vw)}}@media (min-width:992px) and (min-width:1200px){.col-lg-2 .small-box .h3,.col-lg-2 .small-box h3,.col-md-2 .small-box .h3,.col-md-2 .small-box h3,.col-xl-2 .small-box .h3,.col-xl-2 .small-box h3{font-size:1.6rem}}@media (min-width:992px){.col-lg-3 .small-box .h3,.col-lg-3 .small-box h3,.col-md-3 .small-box .h3,.col-md-3 .small-box h3,.col-xl-3 .small-box .h3,.col-xl-3 .small-box h3{font-size:calc(1.285rem + .42vw)}}@media (min-width:992px) and (min-width:1200px){.col-lg-3 .small-box .h3,.col-lg-3 .small-box h3,.col-md-3 .small-box .h3,.col-md-3 .small-box h3,.col-xl-3 .small-box .h3,.col-xl-3 .small-box h3{font-size:1.6rem}}@media (min-width:1200px){.col-lg-2 .small-box .h3,.col-lg-2 .small-box h3,.col-md-2 .small-box .h3,.col-md-2 .small-box h3,.col-xl-2 .small-box .h3,.col-xl-2 .small-box h3{font-size:calc(1.345rem + 1.14vw)}}@media (min-width:1200px) and (min-width:1200px){.col-lg-2 .small-box .h3,.col-lg-2 .small-box h3,.col-md-2 .small-box .h3,.col-md-2 .small-box h3,.col-xl-2 .small-box .h3,.col-xl-2 .small-box h3{font-size:2.2rem}}@media (min-width:1200px){.col-lg-3 .small-box .h3,.col-lg-3 .small-box h3,.col-md-3 .small-box .h3,.col-md-3 .small-box h3,.col-xl-3 .small-box .h3,.col-xl-3 .small-box h3{font-size:calc(1.345rem + 1.14vw)}}@media (min-width:1200px) and (min-width:1200px){.col-lg-3 .small-box .h3,.col-lg-3 .small-box h3,.col-md-3 .small-box .h3,.col-md-3 .small-box h3,.col-xl-3 .small-box .h3,.col-xl-3 .small-box h3{font-size:2.2rem}}.small-box p{font-size:1rem}.small-box p>.small,.small-box p>small{display:block;margin-top:5px;font-size:.9rem;color:#f8f9fa}.small-box .h3,.small-box h3,.small-box p{z-index:5}.small-box .small-box-icon{position:absolute;top:15px;right:15px;z-index:0;height:70px;font-size:70px;color:rgba(0,0,0,.15);transition:transform .3s linear}@media (prefers-reduced-motion:reduce){.small-box .small-box-icon{transition:none}}.small-box:hover .small-box-icon{transform:scale(1.1)}@media (max-width:575.98px){.small-box{text-align:center}.small-box .small-box-icon{display:none}.small-box p{font-size:12px}}.info-box{box-shadow:0 0 1px rgba(var(--bs-body-color-rgb),.125),0 1px 3px rgba(var(--bs-body-color-rgb),.2);border-radius:.375rem;position:relative;display:flex;width:100%;min-height:80px;padding:.5rem;margin-bottom:1rem;color:var(--bs-body-color);background-color:var(--bs-body-bg)}.info-box .progress{height:2px;margin:5px 0;background-color:rgba(var(--lte-card-variant-color-rgb),.125)}.info-box .progress .progress-bar{background-color:var(--lte-card-variant-color)}.info-box .info-box-icon{display:flex;align-items:center;justify-content:center;width:70px;font-size:1.875rem;text-align:center;border-radius:.375rem}.info-box .info-box-icon>img{max-width:100%}.info-box .info-box-content{display:flex;flex:1;flex-direction:column;justify-content:center;padding:0 10px;line-height:1.8}.info-box .info-box-number{display:block;margin-top:.25rem;font-weight:700}.info-box .info-box-text,.info-box .progress-description{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.info-box .info-box-more{display:block}.info-box .progress-description{margin:0}@media (min-width:768px){.col-lg-2 .info-box .progress-description,.col-md-2 .info-box .progress-description,.col-xl-2 .info-box .progress-description{display:none}.col-lg-3 .info-box .progress-description,.col-md-3 .info-box .progress-description,.col-xl-3 .info-box .progress-description{display:none}}@media (min-width:992px){.col-lg-2 .info-box .progress-description,.col-md-2 .info-box .progress-description,.col-xl-2 .info-box .progress-description{font-size:.75rem;display:block}.col-lg-3 .info-box .progress-description,.col-md-3 .info-box .progress-description,.col-xl-3 .info-box .progress-description{font-size:.75rem;display:block}}@media (min-width:1200px){.col-lg-2 .info-box .progress-description,.col-md-2 .info-box .progress-description,.col-xl-2 .info-box .progress-description{font-size:1rem;display:block}.col-lg-3 .info-box .progress-description,.col-md-3 .info-box .progress-description,.col-xl-3 .info-box .progress-description{font-size:1rem;display:block}}.timeline{position:relative;padding:0;margin:0 0 45px}.timeline::before{border-radius:.375rem;position:absolute;top:0;bottom:0;left:31px;width:4px;margin:0;content:"";background-color:var(--bs-border-color)}.timeline>div::after,.timeline>div::before{display:table;content:""}.timeline>div{position:relative;margin-right:10px;margin-bottom:15px}.timeline>div>.timeline-item{box-shadow:0 0 1px rgba(var(--bs-body-color-rgb),.125),0 1px 3px rgba(var(--bs-body-color-rgb),.2);border-radius:.375rem;position:relative;padding:0;margin-top:0;margin-right:15px;margin-left:60px;color:var(--bs-body-color);background-color:var(--bs-body-bg)}.timeline>div>.timeline-item>.time{float:right;padding:10px;font-size:12px;color:var(--bs-secondary-color)}.timeline>div>.timeline-item>.timeline-header{padding:10px;margin:0;font-size:16px;line-height:1.1;color:var(--bs-secondary-color);border-bottom:1px solid var(--bs-border-color)}.timeline>div>.timeline-item>.timeline-header>a{font-weight:600;text-decoration:none}.timeline>div>.timeline-item>.timeline-body,.timeline>div>.timeline-item>.timeline-footer{padding:10px}.timeline>div>.timeline-item>.timeline-body>img{margin:10px}.timeline>div>.timeline-item>.timeline-body ol,.timeline>div>.timeline-item>.timeline-body ul,.timeline>div>.timeline-item>.timeline-body>dl{margin:0}.timeline>div .timeline-icon{position:absolute;top:0;left:18px;width:30px;height:30px;font-size:16px;line-height:30px;text-align:center;background-color:var(--bs-secondary-bg);border-radius:50%}.timeline>.time-label>span{border-radius:4px;display:inline-block;padding:5px;font-weight:600;background-color:var(--bs-body-bg)}.timeline-inverse>div>.timeline-item{box-shadow:none;background-color:var(--bs-tertiary-bg);border:1px solid var(--bs-border-color)}.timeline-inverse>div>.timeline-item>.timeline-header{border-bottom-color:var(--bs-border-color)}.direct-chat .card-body{position:relative;padding:0;overflow-x:hidden}.direct-chat.chat-pane-open .direct-chat-contacts{transform:translate(0,0)}.direct-chat.timestamp-light .direct-chat-timestamp{color:rgba(var(--bs-body-color-rgb),.65)}.direct-chat.timestamp-dark .direct-chat-timestamp{color:rgba(var(--bs-body-color-rgb),.9)}.direct-chat-messages{height:250px;padding:10px;overflow:auto;transform:translate(0,0)}.direct-chat-msg,.direct-chat-text{display:block}.direct-chat-msg::after{display:block;clear:both;content:""}.direct-chat-msg{margin-bottom:10px}.direct-chat-contacts,.direct-chat-messages{transition:transform .5s ease-in-out}@media (prefers-reduced-motion:reduce){.direct-chat-contacts,.direct-chat-messages{transition:none}}.direct-chat-text{border-radius:.5rem;position:relative;padding:5px 10px;margin:5px 0 0 50px;color:var(--bs-emphasis-color);background-color:var(--bs-secondary-bg);border:1px solid var(--bs-border-color)}.direct-chat-text::after,.direct-chat-text::before{position:absolute;top:15px;right:100%;width:0;height:0;pointer-events:none;content:" ";border:solid transparent;border-right-color:var(--bs-border-color)}.direct-chat-text::after{margin-top:-5px;border-width:5px}.direct-chat-text::before{margin-top:-6px;border-width:6px}.end .direct-chat-text{margin-right:50px;margin-left:0}.end .direct-chat-text::after,.end .direct-chat-text::before{right:auto;left:100%;border-right-color:transparent;border-left-color:var(--bs-border-color)}.direct-chat-img{border-radius:50%;float:left;width:40px;height:40px}.end .direct-chat-img{float:right}.direct-chat-infos{display:block;margin-bottom:2px;font-size:.875rem}.direct-chat-name{font-weight:600}.direct-chat-timestamp{color:rgba(var(--bs-body-color-rgb),.75)}.direct-chat-contacts-open .direct-chat-contacts{transform:translate(0,0)}.direct-chat-contacts{position:absolute;top:0;bottom:0;width:100%;height:250px;overflow:auto;color:var(--bs-body-bg);background-color:var(--bs-body-color);transform:translate(101%,0)}.direct-chat-contacts-light{background-color:var(--bs-light-bg-subtle)}.direct-chat-contacts-light .contacts-list-name{color:var(--bs-body-color)}.direct-chat-contacts-light .contacts-list-date{color:var(--bs-secondary-color)}.direct-chat-contacts-light .contacts-list-msg{color:var(--bs-secondary-color)}.contacts-list{padding-left:0;list-style:none}.contacts-list>li::after{display:block;clear:both;content:""}.contacts-list>li{padding:10px;margin:0;text-decoration:none;border-bottom:1px solid rgba(0,0,0,.2)}.contacts-list>li:last-of-type{border-bottom:0}.contacts-list>li a{text-decoration:none}.contacts-list-img{border-radius:50%;float:left;width:40px}.contacts-list-info{margin-left:45px;color:var(--bs-body-bg)}.contacts-list-name,.contacts-list-status{display:block}.contacts-list-name{font-weight:600}.contacts-list-status{font-size:.875rem}.contacts-list-date{font-weight:400;color:var(--bs-secondary-bg)}.contacts-list-msg{color:var(--bs-secondary-bg)}.end>.direct-chat-text{color:var(--lte-direct-chat-color);background-color:var(--lte-direct-chat-bg);border-color:var(--lte-direct-chat-bg)}.end>.direct-chat-text::after,.end>.direct-chat-text::before{border-left-color:var(--lte-direct-chat-bg)}.direct-chat-primary{--lte-direct-chat-color:#fff;--lte-direct-chat-bg:#0d6efd}.direct-chat-secondary{--lte-direct-chat-color:#fff;--lte-direct-chat-bg:#6c757d}.direct-chat-success{--lte-direct-chat-color:#fff;--lte-direct-chat-bg:#198754}.direct-chat-info{--lte-direct-chat-color:#000;--lte-direct-chat-bg:#0dcaf0}.direct-chat-warning{--lte-direct-chat-color:#000;--lte-direct-chat-bg:#ffc107}.direct-chat-danger{--lte-direct-chat-color:#fff;--lte-direct-chat-bg:#dc3545}.direct-chat-light{--lte-direct-chat-color:#000;--lte-direct-chat-bg:#f8f9fa}.direct-chat-dark{--lte-direct-chat-color:#fff;--lte-direct-chat-bg:#212529}.toast-primary{--bs-toast-header-color:#fff;--bs-toast-header-bg:#0d6efd;--bs-toast-header-border-color:#0d6efd;--bs-toast-border-color:#0d6efd;--bs-toast-bg:var(--bs-primary-bg-subtle)}.toast-primary .btn-close{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast-secondary{--bs-toast-header-color:#fff;--bs-toast-header-bg:#6c757d;--bs-toast-header-border-color:#6c757d;--bs-toast-border-color:#6c757d;--bs-toast-bg:var(--bs-secondary-bg-subtle)}.toast-secondary .btn-close{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast-success{--bs-toast-header-color:#fff;--bs-toast-header-bg:#198754;--bs-toast-header-border-color:#198754;--bs-toast-border-color:#198754;--bs-toast-bg:var(--bs-success-bg-subtle)}.toast-success .btn-close{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast-info{--bs-toast-header-color:#000;--bs-toast-header-bg:#0dcaf0;--bs-toast-header-border-color:#0dcaf0;--bs-toast-border-color:#0dcaf0;--bs-toast-bg:var(--bs-info-bg-subtle)}.toast-warning{--bs-toast-header-color:#000;--bs-toast-header-bg:#ffc107;--bs-toast-header-border-color:#ffc107;--bs-toast-border-color:#ffc107;--bs-toast-bg:var(--bs-warning-bg-subtle)}.toast-danger{--bs-toast-header-color:#fff;--bs-toast-header-bg:#dc3545;--bs-toast-header-border-color:#dc3545;--bs-toast-border-color:#dc3545;--bs-toast-bg:var(--bs-danger-bg-subtle)}.toast-danger .btn-close{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast-light{--bs-toast-header-color:#000;--bs-toast-header-bg:#f8f9fa;--bs-toast-header-border-color:#f8f9fa;--bs-toast-border-color:#f8f9fa;--bs-toast-bg:var(--bs-light-bg-subtle)}.toast-dark{--bs-toast-header-color:#fff;--bs-toast-header-bg:#212529;--bs-toast-header-border-color:#212529;--bs-toast-border-color:#212529;--bs-toast-bg:var(--bs-dark-bg-subtle)}.toast-dark .btn-close{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}[data-bs-theme=dark] .toast-info .btn-close{--bs-btn-close-white-filter:none}[data-bs-theme=dark] .toast-warning .btn-close{--bs-btn-close-white-filter:none}[data-bs-theme=dark] .toast-light .btn-close{--bs-btn-close-white-filter:none}.login-logo,.register-logo{margin-bottom:.9rem;font-size:2.1rem;font-weight:300;text-align:center}.login-logo a,.register-logo a{color:var(--bs-secondary-color);text-decoration:none}.login-page,.register-page{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh}.login-box,.register-box{width:400px}@media (max-width:576px){.login-box,.register-box{width:90%;margin-top:.5rem}}.login-box .card,.register-box .card{margin-bottom:0}.login-card-body,.register-card-body{padding:20px;color:var(--bs-secondary-color);background-color:var(--bs-body-bg);border-top:0}.login-card-body .input-group .form-control:focus,.register-card-body .input-group .form-control:focus{box-shadow:none}.login-card-body .input-group .form-control:focus~.input-group-append .input-group-text,.login-card-body .input-group .form-control:focus~.input-group-prepend .input-group-text,.register-card-body .input-group .form-control:focus~.input-group-append .input-group-text,.register-card-body .input-group .form-control:focus~.input-group-prepend .input-group-text{border-color:rgb(134,182.5,254)}.login-card-body .input-group .form-control.is-valid:focus,.register-card-body .input-group .form-control.is-valid:focus{box-shadow:none}.login-card-body .input-group .form-control.is-valid~.input-group-append .input-group-text,.login-card-body .input-group .form-control.is-valid~.input-group-prepend .input-group-text,.register-card-body .input-group .form-control.is-valid~.input-group-append .input-group-text,.register-card-body .input-group .form-control.is-valid~.input-group-prepend .input-group-text{border-color:#198754}.login-card-body .input-group .form-control.is-invalid:focus,.register-card-body .input-group .form-control.is-invalid:focus{box-shadow:none}.login-card-body .input-group .form-control.is-invalid~.input-group-append .input-group-text,.register-card-body .input-group .form-control.is-invalid~.input-group-append .input-group-text{border-color:#dc3545}.login-card-body .input-group .input-group-text,.register-card-body .input-group .input-group-text{color:var(--bs-secondary-color);background-color:transparent;border-top-right-radius:.375rem;border-bottom-right-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.login-card-body .input-group .input-group-text,.register-card-body .input-group .input-group-text{transition:none}}.login-box-msg,.register-box-msg{padding:0 20px 20px;margin:0;text-align:center}.social-auth-links{margin:10px 0}.lockscreen .lockscreen-name{font-weight:600;text-align:center}.lockscreen .lockscreen-logo{margin-bottom:25px;font-size:35px;font-weight:300;text-align:center}.lockscreen .lockscreen-logo a{color:var(--bs-emphasis-color);text-decoration:none}.lockscreen .lockscreen-wrapper{max-width:400px;margin:0 auto;margin-top:10%}.lockscreen .lockscreen-item{position:relative;width:290px;padding:0;margin:10px auto 30px;background-color:var(--bs-body-bg);border-radius:4px}.lockscreen .lockscreen-image{position:absolute;top:-25px;left:-10px;z-index:10;padding:5px;background-color:var(--bs-body-bg);border-radius:50%}.lockscreen .lockscreen-image>img{border-radius:50%;width:70px;height:70px}.lockscreen .lockscreen-credentials{margin-left:70px}.lockscreen .lockscreen-credentials .form-control{border:0}.lockscreen .lockscreen-credentials .btn{padding:0 10px;border:0}.lockscreen .lockscreen-footer{margin-top:10px}.img-size-32,.img-size-50,.img-size-64{height:auto}.img-size-64{width:64px}.img-size-50{width:50px}.img-size-32{width:32px}.skip-link{position:absolute;top:-40px;left:6px;z-index:999999;padding:8px 16px;font-weight:600;color:var(--bs-white);text-decoration:none;background:var(--bs-primary)}.skip-link:focus{top:0;outline:3px solid var(--bs-warning);outline-offset:2px}.skip-link:hover{color:var(--bs-white);text-decoration:none;background:var(--bs-primary-emphasis)}.focus-enhanced:focus{outline:3px solid var(--bs-focus-ring-color,#0d6efd);outline-offset:2px;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}@media (prefers-contrast:high){.card{border:2px solid}.btn{border-width:2px}.nav-link{border:1px solid transparent}.nav-link:focus,.nav-link:hover{border-color:currentcolor}}@media (prefers-reduced-motion:reduce){*,::after,::before{transition-duration:0s!important;animation-duration:0s!important;animation-iteration-count:1!important;scroll-behavior:auto!important}.fade{opacity:1!important;transition:none!important}.collapse{transition:none!important}.modal.fade .modal-dialog{transform:none!important}}.sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.sr-only-focusable:focus{position:static!important;width:auto!important;height:auto!important;padding:inherit!important;margin:inherit!important;overflow:visible!important;clip:auto!important;white-space:normal!important}.focus-trap:focus{box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.text-accessible-primary{color:#003d82}.text-accessible-success{color:#0f5132}.text-accessible-danger{color:#842029}.text-accessible-warning{color:#664d03}.live-region{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}.live-region.live-region-visible{position:static;left:auto;width:auto;height:auto;overflow:visible}.form-control.is-invalid{border-color:var(--bs-danger)}.form-control.is-invalid:focus{border-color:var(--bs-danger);box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.invalid-feedback[role=alert]{font-weight:600}.touch-target{min-width:44px;min-height:44px}.touch-target.touch-target-small{min-width:24px;min-height:24px}.table-accessible th{font-weight:600;background-color:var(--bs-secondary-bg)}.table-accessible th[scope=col]{border-bottom:2px solid var(--bs-border-color)}.table-accessible th[scope=row]{border-right:2px solid var(--bs-border-color)}.table-accessible caption{padding:.75rem;font-weight:600;color:var(--bs-secondary);text-align:left;caption-side:top}nav[role=navigation]:not([aria-label]):not([aria-labelledby])::before{position:absolute;left:-10000px;content:"Navigation"}fieldset{padding:1rem;margin-bottom:1rem;border:1px solid var(--bs-border-color)}fieldset legend{padding:0 .5rem;margin-bottom:.5rem;font-size:1.1em;font-weight:600}.loading[aria-busy=true]{position:relative;pointer-events:none}.loading[aria-busy=true]::after{position:absolute;top:50%;left:50%;width:20px;height:20px;margin-top:-10px;margin-left:-10px;content:"";border:2px solid var(--bs-primary);border-top-color:transparent;animation:spin 1s linear infinite}@media (prefers-reduced-motion:reduce){.loading[aria-busy=true]::after{border-top-color:var(--bs-primary);animation:none}}@keyframes spin{to{transform:rotate(360deg)}}[data-bs-theme=dark] .text-accessible-primary{color:#6ea8fe}[data-bs-theme=dark] .text-accessible-success{color:#75b798}[data-bs-theme=dark] .text-accessible-danger{color:#f1aeb5}[data-bs-theme=dark] .text-accessible-warning{color:#ffda6a}@media print{.btn,.nav-link,.skip-link{color:#000!important;background:0 0!important;border:1px solid #000!important}a[href^=http]::after{font-size:.8em;content:" (" attr(href) ")"}.app-wrapper{display:grid!important;grid-template-rows:auto 1fr auto!important;grid-template-columns:auto 1fr!important}.sidebar-overlay{display:none!important}.app-sidebar{position:static!important;display:block!important;min-width:200px!important;max-width:200px!important;max-height:none!important;margin-left:0!important;overflow:visible!important}.sidebar-wrapper{height:auto!important;overflow:visible!important}.app-header{position:static!important}.app-main{width:auto!important;max-width:100%!important;overflow:visible!important}.app-content{overflow:visible!important}.app-footer{position:static!important}} +/*# sourceMappingURL=adminlte.min.css.map */ \ No newline at end of file diff --git a/src/web/public/adminlte/js/adminlte.min.js b/src/web/public/adminlte/js/adminlte.min.js new file mode 100644 index 0000000..6adef65 --- /dev/null +++ b/src/web/public/adminlte/js/adminlte.min.js @@ -0,0 +1,7 @@ +/*! + * AdminLTE v4.1.0 (https://adminlte.io) + * Copyright 2014-2026 Colorlib + * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE) + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).adminlte={})}(this,function(e){"use strict";const t=[],n={controller:new AbortController,hasInitialized:!1},i=()=>n.controller.signal,s=()=>{if(!n.hasInitialized){n.hasInitialized=!0;for(const e of t)e()}},a=e=>{t.push(e),n.hasInitialized&&e()};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",s,{once:!0}):s(),document.addEventListener("turbo:before-render",()=>{n.controller.abort(),n.controller=new AbortController,n.hasInitialized=!1}),document.addEventListener("turbo:load",s);const o=new WeakMap,r=e=>{const t=o.get(e)??[];for(const e of t)globalThis.clearTimeout(e);o.delete(e)},c=e=>{for(const t of["height","padding-top","padding-bottom","margin-top","margin-bottom","overflow","transition-duration","transition-property"])e.style.removeProperty(t)},l=(e,t=500)=>{if(r(e),t<=1)return e.style.display="none",void c(e);e.style.transitionProperty="height, margin, padding",e.style.transitionDuration=`${t}ms`,e.style.boxSizing="border-box",e.style.height=`${e.offsetHeight}px`,e.style.overflow="hidden";const n=globalThis.setTimeout(()=>{e.style.height="0",e.style.paddingTop="0",e.style.paddingBottom="0",e.style.marginTop="0",e.style.marginBottom="0"},1),i=globalThis.setTimeout(()=>{e.style.display="none",c(e),o.delete(e)},t);o.set(e,[n,i])},d=(e,t=500)=>{r(e),c(e),e.style.removeProperty("display");let{display:n}=globalThis.getComputedStyle(e);if("none"===n&&(n="block"),e.style.display=n,t<=1)return;const i=e.offsetHeight;e.style.overflow="hidden",e.style.height="0",e.style.paddingTop="0",e.style.paddingBottom="0",e.style.marginTop="0",e.style.marginBottom="0";const s=globalThis.setTimeout(()=>{e.style.boxSizing="border-box",e.style.transitionProperty="height, margin, padding",e.style.transitionDuration=`${t}ms`,e.style.height=`${i}px`,e.style.removeProperty("padding-top"),e.style.removeProperty("padding-bottom"),e.style.removeProperty("margin-top"),e.style.removeProperty("margin-bottom")},1),a=globalThis.setTimeout(()=>{c(e),o.delete(e)},t);o.set(e,[s,a])},u="hold-transition";class h{_element;_holdTransitionTimer;constructor(e){this._element=e,this._holdTransitionTimer=void 0}holdTransition(e=100){this._holdTransitionTimer&&clearTimeout(this._holdTransitionTimer),document.body.classList.add(u),this._holdTransitionTimer=setTimeout(()=>{document.body.classList.remove(u)},e)}}a(()=>{const e=new h(document.body);window.addEventListener("resize",()=>e.holdTransition(200),{signal:i()}),setTimeout(()=>{document.body.classList.add("app-loaded")},400)});const m=new WeakMap;class p{static get NAME(){throw new Error("Component subclasses must override the static NAME getter.")}static get DATA_KEY(){return`lte.${this.NAME}`}static _getInstance(e){return e?m.get(e)?.get(this.DATA_KEY)??null:null}_element;constructor(e){this._element=e;const t=m.get(e)??new Map;m.set(e,t),t.set(this.constructor.DATA_KEY,this)}dispose(){const e=m.get(this._element);e?.delete(this.constructor.DATA_KEY),0===e?.size&&m.delete(this._element)}}const g=(e,t,n={})=>{const i=new CustomEvent(t,{bubbles:!0,cancelable:n.cancelable??!1,detail:n.detail});return e.dispatchEvent(i),i},b="card-widget",f=`.lte.${b}`,v=`collapse${f}`,y=`expand${f}`,_=`remove${f}`,S=`collapsed${f}`,E=`expanded${f}`,L=`removed${f}`,A=`maximized${f}`,T=`minimized${f}`,k="card",x="collapsed-card",w="collapsing-card",M="expanding-card",q="was-collapsed",$="maximized-card",I='[data-lte-toggle="card-remove"]',C='[data-lte-toggle="card-collapse"]',N='[data-lte-toggle="card-maximize"]',P=`.${k}`,z=".card-body",D=".card-footer",R={animationSpeed:500,collapseTrigger:C,removeTrigger:I,maximizeTrigger:N};class B extends p{static get NAME(){return b}static getInstance(e){return this._getInstance(e)}static getOrCreateInstance(e,t={}){return this.getInstance(e)??new this(e,t)}_parent;_config;constructor(e,t={}){super(e),this._parent=e.closest(P),e.classList.contains(k)&&(this._parent=e),this._config={...R,...t}}collapse(){this._parent&&(g(this._parent,v,{cancelable:!0}).defaultPrevented||(this._parent.classList.add(w),this._parent.classList.remove(M),this._parent.querySelectorAll(`:scope > ${z}, :scope > ${D}`).forEach(e=>{e instanceof HTMLElement&&l(e,this._config.animationSpeed)}),setTimeout(()=>{this._parent?.classList.contains(w)&&(this._parent.classList.add(x),this._parent.classList.remove(w),g(this._parent,S))},this._config.animationSpeed)))}expand(){this._parent&&(g(this._parent,y,{cancelable:!0}).defaultPrevented||(this._parent.classList.add(M),this._parent.classList.remove(w,x),this._parent.querySelectorAll(`:scope > ${z}, :scope > ${D}`).forEach(e=>{e instanceof HTMLElement&&d(e,this._config.animationSpeed)}),setTimeout(()=>{this._parent?.classList.contains(M)&&(this._parent.classList.remove(M),g(this._parent,E))},this._config.animationSpeed)))}remove(){if(!this._parent)return;if(g(this._parent,_,{cancelable:!0}).defaultPrevented)return;const e=this._parent;l(e,this._config.animationSpeed),setTimeout(()=>{g(e,L),e.remove(),this.dispose()},this._config.animationSpeed)}toggle(){this._parent?.classList.contains(x)||this._parent?.classList.contains(w)?this.expand():this.collapse()}maximize(){this._parent&&(this._parent.style.height=`${this._parent.offsetHeight}px`,this._parent.style.width=`${this._parent.offsetWidth}px`,this._parent.style.transition="all .15s",setTimeout(()=>{const e=document.querySelector("html");e&&e.classList.add($),this._parent&&(this._parent.classList.add($),this._parent.classList.contains(x)&&this._parent.classList.add(q),g(this._parent,A))},150))}minimize(){this._parent&&(this._parent.style.height="auto",this._parent.style.width="auto",this._parent.style.transition="all .15s",setTimeout(()=>{const e=document.querySelector("html");e&&e.classList.remove($),this._parent&&(this._parent.classList.remove($),this._parent?.classList.contains(q)&&this._parent.classList.remove(q),g(this._parent,T),setTimeout(()=>{this._parent?.style.removeProperty("height"),this._parent?.style.removeProperty("width"),this._parent?.style.removeProperty("transition")},150))},10))}toggleMaximize(){this._parent?.classList.contains($)?this.minimize():this.maximize()}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;const n=t.closest(C),i=t.closest(I),s=t.closest(N),a=n??i??s;if(!a)return;e.preventDefault();const o=a.closest(P);if(!o)return;const r=B.getOrCreateInstance(o);n?r.toggle():i?r.remove():r.toggleMaximize()});const F="treeview",O=`.lte.${F}`,H=`expand${O}`,K=`collapse${O}`,W=`expanded${O}`,Y=`collapsed${O}`,j=`load${O}`,U="menu-open",V=".nav-item",G=".nav-link",J=".nav-treeview",Q='[data-lte-toggle="treeview"]',X={animationSpeed:300,accordion:!0},Z=(e,t)=>{const n=e.querySelector(`:scope > ${G}`);n?.setAttribute("aria-expanded",String(t))};class ee extends p{static get NAME(){return F}static getInstance(e){return this._getInstance(e)}static getOrCreateInstance(e,t={}){return this.getInstance(e)??new this(e,t)}_config;constructor(e,t={}){super(e),this._config={...X,...t}}open(){if(g(this._element,H,{cancelable:!0}).defaultPrevented)return;if(this._config.accordion){const e=this._element.parentElement?.querySelectorAll(`${V}.${U}`);e?.forEach(e=>{if(!this._element.contains(e)){e.classList.remove(U),Z(e,!1);const t=e?.querySelector(J);t&&l(t,this._config.animationSpeed)}})}this._element.classList.add(U),Z(this._element,!0);const e=this._element.querySelector(J);e&&d(e,this._config.animationSpeed),setTimeout(()=>{this._element.classList.contains(U)&&g(this._element,W)},this._config.animationSpeed)}close(){if(g(this._element,K,{cancelable:!0}).defaultPrevented)return;this._element.classList.remove(U),Z(this._element,!1);const e=this._element.querySelector(J);e&&l(e,this._config.animationSpeed),setTimeout(()=>{this._element.classList.contains(U)||g(this._element,Y)},this._config.animationSpeed)}toggle(){this._element.classList.contains(U)?this.close():this.open()}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;const n=t.closest(Q);if(!n)return;const i=t.closest(V),s=t.closest(G);if(!i?.querySelector(J))return;"#"!==t.getAttribute("href")&&"#"!==s?.getAttribute("href")||e.preventDefault();const a=n.dataset.accordion,o=n.dataset.animationSpeed,r={accordion:void 0===a?X.accordion:"true"===a,animationSpeed:void 0===o?X.animationSpeed:Number(o)};ee.getOrCreateInstance(i,r).toggle()}),a(()=>{document.querySelectorAll(`${V}.${U}`).forEach(e=>{const t=e.querySelector(J);if(t){d(t,0);const n=new Event(j);e.dispatchEvent(n)}}),document.querySelectorAll(Q).forEach(e=>{e.querySelectorAll(V).forEach(e=>{e.querySelector(`:scope > ${J}`)&&Z(e,e.classList.contains(U))})})});const te="direct-chat",ne=`.lte.${te}`,ie=`expanded${ne}`,se=`collapsed${ne}`,ae="direct-chat-contacts-open";class oe extends p{static get NAME(){return te}static getInstance(e){return this._getInstance(e)}static getOrCreateInstance(e){return this.getInstance(e)??new this(e)}toggle(){this._element.classList.contains(ae)?(this._element.classList.remove(ae),g(this._element,se)):(this._element.classList.add(ae),g(this._element,ie))}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;const n=t.closest('[data-lte-toggle="chat-pane"]');if(!n)return;e.preventDefault();const i=n.closest(".direct-chat");i&&oe.getOrCreateInstance(i).toggle()});const re="fullscreen",ce=`.lte.${re}`,le=`maximized${ce}`,de=`minimized${ce}`,ue='[data-lte-toggle="fullscreen"]';function he(){const e=document.querySelector('[data-lte-icon="maximize"]'),t=document.querySelector('[data-lte-icon="minimize"]'),n=Boolean(document.fullscreenElement);e?.classList.toggle("d-none",n),t?.classList.toggle("d-none",!n);const i=n?le:de;document.querySelectorAll(ue).forEach(e=>{g(e,i)})}class me extends p{static get NAME(){return re}static getInstance(e){return this._getInstance(e)}static getOrCreateInstance(e){return this.getInstance(e)??new this(e)}inFullScreen(){document.documentElement.requestFullscreen().catch(()=>{})}outFullscreen(){document.exitFullscreen().catch(()=>{})}toggleFullScreen(){document.fullscreenEnabled&&(document.fullscreenElement?this.outFullscreen():this.inFullScreen())}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;const n=t.closest(ue);n&&(e.preventDefault(),me.getOrCreateInstance(n).toggleFullScreen())}),a(()=>{document.addEventListener("fullscreenchange",he,{signal:i()})});const pe="push-menu",ge=`.lte.${pe}`,be=`open${ge}`,fe=`collapse${ge}`,ve=`opened${ge}`,ye=`collapsed${ge}`,_e="sidebar-overlay",Se="sidebar-collapse",Ee="sidebar-open",Le=".app-sidebar",Ae="lte.sidebar.state",Te={sidebarBreakpoint:991.98,enablePersistence:!1};class ke extends p{static get NAME(){return pe}static getInstance(e){return this._getInstance(e)}static getOrCreateInstance(e,t={}){return this.getInstance(e)??new this(e,t)}_config;constructor(e,t={}){super(e),this._config={...Te,...t}}isCollapsed(){return document.body.classList.contains(Se)}isExplicitlyOpen(){return document.body.classList.contains(Ee)}isMiniMode(){return document.body.classList.contains("sidebar-mini")}isMobileSize(){return globalThis.innerWidth<=this._config.sidebarBreakpoint}expand(){g(this._element,be,{cancelable:!0}).defaultPrevented||(document.body.classList.remove(Se),this.isMobileSize()&&document.body.classList.add(Ee),g(this._element,ve))}collapse(){g(this._element,fe,{cancelable:!0}).defaultPrevented||(document.body.classList.remove(Ee),document.body.classList.add(Se),g(this._element,ye))}toggle(){const e=this.isCollapsed();e?this.expand():this.collapse(),this._config.enablePersistence&&this.saveSidebarState(e?Ee:Se)}setupSidebarBreakPoint(){const e=document.querySelector('[class*="sidebar-expand"]');if(!e)return;const t=globalThis.getComputedStyle(e,"::before").getPropertyValue("content");if(!t||"none"===t)return;const n=Number(t.replace(/[^\d.-]/g,""));Number.isNaN(n)||(this._config={...this._config,sidebarBreakpoint:n})}updateStateByResponsiveLogic(){this.isMobileSize()?this.isExplicitlyOpen()||this.collapse():this.isMiniMode()&&this.isCollapsed()||this.expand()}saveSidebarState(e){if(void 0!==globalThis.localStorage)try{localStorage.setItem(Ae,e)}catch{}}loadSidebarState(){if(void 0!==globalThis.localStorage)try{const e=localStorage.getItem(Ae);e===Se?this.collapse():e===Ee?this.expand():this.updateStateByResponsiveLogic()}catch{this.updateStateByResponsiveLogic()}}clearSidebarState(){if(void 0!==globalThis.localStorage)try{localStorage.removeItem(Ae)}catch{}}init(){this.setupSidebarBreakPoint(),this._config.enablePersistence||this.clearSidebarState(),this._config.enablePersistence&&!this.isMobileSize()?this.loadSidebarState():this.updateStateByResponsiveLogic()}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;if(!t.closest('[data-lte-toggle="sidebar"]'))return;e.preventDefault();const n=document.querySelector(Le);n&&ke.getOrCreateInstance(n).toggle()}),a(()=>{const e=document.querySelector(Le);if(!e)return;const t=e.dataset.sidebarBreakpoint,n=e.dataset.enablePersistence,s={sidebarBreakpoint:void 0===t?Te.sidebarBreakpoint:Number(t),enablePersistence:void 0===n?Te.enablePersistence:"true"===n},a=ke.getOrCreateInstance(e,s);a.init(),globalThis.matchMedia(`(max-width: ${a._config.sidebarBreakpoint}px)`).addEventListener("change",()=>{a.updateStateByResponsiveLogic()},{signal:i()});const o=document.querySelector(".app-wrapper");let r=o?.querySelector(`:scope > .${_e}`);r||(r=document.createElement("div"),r.className=_e,o?.append(r));let c=!1;r.addEventListener("touchstart",()=>{c=!1},{passive:!0}),r.addEventListener("touchmove",()=>{c=!0},{passive:!0}),r.addEventListener("touchend",e=>{c||(e.preventDefault(),a.collapse()),c=!1},{passive:!1}),r.addEventListener("click",e=>{e.preventDefault(),a.collapse()})});const xe="lte-theme",we="[data-bs-theme-value]";class Me{getStoredTheme(){try{const e=localStorage.getItem(xe);return e&&["light","dark","auto"].includes(e)?e:null}catch{return null}}getPreferredTheme(){return this.getStoredTheme()||(this._prefersDark()?"dark":"light")}resolveTheme(e){return"auto"===e?this._prefersDark()?"dark":"light":e}setTheme(e){try{localStorage.setItem(xe,e)}catch{}this._applyTheme(e),this._showActiveTheme(e),document.dispatchEvent(new CustomEvent("changed.lte.color-mode",{detail:{theme:e,resolved:this.resolveTheme(e)}}))}_applyTheme(e){const t=this.resolveTheme(e);document.documentElement.setAttribute("data-bs-theme",t),document.documentElement.style.colorScheme=t}_prefersDark(){return globalThis.matchMedia("(prefers-color-scheme: dark)").matches}_showActiveTheme(e){document.querySelectorAll(we).forEach(t=>{const n=t.getAttribute("data-bs-theme-value")===e;t.classList.toggle("active",n),t.setAttribute("aria-pressed",String(n)),t.querySelector(".bi-check-lg")?.classList.toggle("d-none",!n)}),document.querySelectorAll("[data-lte-theme-icon]").forEach(t=>{t.classList.toggle("d-none",t.dataset.lteThemeIcon!==e)})}init(){const e=this.getPreferredTheme();this._applyTheme(e),this._showActiveTheme(e)}}document.addEventListener("click",e=>{const t=e.target;if(!(t instanceof Element))return;const n=t.closest(we),i=n?.getAttribute("data-bs-theme-value");i&&(new Me).setTheme(i)}),a(()=>{const e=new Me;e.init(),globalThis.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{const t=e.getStoredTheme();t&&"auto"!==t||(e._applyTheme("auto"),e._showActiveTheme(t??"auto"))},{signal:i()})});class qe{config;liveRegion=null;focusHistory=[];signal=i();constructor(e={}){this.config={announcements:!0,skipLinks:!0,focusManagement:!0,keyboardNavigation:!0,reducedMotion:!0,...e},this.init()}init(){this.config.announcements&&this.createLiveRegion(),this.config.skipLinks&&this.addSkipLinks(),this.config.focusManagement&&this.initFocusManagement(),this.config.keyboardNavigation&&this.initKeyboardNavigation(),this.config.reducedMotion&&this.respectReducedMotion(),this.initErrorAnnouncements(),this.initTableAccessibility(),this.initFormAccessibility()}createLiveRegion(){if(this.liveRegion)return;const e=document.getElementById("live-region");e?this.liveRegion=e:(this.liveRegion=document.createElement("div"),this.liveRegion.id="live-region",this.liveRegion.className="live-region",this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.setAttribute("role","status"),document.body.append(this.liveRegion))}addSkipLinks(){if(document.querySelector(".skip-links"))return void this.ensureSkipTargets();const e=document.createElement("div");e.className="skip-links";const t=document.createElement("a");t.href="#main",t.className="skip-link",t.textContent="Skip to main content";const n=document.createElement("a");n.href="#navigation",n.className="skip-link",n.textContent="Skip to navigation",e.append(t),e.append(n),document.body.insertBefore(e,document.body.firstChild),this.ensureSkipTargets()}ensureSkipTargets(){const e=document.querySelector('#main, main, [role="main"]');e&&!e.id&&(e.id="main"),e&&!e.hasAttribute("tabindex")&&e.setAttribute("tabindex","-1");const t=document.querySelector('#navigation, nav, [role="navigation"]');t&&!t.id&&(t.id="navigation"),t&&!t.hasAttribute("tabindex")&&t.setAttribute("tabindex","-1")}initFocusManagement(){document.addEventListener("keydown",e=>{"Escape"===e.key&&this.handleEscapeKey(e)},{signal:this.signal}),this.initModalFocusManagement(),this.initDropdownFocusManagement()}handleEscapeKey(e){if(!document.querySelector(".modal.show")&&document.querySelector(".dropdown-menu.show")){const t=document.querySelector('[data-bs-toggle="dropdown"][aria-expanded="true"]');t?.click(),e.preventDefault()}}initKeyboardNavigation(){document.addEventListener("keydown",e=>{const t=e.target;t.matches("input, textarea, select, [contenteditable], [contenteditable] *")||(t.closest(".nav, .navbar-nav, .dropdown-menu")&&this.handleMenuNavigation(e),"Enter"!==e.key&&" "!==e.key||!t.hasAttribute("role")||"button"!==t.getAttribute("role")||t.matches('button, input[type="button"], input[type="submit"]')||(e.preventDefault(),t.click()))},{signal:this.signal})}handleMenuNavigation(e){if(!["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"].includes(e.key))return;const t=e.target,n=Array.from(t.closest(".nav, .navbar-nav, .dropdown-menu")?.querySelectorAll("a, button")||[]).filter(e=>null!==e.offsetParent),i=n.indexOf(t);if(-1===i)return;let s;switch(e.key){case"ArrowDown":case"ArrowRight":s=i0?i-1:n.length-1;break;case"Home":s=0;break;case"End":s=n.length-1;break;default:return}e.preventDefault(),n[s]?.focus()}respectReducedMotion(){if(globalThis.matchMedia("(prefers-reduced-motion: reduce)").matches&&(document.body.classList.add("reduce-motion"),document.documentElement.style.scrollBehavior="auto",!document.getElementById("adminlte-reduce-motion"))){const e=document.createElement("style");e.id="adminlte-reduce-motion",e.textContent="\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n ",document.head.append(e)}}initErrorAnnouncements(){const e=new MutationObserver(e=>{e.forEach(e=>{e.addedNodes.forEach(e=>{if(e.nodeType===Node.ELEMENT_NODE){const t=e;t.matches(".alert-danger, .invalid-feedback, .error")&&this.announce(t.textContent||"Error occurred","assertive"),t.matches(".alert-success, .success")&&this.announce(t.textContent||"Success","polite")}})})});e.observe(document.body,{childList:!0,subtree:!0}),this.signal.addEventListener("abort",()=>{e.disconnect()},{once:!0})}initTableAccessibility(){document.querySelectorAll("table").forEach(e=>{if(e.hasAttribute("role")||e.setAttribute("role","table"),e.querySelectorAll("th").forEach(e=>{if(!e.hasAttribute("scope")){const t=e.closest("thead"),n=0===e.cellIndex;t?e.setAttribute("scope","col"):n&&e.setAttribute("scope","row")}}),!e.querySelector("caption")&&e.hasAttribute("title")){const t=document.createElement("caption");t.textContent=e.getAttribute("title")||"",e.insertBefore(t,e.firstChild)}})}initFormAccessibility(){document.querySelectorAll("input, select, textarea").forEach(e=>{const t=e;if(!t.labels?.length&&!t.hasAttribute("aria-label")&&!t.hasAttribute("aria-labelledby")){const e=t.getAttribute("placeholder");e&&t.setAttribute("aria-label",e)}if(t.hasAttribute("required")){const e=t.labels?.[0];if(e&&!e.querySelector(".required-indicator")){const t=document.createElement("span");t.className="required-indicator sr-only",t.textContent=" (required)",e.append(t)}}t.classList.contains("disable-adminlte-validations")||t.addEventListener("invalid",()=>{this.handleFormError(t)})})}handleFormError(e){e.id||e.name||(e.id=Ce.generateId("field"));const t=`${e.id||e.name}-error`;let n=document.getElementById(t);n||(n=document.createElement("div"),n.id=t,n.className="invalid-feedback",n.setAttribute("role","alert"),e.parentNode?.append(n)),n.textContent=e.validationMessage;const i=(e.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);i.includes(t)||i.push(t),e.setAttribute("aria-describedby",i.join(" ")),e.classList.add("is-invalid"),this.announce(`Error in ${e.labels?.[0]?.textContent||e.name}: ${e.validationMessage}`,"assertive")}initModalFocusManagement(){document.addEventListener("show.bs.modal",()=>{this.focusHistory.push(document.activeElement)},{signal:this.signal}),document.addEventListener("shown.bs.modal",e=>{const t=e.target,n=t.querySelector("[autofocus]")||t.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');n?.focus()},{signal:this.signal}),document.addEventListener("hidden.bs.modal",()=>{const e=this.focusHistory.pop();e?.isConnected&&e.focus()},{signal:this.signal})}initDropdownFocusManagement(){document.addEventListener("shown.bs.dropdown",e=>{const t=e.target.querySelector(".dropdown-menu"),n=t?.querySelector("a, button");n&&n.focus()},{signal:this.signal})}announce(e,t="polite"){this.liveRegion||this.createLiveRegion(),this.liveRegion&&(this.liveRegion.setAttribute("aria-live",t),this.liveRegion.textContent=e,setTimeout(()=>{this.liveRegion&&(this.liveRegion.textContent="")},1e3))}focusElement(e){const t=document.querySelector(e);t&&(t.focus(),t.scrollIntoView({behavior:"smooth",block:"center"}))}trapFocus(e){const t=e.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),n=Array.from(t),i=n[0],s=n.at(-1);e.addEventListener("keydown",e=>{"Tab"===e.key&&(e.shiftKey?document.activeElement===i&&(s?.focus(),e.preventDefault()):document.activeElement===s&&(i.focus(),e.preventDefault()))},{signal:this.signal})}addLandmarks(){if(!document.querySelector("main")){const e=document.querySelector(".app-main");e&&(e.setAttribute("role","main"),e.id||(e.id="main"))}document.querySelectorAll(".navbar-nav, .nav").forEach((e,t)=>{"UL"!==e.tagName&&"OL"!==e.tagName&&(e.hasAttribute("role")||e.setAttribute("role","navigation"),e.hasAttribute("aria-label")||e.setAttribute("aria-label",`Navigation ${t+1}`))});const e=document.querySelector('form[role="search"], .navbar-search');e&&!e.hasAttribute("role")&&e.setAttribute("role","search")}}const $e=e=>new qe(e),Ie=e=>{const[t,n,i]=(e=>{const t=/^#([\da-f]{3}|[\da-f]{6})$/i.exec(e.trim());if(t){let e=t[1];return 3===e.length&&(e=[...e].map(e=>e+e).join("")),[Number.parseInt(e.slice(0,2),16),Number.parseInt(e.slice(2,4),16),Number.parseInt(e.slice(4,6),16)]}return e.match(/\d+/g)?.map(Number)||[0,0,0]})(e).map(e=>(e/=255)<=.03928?e/12.92:(e+.055)**2.4/1.055**2.4);return.2126*t+.7152*n+.0722*i},Ce={checkColorContrast:(e,t)=>{const n=Ie(e),i=Ie(t),s=(Math.max(n,i)+.05)/(Math.min(n,i)+.05);return{ratio:Math.round(100*s)/100,passes:s>=4.5}},generateId:(e="a11y")=>`${e}-${Math.random().toString(36).slice(2,11)}`,isFocusable:e=>["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])','[contenteditable="true"]'].some(t=>e.matches(t))};a(()=>{$e({announcements:!0,skipLinks:!0,focusManagement:!0,keyboardNavigation:!0,reducedMotion:!0}).addLandmarks()}),e.CardWidget=B,e.ColorMode=Me,e.DirectChat=oe,e.FullScreen=me,e.Layout=h,e.PushMenu=ke,e.Treeview=ee,e.initAccessibility=$e}); +//# sourceMappingURL=adminlte.min.js.map \ No newline at end of file diff --git a/src/web/public/adminlte/js/bootstrap.bundle.min.js b/src/web/public/adminlte/js/bootstrap.bundle.min.js new file mode 100644 index 0000000..0b87369 --- /dev/null +++ b/src/web/public/adminlte/js/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.8 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,(t,e)=>`#${CSS.escape(e)}`)),t),s=t=>null==t?`${t}`:Object.prototype.toString.call(t).match(/\s([a-z]+)/i)[1].toLowerCase(),o=t=>{t.dispatchEvent(new Event(i))},r=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),a=t=>r(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,l=t=>{if(!r(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",()=>{for(const t of p)t()}),p.push(e)):e()},_=(t,e=[],i=t)=>"function"==typeof t?t.call(...e):i,b=(t,e,n=!0)=>{if(!n)return void _(t);const s=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),_(t))};e.addEventListener(i,a),setTimeout(()=>{r||o(e)},s)},v=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,A=/::\d+$/,E={};let T=1;const C={mouseenter:"mouseover",mouseleave:"mouseout"},O=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function x(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function k(t){const e=x(t);return t.uidEvent=e,E[e]=E[e]||{},E[e]}function L(t,e,i=null){return Object.values(t).find(t=>t.callable===e&&t.delegationSelector===i)}function S(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=N(t);return O.has(o)||(o=t),[n,s,o]}function D(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=S(e,i,n);if(e in C){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=k(t),c=l[a]||(l[a]={}),h=L(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=x(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return j(s,{delegateTarget:r}),n.oneOff&&P.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return j(n,{delegateTarget:t}),i.oneOff&&P.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function $(t,e,i,n,s){const o=L(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function I(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&$(t,e,i,r.callable,r.delegationSelector)}function N(t){return t=t.replace(w,""),C[t]||t}const P={on(t,e,i,n){D(t,e,i,n,!1)},one(t,e,i,n){D(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=k(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))I(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(A,"");a&&!e.includes(s)||$(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;$(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=f();let s=null,o=!0,r=!0,a=!1;e!==N(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=j(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function j(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function F(t){return t.replace(/[A-Z]/g,t=>`-${t.toLowerCase()}`)}const H={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter(t=>t.startsWith("bs")&&!t.startsWith("bsConfig"));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${F(e)}`))};class W{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=r(e)?H.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...r(e)?H.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[i,n]of Object.entries(e)){const e=t[i],o=r(e)?"element":s(e);if(!new RegExp(n).test(o))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${i}" provided type "${o}" but expected type "${n}".`)}}}class B extends W{constructor(t,i){super(),(t=a(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),P.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){b(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(a(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.8"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const z=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e?e.split(",").map(t=>n(t)).join(","):null},R={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter(t=>t.matches(e)),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(t=>`${t}:not([tabindex^="-"])`).join(",");return this.find(e,t).filter(t=>!c(t)&&l(t))},getSelectorFromElement(t){const e=z(t);return e&&R.findOne(e)?e:null},getElementFromSelector(t){const e=z(t);return e?R.findOne(e):null},getMultipleElementsFromSelector(t){const e=z(t);return e?R.find(e):[]}},q=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;P.on(document,i,`[data-bs-dismiss="${n}"]`,function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),c(this))return;const s=R.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()})},V=".bs.alert",K=`close${V}`,Q=`closed${V}`;class X extends B{static get NAME(){return"alert"}close(){if(P.trigger(this._element,K).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback(()=>this._destroyElement(),this._element,t)}_destroyElement(){this._element.remove(),P.trigger(this._element,Q),this.dispose()}static jQueryInterface(t){return this.each(function(){const e=X.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}})}}q(X,"close"),g(X);const Y='[data-bs-toggle="button"]';class U extends B{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each(function(){const e=U.getOrCreateInstance(this);"toggle"===t&&e[t]()})}}P.on(document,"click.bs.button.data-api",Y,t=>{t.preventDefault();const e=t.target.closest(Y);U.getOrCreateInstance(e).toggle()}),g(U);const G=".bs.swipe",J=`touchstart${G}`,Z=`touchmove${G}`,tt=`touchend${G}`,et=`pointerdown${G}`,it=`pointerup${G}`,nt={endCallback:null,leftCallback:null,rightCallback:null},st={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class ot extends W{constructor(t,e){super(),this._element=t,t&&ot.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return nt}static get DefaultType(){return st}static get NAME(){return"swipe"}dispose(){P.off(this._element,G)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),_(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&_(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(P.on(this._element,et,t=>this._start(t)),P.on(this._element,it,t=>this._end(t)),this._element.classList.add("pointer-event")):(P.on(this._element,J,t=>this._start(t)),P.on(this._element,Z,t=>this._move(t)),P.on(this._element,tt,t=>this._end(t)))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const rt=".bs.carousel",at=".data-api",lt="ArrowLeft",ct="ArrowRight",ht="next",dt="prev",ut="left",ft="right",pt=`slide${rt}`,mt=`slid${rt}`,gt=`keydown${rt}`,_t=`mouseenter${rt}`,bt=`mouseleave${rt}`,vt=`dragstart${rt}`,yt=`load${rt}${at}`,wt=`click${rt}${at}`,At="carousel",Et="active",Tt=".active",Ct=".carousel-item",Ot=Tt+Ct,xt={[lt]:ft,[ct]:ut},kt={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Lt={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class St extends B{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=R.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===At&&this.cycle()}static get Default(){return kt}static get DefaultType(){return Lt}static get NAME(){return"carousel"}next(){this._slide(ht)}nextWhenVisible(){!document.hidden&&l(this._element)&&this.next()}prev(){this._slide(dt)}pause(){this._isSliding&&o(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval(()=>this.nextWhenVisible(),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?P.one(this._element,mt,()=>this.cycle()):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void P.one(this._element,mt,()=>this.to(t));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?ht:dt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&P.on(this._element,gt,t=>this._keydown(t)),"hover"===this._config.pause&&(P.on(this._element,_t,()=>this.pause()),P.on(this._element,bt,()=>this._maybeEnableCycle())),this._config.touch&&ot.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of R.find(".carousel-item img",this._element))P.on(t,vt,t=>t.preventDefault());const t={leftCallback:()=>this._slide(this._directionToOrder(ut)),rightCallback:()=>this._slide(this._directionToOrder(ft)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(()=>this._maybeEnableCycle(),500+this._config.interval))}};this._swipeHelper=new ot(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=xt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=R.findOne(Tt,this._indicatorsElement);e.classList.remove(Et),e.removeAttribute("aria-current");const i=R.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(Et),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===ht,s=e||v(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>P.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(pt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),u(s),i.classList.add(l),s.classList.add(l),this._queueCallback(()=>{s.classList.remove(l,c),s.classList.add(Et),i.classList.remove(Et,c,l),this._isSliding=!1,r(mt)},i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return R.findOne(Ot,this._element)}_getItems(){return R.find(Ct,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return m()?t===ut?dt:ht:t===ut?ht:dt}_orderToDirection(t){return m()?t===dt?ut:ft:t===dt?ft:ut}static jQueryInterface(t){return this.each(function(){const e=St.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)})}}P.on(document,wt,"[data-bs-slide], [data-bs-slide-to]",function(t){const e=R.getElementFromSelector(this);if(!e||!e.classList.contains(At))return;t.preventDefault();const i=St.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===H.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())}),P.on(window,yt,()=>{const t=R.find('[data-bs-ride="carousel"]');for(const e of t)St.getOrCreateInstance(e)}),g(St);const Dt=".bs.collapse",$t=`show${Dt}`,It=`shown${Dt}`,Nt=`hide${Dt}`,Pt=`hidden${Dt}`,jt=`click${Dt}.data-api`,Mt="show",Ft="collapse",Ht="collapsing",Wt=`:scope .${Ft} .${Ft}`,Bt='[data-bs-toggle="collapse"]',zt={parent:null,toggle:!0},Rt={parent:"(null|element)",toggle:"boolean"};class qt extends B{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=R.find(Bt);for(const t of i){const e=R.getSelectorFromElement(t),i=R.find(e).filter(t=>t===this._element);null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return zt}static get DefaultType(){return Rt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter(t=>t!==this._element).map(t=>qt.getOrCreateInstance(t,{toggle:!1}))),t.length&&t[0]._isTransitioning)return;if(P.trigger(this._element,$t).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Ft),this._element.classList.add(Ht),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(Ht),this._element.classList.add(Ft,Mt),this._element.style[e]="",P.trigger(this._element,It)},this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(P.trigger(this._element,Nt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,u(this._element),this._element.classList.add(Ht),this._element.classList.remove(Ft,Mt);for(const t of this._triggerArray){const e=R.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(Ht),this._element.classList.add(Ft),P.trigger(this._element,Pt)},this._element,!0)}_isShown(t=this._element){return t.classList.contains(Mt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=a(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Bt);for(const e of t){const t=R.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=R.find(Wt,this._config.parent);return R.find(t,this._config.parent).filter(t=>!e.includes(t))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each(function(){const i=qt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}})}}P.on(document,jt,Bt,function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of R.getMultipleElementsFromSelector(this))qt.getOrCreateInstance(t,{toggle:!1}).toggle()}),g(qt);var Vt="top",Kt="bottom",Qt="right",Xt="left",Yt="auto",Ut=[Vt,Kt,Qt,Xt],Gt="start",Jt="end",Zt="clippingParents",te="viewport",ee="popper",ie="reference",ne=Ut.reduce(function(t,e){return t.concat([e+"-"+Gt,e+"-"+Jt])},[]),se=[].concat(Ut,[Yt]).reduce(function(t,e){return t.concat([e,e+"-"+Gt,e+"-"+Jt])},[]),oe="beforeRead",re="read",ae="afterRead",le="beforeMain",ce="main",he="afterMain",de="beforeWrite",ue="write",fe="afterWrite",pe=[oe,re,ae,le,ce,he,de,ue,fe];function me(t){return t?(t.nodeName||"").toLowerCase():null}function ge(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function _e(t){return t instanceof ge(t).Element||t instanceof Element}function be(t){return t instanceof ge(t).HTMLElement||t instanceof HTMLElement}function ve(t){return"undefined"!=typeof ShadowRoot&&(t instanceof ge(t).ShadowRoot||t instanceof ShadowRoot)}const ye={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach(function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];be(s)&&me(s)&&(Object.assign(s.style,i),Object.keys(n).forEach(function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)}))})},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach(function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce(function(t,e){return t[e]="",t},{});be(n)&&me(n)&&(Object.assign(n.style,o),Object.keys(s).forEach(function(t){n.removeAttribute(t)}))})}},requires:["computeStyles"]};function we(t){return t.split("-")[0]}var Ae=Math.max,Ee=Math.min,Te=Math.round;function Ce(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map(function(t){return t.brand+"/"+t.version}).join(" "):navigator.userAgent}function Oe(){return!/^((?!chrome|android).)*safari/i.test(Ce())}function xe(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&be(t)&&(s=t.offsetWidth>0&&Te(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&Te(n.height)/t.offsetHeight||1);var r=(_e(t)?ge(t):window).visualViewport,a=!Oe()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function ke(t){var e=xe(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Le(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ve(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Se(t){return ge(t).getComputedStyle(t)}function De(t){return["table","td","th"].indexOf(me(t))>=0}function $e(t){return((_e(t)?t.ownerDocument:t.document)||window.document).documentElement}function Ie(t){return"html"===me(t)?t:t.assignedSlot||t.parentNode||(ve(t)?t.host:null)||$e(t)}function Ne(t){return be(t)&&"fixed"!==Se(t).position?t.offsetParent:null}function Pe(t){for(var e=ge(t),i=Ne(t);i&&De(i)&&"static"===Se(i).position;)i=Ne(i);return i&&("html"===me(i)||"body"===me(i)&&"static"===Se(i).position)?e:i||function(t){var e=/firefox/i.test(Ce());if(/Trident/i.test(Ce())&&be(t)&&"fixed"===Se(t).position)return null;var i=Ie(t);for(ve(i)&&(i=i.host);be(i)&&["html","body"].indexOf(me(i))<0;){var n=Se(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function je(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Me(t,e,i){return Ae(t,Ee(e,i))}function Fe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function He(t,e){return e.reduce(function(e,i){return e[i]=t,e},{})}const We={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=we(i.placement),l=je(a),c=[Xt,Qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Fe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:He(t,Ut))}(s.padding,i),d=ke(o),u="y"===l?Vt:Xt,f="y"===l?Kt:Qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=Pe(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Me(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Le(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Be(t){return t.split("-")[1]}var ze={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Re(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Xt,y=Vt,w=window;if(c){var A=Pe(i),E="clientHeight",T="clientWidth";A===ge(i)&&"static"!==Se(A=$e(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===Vt||(s===Xt||s===Qt)&&o===Jt)&&(y=Kt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Xt&&(s!==Vt&&s!==Kt||o!==Jt)||(v=Qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&ze),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:Te(i*s)/s||0,y:Te(n*s)/s||0}}({x:f,y:m},ge(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const qe={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:we(e.placement),variation:Be(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,Re(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,Re(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var Ve={passive:!0};const Ke={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=ge(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach(function(t){t.addEventListener("scroll",i.update,Ve)}),a&&l.addEventListener("resize",i.update,Ve),function(){o&&c.forEach(function(t){t.removeEventListener("scroll",i.update,Ve)}),a&&l.removeEventListener("resize",i.update,Ve)}},data:{}};var Qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Xe(t){return t.replace(/left|right|bottom|top/g,function(t){return Qe[t]})}var Ye={start:"end",end:"start"};function Ue(t){return t.replace(/start|end/g,function(t){return Ye[t]})}function Ge(t){var e=ge(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Je(t){return xe($e(t)).left+Ge(t).scrollLeft}function Ze(t){var e=Se(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function ti(t){return["html","body","#document"].indexOf(me(t))>=0?t.ownerDocument.body:be(t)&&Ze(t)?t:ti(Ie(t))}function ei(t,e){var i;void 0===e&&(e=[]);var n=ti(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=ge(n),r=s?[o].concat(o.visualViewport||[],Ze(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(ei(Ie(r)))}function ii(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ni(t,e,i){return e===te?ii(function(t,e){var i=ge(t),n=$e(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Oe();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Je(t),y:l}}(t,i)):_e(e)?function(t,e){var i=xe(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):ii(function(t){var e,i=$e(t),n=Ge(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=Ae(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=Ae(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Je(t),l=-n.scrollTop;return"rtl"===Se(s||i).direction&&(a+=Ae(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}($e(t)))}function si(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?we(s):null,r=s?Be(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case Vt:e={x:a,y:i.y-n.height};break;case Kt:e={x:a,y:i.y+i.height};break;case Qt:e={x:i.x+i.width,y:l};break;case Xt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?je(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Gt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Jt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function oi(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Zt:a,c=i.rootBoundary,h=void 0===c?te:c,d=i.elementContext,u=void 0===d?ee:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Fe("number"!=typeof g?g:He(g,Ut)),b=u===ee?ie:ee,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=ei(Ie(t)),i=["absolute","fixed"].indexOf(Se(t).position)>=0&&be(t)?Pe(t):t;return _e(i)?e.filter(function(t){return _e(t)&&Le(t,i)&&"body"!==me(t)}):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce(function(e,i){var s=ni(t,i,n);return e.top=Ae(s.top,e.top),e.right=Ee(s.right,e.right),e.bottom=Ee(s.bottom,e.bottom),e.left=Ae(s.left,e.left),e},ni(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(_e(y)?y:y.contextElement||$e(t.elements.popper),l,h,r),A=xe(t.elements.reference),E=si({reference:A,element:v,placement:s}),T=ii(Object.assign({},v,E)),C=u===ee?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===ee&&x){var k=x[s];Object.keys(O).forEach(function(t){var e=[Qt,Kt].indexOf(t)>=0?1:-1,i=[Vt,Kt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e})}return O}function ri(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?se:l,h=Be(n),d=h?a?ne:ne.filter(function(t){return Be(t)===h}):Ut,u=d.filter(function(t){return c.indexOf(t)>=0});0===u.length&&(u=d);var f=u.reduce(function(e,i){return e[i]=oi(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[we(i)],e},{});return Object.keys(f).sort(function(t,e){return f[t]-f[e]})}const ai={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=we(g),b=l||(_!==g&&p?function(t){if(we(t)===Yt)return[];var e=Xe(t);return[Ue(t),e,Ue(e)]}(g):[Xe(g)]),v=[g].concat(b).reduce(function(t,i){return t.concat(we(i)===Yt?ri(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)},[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=oi(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?Qt:Xt:k?Kt:Vt;y[S]>w[S]&&($=Xe($));var I=Xe($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every(function(t){return t})){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find(function(e){var i=A.get(e);if(i)return i.slice(0,t).every(function(t){return t})});if(e)return T=e,"break"},j=p?3:1;j>0&&"break"!==P(j);j--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function li(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ci(t){return[Vt,Qt,Kt,Xt].some(function(e){return t[e]>=0})}const hi={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=oi(e,{elementContext:"reference"}),a=oi(e,{altBoundary:!0}),l=li(r,n),c=li(a,s,o),h=ci(l),d=ci(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},di={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=se.reduce(function(t,i){return t[i]=function(t,e,i){var n=we(t),s=[Xt,Vt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Xt,Qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t},{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ui={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=si({reference:e.rects.reference,element:e.rects.popper,placement:e.placement})},data:{}},fi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=oi(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=we(e.placement),b=Be(e.placement),v=!b,y=je(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?Vt:Xt,D="y"===y?Kt:Qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],j=f?-T[$]/2:0,M=b===Gt?E[$]:T[$],F=b===Gt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?ke(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Me(0,E[$],W[$]),V=v?E[$]/2-j-q-z-O.mainAxis:M-q-z-O.mainAxis,K=v?-E[$]/2+j+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&Pe(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Me(f?Ee(N,I+V-Y-X):N,I,f?Ae(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?Vt:Xt,tt="x"===y?Kt:Qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[Vt,Xt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Me(t,e,i);return n>i?i:n}(at,et,lt):Me(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function pi(t,e,i){void 0===i&&(i=!1);var n,s,o=be(e),r=be(e)&&function(t){var e=t.getBoundingClientRect(),i=Te(e.width)/t.offsetWidth||1,n=Te(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=$e(e),l=xe(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==me(e)||Ze(a))&&(c=(n=e)!==ge(n)&&be(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Ge(n)),be(e)?((h=xe(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Je(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function mi(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach(function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}}),n.push(t)}return t.forEach(function(t){e.set(t.name,t)}),t.forEach(function(t){i.has(t.name)||s(t)}),n}var gi={placement:"bottom",modifiers:[],strategy:"absolute"};function _i(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(H.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..._(this._config.popperConfig,[void 0,t])}}_selectMenuItem({key:t,target:e}){const i=R.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(t=>l(t));i.length&&v(i,e,t===xi,!i.includes(e)).focus()}static jQueryInterface(t){return this.each(function(){const e=Qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=R.find(Mi);for(const i of e){const e=Qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Oi,xi].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(ji)?this:R.prev(this,ji)[0]||R.next(this,ji)[0]||R.findOne(ji,t.delegateTarget.parentNode),o=Qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}P.on(document,Ii,ji,Qi.dataApiKeydownHandler),P.on(document,Ii,Fi,Qi.dataApiKeydownHandler),P.on(document,$i,Qi.clearMenus),P.on(document,Ni,Qi.clearMenus),P.on(document,$i,ji,function(t){t.preventDefault(),Qi.getOrCreateInstance(this).toggle()}),g(Qi);const Xi="backdrop",Yi="show",Ui=`mousedown.bs.${Xi}`,Gi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Ji={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Zi extends W{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Gi}static get DefaultType(){return Ji}static get NAME(){return Xi}show(t){if(!this._config.isVisible)return void _(t);this._append();const e=this._getElement();this._config.isAnimated&&u(e),e.classList.add(Yi),this._emulateAnimation(()=>{_(t)})}hide(t){this._config.isVisible?(this._getElement().classList.remove(Yi),this._emulateAnimation(()=>{this.dispose(),_(t)})):_(t)}dispose(){this._isAppended&&(P.off(this._element,Ui),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=a(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),P.on(t,Ui,()=>{_(this._config.clickCallback)}),this._isAppended=!0}_emulateAnimation(t){b(t,this._getElement(),this._config.isAnimated)}}const tn=".bs.focustrap",en=`focusin${tn}`,nn=`keydown.tab${tn}`,sn="backward",on={autofocus:!0,trapElement:null},rn={autofocus:"boolean",trapElement:"element"};class an extends W{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return on}static get DefaultType(){return rn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),P.off(document,tn),P.on(document,en,t=>this._handleFocusin(t)),P.on(document,nn,t=>this._handleKeydown(t)),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,P.off(document,tn))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=R.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===sn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?sn:"forward")}}const ln=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",cn=".sticky-top",hn="padding-right",dn="margin-right";class un{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,hn,e=>e+t),this._setElementAttributes(ln,hn,e=>e+t),this._setElementAttributes(cn,dn,e=>e-t)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,hn),this._resetElementAttributes(ln,hn),this._resetElementAttributes(cn,dn)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)})}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&H.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,t=>{const i=H.getDataAttribute(t,e);null!==i?(H.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)})}_applyManipulationCallback(t,e){if(r(t))e(t);else for(const i of R.find(t,this._element))e(i)}}const fn=".bs.modal",pn=`hide${fn}`,mn=`hidePrevented${fn}`,gn=`hidden${fn}`,_n=`show${fn}`,bn=`shown${fn}`,vn=`resize${fn}`,yn=`click.dismiss${fn}`,wn=`mousedown.dismiss${fn}`,An=`keydown.dismiss${fn}`,En=`click${fn}.data-api`,Tn="modal-open",Cn="show",On="modal-static",xn={backdrop:!0,focus:!0,keyboard:!0},kn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Ln extends B{constructor(t,e){super(t,e),this._dialog=R.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new un,this._addEventListeners()}static get Default(){return xn}static get DefaultType(){return kn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||P.trigger(this._element,_n,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(Tn),this._adjustDialog(),this._backdrop.show(()=>this._showElement(t)))}hide(){this._isShown&&!this._isTransitioning&&(P.trigger(this._element,pn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Cn),this._queueCallback(()=>this._hideModal(),this._element,this._isAnimated())))}dispose(){P.off(window,fn),P.off(this._dialog,fn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Zi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new an({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=R.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),u(this._element),this._element.classList.add(Cn),this._queueCallback(()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,P.trigger(this._element,bn,{relatedTarget:t})},this._dialog,this._isAnimated())}_addEventListeners(){P.on(this._element,An,t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())}),P.on(window,vn,()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()}),P.on(this._element,wn,t=>{P.one(this._element,yn,e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())})})}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove(Tn),this._resetAdjustments(),this._scrollBar.reset(),P.trigger(this._element,gn)})}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(P.trigger(this._element,mn).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(On)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(On),this._queueCallback(()=>{this._element.classList.remove(On),this._queueCallback(()=>{this._element.style.overflowY=e},this._dialog)},this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=m()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=m()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each(function(){const i=Ln.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}})}}P.on(document,En,'[data-bs-toggle="modal"]',function(t){const e=R.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),P.one(e,_n,t=>{t.defaultPrevented||P.one(e,gn,()=>{l(this)&&this.focus()})});const i=R.findOne(".modal.show");i&&Ln.getInstance(i).hide(),Ln.getOrCreateInstance(e).toggle(this)}),q(Ln),g(Ln);const Sn=".bs.offcanvas",Dn=".data-api",$n=`load${Sn}${Dn}`,In="show",Nn="showing",Pn="hiding",jn=".offcanvas.show",Mn=`show${Sn}`,Fn=`shown${Sn}`,Hn=`hide${Sn}`,Wn=`hidePrevented${Sn}`,Bn=`hidden${Sn}`,zn=`resize${Sn}`,Rn=`click${Sn}${Dn}`,qn=`keydown.dismiss${Sn}`,Vn={backdrop:!0,keyboard:!0,scroll:!1},Kn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class Qn extends B{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Vn}static get DefaultType(){return Kn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||P.trigger(this._element,Mn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new un).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Nn),this._queueCallback(()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(In),this._element.classList.remove(Nn),P.trigger(this._element,Fn,{relatedTarget:t})},this._element,!0))}hide(){this._isShown&&(P.trigger(this._element,Hn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Pn),this._backdrop.hide(),this._queueCallback(()=>{this._element.classList.remove(In,Pn),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new un).reset(),P.trigger(this._element,Bn)},this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Zi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():P.trigger(this._element,Wn)}:null})}_initializeFocusTrap(){return new an({trapElement:this._element})}_addEventListeners(){P.on(this._element,qn,t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():P.trigger(this._element,Wn))})}static jQueryInterface(t){return this.each(function(){const e=Qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}})}}P.on(document,Rn,'[data-bs-toggle="offcanvas"]',function(t){const e=R.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this))return;P.one(e,Bn,()=>{l(this)&&this.focus()});const i=R.findOne(jn);i&&i!==e&&Qn.getInstance(i).hide(),Qn.getOrCreateInstance(e).toggle(this)}),P.on(window,$n,()=>{for(const t of R.find(jn))Qn.getOrCreateInstance(t).show()}),P.on(window,zn,()=>{for(const t of R.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&Qn.getOrCreateInstance(t).hide()}),q(Qn),g(Qn);const Xn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],dd:[],div:[],dl:[],dt:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Yn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Un=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Gn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Yn.has(i)||Boolean(Un.test(t.nodeValue)):e.filter(t=>t instanceof RegExp).some(t=>t.test(i))},Jn={allowList:Xn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
    "},Zn={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},ts={entry:"(string|element|function|null)",selector:"(string|element)"};class es extends W{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Jn}static get DefaultType(){return Zn}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map(t=>this._resolvePossibleFunction(t)).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},ts)}_setContent(t,e,i){const n=R.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?r(e)?this._putElementInTemplate(a(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Gn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return _(t,[void 0,this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const is=new Set(["sanitize","allowList","sanitizeFn"]),ns="fade",ss="show",os=".tooltip-inner",rs=".modal",as="hide.bs.modal",ls="hover",cs="focus",hs="click",ds={AUTO:"auto",TOP:"top",RIGHT:m()?"left":"right",BOTTOM:"bottom",LEFT:m()?"right":"left"},us={allowList:Xn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},fs={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class ps extends B{constructor(t,e){if(void 0===Ai)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org/docs/v2/)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return us}static get DefaultType(){return fs}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),P.off(this._element.closest(rs),as,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=P.trigger(this._element,this.constructor.eventName("show")),e=(h(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),P.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(ss),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.on(t,"mouseover",d);this._queueCallback(()=>{P.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1},this.tip,this._isAnimated())}hide(){if(this._isShown()&&!P.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(ss),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.off(t,"mouseover",d);this._activeTrigger[hs]=!1,this._activeTrigger[cs]=!1,this._activeTrigger[ls]=!1,this._isHovered=null,this._queueCallback(()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),P.trigger(this._element,this.constructor.eventName("hidden")))},this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ns,ss),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ns),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new es({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{[os]:this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ns)}_isShown(){return this.tip&&this.tip.classList.contains(ss)}_createPopper(t){const e=_(this._config.placement,[this,t,this._element]),i=ds[e.toUpperCase()];return wi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return _(t,[this._element,this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,..._(this._config.popperConfig,[void 0,e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)P.on(this._element,this.constructor.eventName("click"),this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger[hs]=!(e._isShown()&&e._activeTrigger[hs]),e.toggle()});else if("manual"!==e){const t=e===ls?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ls?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");P.on(this._element,t,this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?cs:ls]=!0,e._enter()}),P.on(this._element,i,this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?cs:ls]=e._element.contains(t.relatedTarget),e._leave()})}this._hideModalHandler=()=>{this._element&&this.hide()},P.on(this._element.closest(rs),as,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout(()=>{this._isHovered&&this.show()},this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout(()=>{this._isHovered||this.hide()},this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=H.getDataAttributes(this._element);for(const t of Object.keys(e))is.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:a(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each(function(){const e=ps.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}}g(ps);const ms=".popover-header",gs=".popover-body",_s={...ps.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},bs={...ps.DefaultType,content:"(null|string|element|function)"};class vs extends ps{static get Default(){return _s}static get DefaultType(){return bs}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{[ms]:this._getTitle(),[gs]:this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each(function(){const e=vs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}}g(vs);const ys=".bs.scrollspy",ws=`activate${ys}`,As=`click${ys}`,Es=`load${ys}.data-api`,Ts="active",Cs="[href]",Os=".nav-link",xs=`${Os}, .nav-item > ${Os}, .list-group-item`,ks={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},Ls={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Ss extends B{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ks}static get DefaultType(){return Ls}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=a(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map(t=>Number.parseFloat(t))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(P.off(this._config.target,As),P.on(this._config.target,As,Cs,t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}}))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver(t=>this._observerCallback(t),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=R.find(Cs,this._config.target);for(const e of t){if(!e.hash||c(e))continue;const t=R.findOne(decodeURI(e.hash),this._element);l(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(Ts),this._activateParents(t),P.trigger(this._element,ws,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))R.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(Ts);else for(const e of R.parents(t,".nav, .list-group"))for(const t of R.prev(e,xs))t.classList.add(Ts)}_clearActiveClass(t){t.classList.remove(Ts);const e=R.find(`${Cs}.${Ts}`,t);for(const t of e)t.classList.remove(Ts)}static jQueryInterface(t){return this.each(function(){const e=Ss.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}})}}P.on(window,Es,()=>{for(const t of R.find('[data-bs-spy="scroll"]'))Ss.getOrCreateInstance(t)}),g(Ss);const Ds=".bs.tab",$s=`hide${Ds}`,Is=`hidden${Ds}`,Ns=`show${Ds}`,Ps=`shown${Ds}`,js=`click${Ds}`,Ms=`keydown${Ds}`,Fs=`load${Ds}`,Hs="ArrowLeft",Ws="ArrowRight",Bs="ArrowUp",zs="ArrowDown",Rs="Home",qs="End",Vs="active",Ks="fade",Qs="show",Xs=".dropdown-toggle",Ys=`:not(${Xs})`,Us='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Gs=`.nav-link${Ys}, .list-group-item${Ys}, [role="tab"]${Ys}, ${Us}`,Js=`.${Vs}[data-bs-toggle="tab"], .${Vs}[data-bs-toggle="pill"], .${Vs}[data-bs-toggle="list"]`;class Zs extends B{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),P.on(this._element,Ms,t=>this._keydown(t)))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?P.trigger(e,$s,{relatedTarget:t}):null;P.trigger(t,Ns,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Vs),this._activate(R.getElementFromSelector(t)),this._queueCallback(()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),P.trigger(t,Ps,{relatedTarget:e})):t.classList.add(Qs)},t,t.classList.contains(Ks)))}_deactivate(t,e){t&&(t.classList.remove(Vs),t.blur(),this._deactivate(R.getElementFromSelector(t)),this._queueCallback(()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),P.trigger(t,Is,{relatedTarget:e})):t.classList.remove(Qs)},t,t.classList.contains(Ks)))}_keydown(t){if(![Hs,Ws,Bs,zs,Rs,qs].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter(t=>!c(t));let i;if([Rs,qs].includes(t.key))i=e[t.key===Rs?0:e.length-1];else{const n=[Ws,zs].includes(t.key);i=v(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Zs.getOrCreateInstance(i).show())}_getChildren(){return R.find(Gs,this._parent)}_getActiveElem(){return this._getChildren().find(t=>this._elemIsActive(t))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=R.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=R.findOne(t,i);s&&s.classList.toggle(n,e)};n(Xs,Vs),n(".dropdown-menu",Qs),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Vs)}_getInnerElement(t){return t.matches(Gs)?t:R.findOne(Gs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each(function(){const e=Zs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}})}}P.on(document,js,Us,function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this)||Zs.getOrCreateInstance(this).show()}),P.on(window,Fs,()=>{for(const t of R.find(Js))Zs.getOrCreateInstance(t)}),g(Zs);const to=".bs.toast",eo=`mouseover${to}`,io=`mouseout${to}`,no=`focusin${to}`,so=`focusout${to}`,oo=`hide${to}`,ro=`hidden${to}`,ao=`show${to}`,lo=`shown${to}`,co="hide",ho="show",uo="showing",fo={animation:"boolean",autohide:"boolean",delay:"number"},po={animation:!0,autohide:!0,delay:5e3};class mo extends B{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return po}static get DefaultType(){return fo}static get NAME(){return"toast"}show(){P.trigger(this._element,ao).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(co),u(this._element),this._element.classList.add(ho,uo),this._queueCallback(()=>{this._element.classList.remove(uo),P.trigger(this._element,lo),this._maybeScheduleHide()},this._element,this._config.animation))}hide(){this.isShown()&&(P.trigger(this._element,oo).defaultPrevented||(this._element.classList.add(uo),this._queueCallback(()=>{this._element.classList.add(co),this._element.classList.remove(uo,ho),P.trigger(this._element,ro)},this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(ho),super.dispose()}isShown(){return this._element.classList.contains(ho)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout(()=>{this.hide()},this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){P.on(this._element,eo,t=>this._onInteraction(t,!0)),P.on(this._element,io,t=>this._onInteraction(t,!1)),P.on(this._element,no,t=>this._onInteraction(t,!0)),P.on(this._element,so,t=>this._onInteraction(t,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each(function(){const e=mo.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}})}}return q(mo),g(mo),{Alert:X,Button:U,Carousel:St,Collapse:qt,Dropdown:Qi,Modal:Ln,Offcanvas:Qn,Popover:vs,ScrollSpy:Ss,Tab:Zs,Toast:mo,Tooltip:ps}}); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/src/web/public/css/admin.css b/src/web/public/css/admin.css deleted file mode 100644 index 97773d2..0000000 --- a/src/web/public/css/admin.css +++ /dev/null @@ -1,2704 +0,0 @@ -:root { - color-scheme: light; - --bg: #eef2f7; - --bg-accent: #f8fbff; - --surface: #ffffff; - --surface-alt: #f6f8fc; - --text: #102033; - --muted: #66758a; - --border: rgba(16, 32, 51, 0.1); - --border-strong: rgba(16, 32, 51, 0.16); - --primary: #2563eb; - --primary-dark: #1d4ed8; - --primary-soft: rgba(37, 99, 235, 0.12); - --success: #0f9d58; - --danger: #dc2626; - --warning: #b45309; - --focus-ring: rgba(37, 99, 235, 0.18); - --page-html-bg: radial-gradient(circle at top left, rgba(37, 99, 235, 0.12), transparent 30%), linear-gradient(180deg, #f9fbff 0%, var(--bg) 100%); - --page-body-bg: radial-gradient(circle at top right, rgba(14, 165, 233, 0.16), transparent 24%), radial-gradient(circle at 20% 0%, rgba(37, 99, 235, 0.12), transparent 22%), linear-gradient(180deg, #f8fbff 0%, var(--bg) 100%); - --auth-body-bg: radial-gradient(circle at top left, rgba(34, 197, 94, 0.16), transparent 24%), radial-gradient(circle at 80% 20%, rgba(37, 99, 235, 0.18), transparent 28%), linear-gradient(180deg, #eef5fb 0%, #e6edf6 100%); - --sidebar-background: radial-gradient(circle at top right, rgba(59, 130, 246, 0.18), transparent 30%), linear-gradient(180deg, #0f172a 0%, #111c32 100%); - --sidebar-border: rgba(255, 255, 255, 0.08); - --sidebar-text: #dbe7ff; - --sidebar-text-strong: #ffffff; - --sidebar-muted: rgba(219, 231, 255, 0.7); - --sidebar-surface: rgba(255, 255, 255, 0.06); - --sidebar-hover: rgba(255, 255, 255, 0.12); - --sidebar-divider: rgba(219, 231, 255, 0.12); - --sidebar-link: #93c5fd; - --table-border: rgba(16, 32, 51, 0.08); - --table-hover: rgba(37, 99, 235, 0.04); - --table-row-odd: rgba(15, 23, 42, 0.02); - --table-row-even: rgba(255, 255, 255, 0.82); - --stat-background: linear-gradient(180deg, var(--surface), var(--surface-alt)); - --button-secondary-bg: #334155; - --button-secondary-hover: #1f2937; - --theme-toggle-bg: linear-gradient(180deg, var(--surface), var(--surface-alt)); - --theme-toggle-hover: linear-gradient(180deg, var(--surface-alt), var(--surface)); - --editor-paper: #ffffff; - --editor-text: #000000; - --shadow-lg: 0 24px 60px rgba(15, 23, 42, 0.16); - --shadow-md: 0 16px 28px rgba(15, 23, 42, 0.12); - --shadow-sm: 0 8px 20px rgba(15, 23, 42, 0.08); -} - -html[data-theme='dark'] { - color-scheme: dark; - --bg: #0b1220; - --bg-accent: #111827; - --surface: #111b2d; - --surface-alt: #172337; - --text: #e6eefb; - --muted: #9ba9be; - --border: rgba(148, 163, 184, 0.16); - --border-strong: rgba(148, 163, 184, 0.26); - --primary: #60a5fa; - --primary-dark: #3b82f6; - --primary-soft: rgba(96, 165, 250, 0.16); - --success: #34d399; - --danger: #f87171; - --warning: #f59e0b; - --focus-ring: rgba(96, 165, 250, 0.28); - --page-html-bg: radial-gradient(circle at top left, rgba(96, 165, 250, 0.16), transparent 26%), linear-gradient(180deg, #060b14 0%, #0b1220 100%); - --page-body-bg: radial-gradient(circle at top right, rgba(14, 165, 233, 0.12), transparent 24%), radial-gradient(circle at 20% 0%, rgba(96, 165, 250, 0.12), transparent 22%), linear-gradient(180deg, #08111d 0%, #0b1220 100%); - --auth-body-bg: radial-gradient(circle at top left, rgba(34, 197, 94, 0.12), transparent 24%), radial-gradient(circle at 80% 20%, rgba(96, 165, 250, 0.16), transparent 28%), linear-gradient(180deg, #070d18 0%, #0b1220 100%); - --sidebar-background: radial-gradient(circle at top right, rgba(59, 130, 246, 0.14), transparent 30%), linear-gradient(180deg, #09101d 0%, #0e1728 100%); - --sidebar-border: rgba(148, 163, 184, 0.1); - --sidebar-text: #dce8fb; - --sidebar-text-strong: #ffffff; - --sidebar-muted: rgba(220, 232, 251, 0.66); - --sidebar-surface: rgba(255, 255, 255, 0.08); - --sidebar-hover: rgba(255, 255, 255, 0.14); - --sidebar-divider: rgba(148, 163, 184, 0.12); - --sidebar-link: #bfdbfe; - --table-border: rgba(148, 163, 184, 0.14); - --table-hover: rgba(96, 165, 250, 0.08); - --table-row-odd: rgba(255, 255, 255, 0.03); - --table-row-even: rgba(15, 23, 42, 0.28); - --stat-background: linear-gradient(180deg, var(--surface), var(--surface-alt)); - --button-secondary-bg: #334155; - --button-secondary-hover: #475569; - --theme-toggle-bg: linear-gradient(180deg, #162235, #111b2d); - --theme-toggle-hover: linear-gradient(180deg, #1b2a41, #162235); - --editor-paper: #ffffff; - --editor-text: #000000; - --shadow-lg: 0 28px 64px rgba(2, 6, 23, 0.45); - --shadow-md: 0 18px 30px rgba(2, 6, 23, 0.28); - --shadow-sm: 0 10px 22px rgba(2, 6, 23, 0.24); -} - -* { - box-sizing: border-box; -} - -html { - min-height: 100%; - -webkit-text-size-adjust: 100%; - background: var(--page-html-bg); -} - -body { - margin: 0; - min-height: 100vh; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - color: var(--text); - background: var(--page-body-bg); -} - -a { - color: var(--primary); -} - -/* Shared admin shell and global UI used across most admin pages. */ -.admin-shell-body { - overflow-x: hidden; -} - -.app-shell { - min-height: 100vh; - display: grid; - grid-template-columns: 280px minmax(0, 1fr); -} - -.sidebar { - position: sticky; - top: 0; - align-self: start; - min-height: 100vh; - display: flex; - flex-direction: column; - padding: 16px 12px 12px; - color: var(--sidebar-text); - background: var(--sidebar-background); - border-right: 1px solid var(--sidebar-border); -} - -.brand { - display: flex; - align-items: center; - gap: 12px; - padding: 6px 8px 16px; -} - -.brand-mark { - width: 44px; - height: 44px; - border-radius: 14px; - display: grid; - place-items: center; - background: linear-gradient(135deg, #f97316, #eab308 24%, #22c55e 48%, #06b6d4 72%, #8b5cf6); - background-size: 220% 220%; - animation: logo-rainbow 8s ease-in-out infinite; - color: #fff; - font-weight: 800; - letter-spacing: 0.08em; - box-shadow: 0 12px 30px rgba(37, 99, 235, 0.4); -} - -.brand-copy { - display: grid; - gap: 2px; -} - -.brand-copy strong { - font-size: 16px; - letter-spacing: 0.01em; -} - -.brand-copy span { - color: var(--sidebar-muted); - font-size: 12px; -} - -.sidebar-actions { - padding: 4px 8px 12px; -} - -.nav { - display: grid; - gap: 8px; -} - -.nav-label { - padding: 10px 12px 4px; - color: var(--sidebar-muted); - text-transform: uppercase; - letter-spacing: 0.12em; - font-size: 11px; -} - -.nav-item { - display: flex; - align-items: center; - gap: 10px; - color: var(--sidebar-text); - text-decoration: none; - padding: 12px 14px; - border-radius: 14px; - background: transparent; - transition: background-color 160ms ease, color 160ms ease, transform 160ms ease; -} - -.nav-item::before { - content: ''; - width: 8px; - height: 8px; - border-radius: 999px; - background: rgba(255, 255, 255, 0.24); - flex: none; -} - -.nav-item.active, -.nav-item:hover { - background: var(--sidebar-surface); - color: var(--sidebar-text-strong); - transform: translateX(2px); -} - -.nav-item.active::before, -.nav-item:hover::before { - background: #60a5fa; -} - -.sidebar-footer { - padding: 16px 14px 8px; - display: flex; - align-items: center; - gap: 12px; - color: var(--sidebar-text); -} - -.sidebar-footer--bottom { - margin-top: auto; - padding: 0; - justify-content: space-between; - gap: 16px; -} - -.sidebar-footer strong, -.sidebar-footer > div > span, -.sidebar-footer > .sidebar-version { - display: block; -} - -.sidebar-footer strong { - color: var(--sidebar-text-strong); - font-size: 14px; -} - -.sidebar-account-name { - color: var(--sidebar-text-strong); - font-size: 14px; - font-weight: 800; -} - -.sidebar-footer > div > span { - color: var(--sidebar-muted); - font-size: 12px; - line-height: 1.35; -} - -.sidebar-footer--account { - align-items: flex-start; - gap: 10px; - justify-content: flex-start; -} - -.sidebar-divider { - height: 1px; - margin: 10px 14px 4px; - background: var(--sidebar-divider); -} - -.user-avatar { - width: 34px; - height: 34px; - min-width: 34px; - border-radius: 999px; - display: grid; - place-items: center; - flex: none; - background: linear-gradient(180deg, #60a5fa, #2563eb); - color: #fff; - font-size: 14px; - font-weight: 800; - letter-spacing: 0.02em; - box-shadow: 0 10px 22px rgba(37, 99, 235, 0.28); -} - -.user-avatar--fallback { - background: linear-gradient(180deg, #94a3b8, #64748b); - box-shadow: 0 10px 22px rgba(100, 116, 139, 0.2); -} - -.sidebar-footer-links { - display: flex; - gap: 12px; - margin-top: 8px; - flex-wrap: wrap; -} - -.sidebar-footer-links a { - color: var(--sidebar-link); - text-decoration: none; - font-size: 12px; - font-weight: 700; -} - -.sidebar-footer-links a:hover { - color: var(--sidebar-text-strong); -} - -.sidebar-version { - color: var(--sidebar-muted); - font-size: 12px; - font-weight: 700; - letter-spacing: 0.04em; - text-transform: lowercase; -} - -.theme-toggle { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0; - width: auto; - min-height: 0; - margin-top: 0; - padding: 6px; - border: 0; - border-radius: 0; - background: transparent; - color: var(--text); - box-shadow: none; -} - -.theme-toggle:hover { - background: transparent; - filter: none; -} - -.theme-toggle:active { - transform: translateY(1px); - filter: none; -} - -.theme-toggle__label { - display: block; - text-align: left; - line-height: 1.1; -} - -.theme-toggle__icon { - position: relative; - display: inline-block; - width: 16px; - height: 16px; - flex: none; -} - -.theme-toggle__icon--moon { - border-radius: 50%; - background: var(--theme-toggle-bg); - color: var(--text); -} - -.login-page-body .theme-toggle__icon--moon { - background: currentColor; -} - -.theme-toggle__icon--moon::after { - content: ''; - position: absolute; - top: -1px; - right: -3px; - width: 12px; - height: 12px; - border-radius: 50%; - background: var(--sidebar-background); -} - -.login-page-body .theme-toggle__icon--moon::after { - background: var(--auth-body-bg); -} - -.theme-toggle__icon--sun { - display: none; - color: var(--text); -} - -.theme-toggle__icon--sun::before, -.theme-toggle__icon--sun::after { - content: ''; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - border-radius: 50%; -} - -.theme-toggle__icon--sun::before { - width: 2px; - height: 2px; - background: currentColor; - box-shadow: - 0 -8px 0 0 currentColor, - 0 8px 0 0 currentColor, - 8px 0 0 0 currentColor, - -8px 0 0 0 currentColor, - 6px 6px 0 0 currentColor, - -6px 6px 0 0 currentColor, - 6px -6px 0 0 currentColor, - -6px -6px 0 0 currentColor; -} - -.theme-toggle__icon--sun::after { - width: 7px; - height: 7px; - background: var(--theme-toggle-bg); - box-shadow: inset 0 0 0 2px currentColor; -} - -html[data-theme='dark'] .theme-toggle__icon--sun { - display: inline-block; -} - -.theme-toggle--sidebar { - width: auto; - padding: 0; - justify-content: center; - margin: 0; - color: var(--sidebar-text-strong); -} - -.theme-toggle--sidebar .theme-toggle__icon--moon, -.theme-toggle--sidebar .theme-toggle__icon--sun { - color: var(--sidebar-text-strong); -} - -.theme-toggle--sidebar .theme-toggle__label { - display: none; -} - -.theme-toggle--sidebar .theme-toggle__icon { - width: 18px; - height: 18px; -} - -.theme-toggle--floating { - width: auto; - padding: 0; - justify-content: center; - position: fixed; - top: 16px; - right: 16px; - z-index: 90; -} - -.theme-toggle--floating .theme-toggle__label { - display: none; -} - -.theme-toggle--floating .theme-toggle__icon { - width: 18px; - height: 18px; -} - -.auth-shell-body .theme-toggle--floating { - top: auto; - bottom: 16px; -} - -.status-dot { - width: 12px; - height: 12px; - border-radius: 999px; - background: #22c55e; - box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.14); - flex: none; -} - -.status-dot--unknown { - background: #94a3b8; - box-shadow: 0 0 0 6px rgba(148, 163, 184, 0.14); -} - -.status-dot--online { - background: #22c55e; - box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.14); -} - -.status-dot--offline { - background: #ef4444; - box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.14); -} - -.status-pill--unknown { - color: #334155; - background: rgba(148, 163, 184, 0.18); -} - -.status-pill--online { - color: #14532d; - background: rgba(34, 197, 94, 0.16); -} - -.status-pill--offline { - color: #7f1d1d; - background: rgba(239, 68, 68, 0.14); -} - -.shell-main { - min-width: 0; -} - -.status-pill { - display: inline-flex; - align-items: center; - gap: 8px; - min-height: 38px; - padding: 0 14px; - border-radius: 999px; - font-size: 13px; - font-weight: 700; - text-decoration: none; - color: #0f5132; - background: rgba(16, 185, 129, 0.14); -} - -.content { - padding: 28px; -} - -/* Dashboard and list-style admin pages. */ -.page-shell { - display: grid; - gap: 18px; -} - -.page-shell > * { - animation: fade-up 240ms ease-out both; -} - -.page-header { - display: flex; - align-items: end; - justify-content: space-between; - gap: 16px; - margin-bottom: 4px; -} - -.page-header h2 { - margin: 0; - font-size: 22px; - line-height: 1.2; -} - -.page-header p { - margin: 0; - color: var(--muted); -} - -.toast { - position: fixed; - top: auto; - bottom: 20px; - right: 20px; - z-index: 1000; - display: flex; - align-items: center; - gap: 12px; - max-width: min(360px, calc(100vw - 40px)); - padding: 10px 14px; - border-radius: 16px; - background: linear-gradient(180deg, var(--surface), var(--surface-alt)); - border: 1px solid var(--border-strong); - border-left: 4px solid var(--primary); - color: var(--text); - box-shadow: var(--shadow-md); -} - -.toast-body { - flex: 1; - line-height: 1.4; -} - -.toast-close { - width: 30px; - min-width: 30px; - height: 30px; - margin: 0; - padding: 0; - border-radius: 999px; - background: var(--bg); - color: var(--muted); - font-size: 20px; - line-height: 1; -} - -.toast-close:hover { - background: var(--surface-alt); - color: var(--text); -} - -.toast-hide { - opacity: 0; - transform: translateY(-8px); - transition: opacity 180ms ease, transform 180ms ease; -} - -.grid { - display: grid; - gap: 16px; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); -} - -.card { - background: var(--surface); - border: 1px solid var(--border); - border-radius: 20px; - padding: 18px; - box-shadow: var(--shadow-sm); - margin-bottom: 0; -} - -/* Authentication pages. */ -.auth-shell-body { - background: var(--auth-body-bg); -} - -.auth-page { - min-height: 100vh; - display: grid; - place-items: center; - padding: 24px; -} - -.auth-card { - width: min(100%, 480px); - padding: 28px; -} - -.auth-brand { - display: flex; - gap: 16px; - align-items: center; - margin-bottom: 18px; -} - -.auth-brand h1 { - margin: 4px 0 6px; - font-size: 28px; -} - -.auth-brand p, -.auth-hint { - margin: 0; - color: var(--muted); -} - -.eyebrow { - display: block; - color: var(--primary-dark); - text-transform: uppercase; - letter-spacing: 0.12em; - font-size: 11px; - font-weight: 800; -} - -.auth-message { - margin: 18px 0 0; - padding: 12px 14px; - border-radius: 14px; - background: var(--primary-soft); - color: var(--primary-dark); - font-weight: 700; -} - -.auth-form { - display: grid; - gap: 16px; - margin-top: 18px; -} - -.auth-form button { - margin-top: 4px; -} - -.auth-hint { - margin-top: 16px; - font-size: 13px; - line-height: 1.5; -} - -/* Account and user management pages. */ -.account-card { - max-width: 720px; -} - -.user-create-card { - max-width: 980px; -} - -.user-create-form { - display: grid; - gap: 20px; -} - -.user-create-section { - display: grid; - gap: 14px; -} - -.user-create-section h3 { - margin: 0; -} - -.user-create-fields { - display: grid; - gap: 14px; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); -} - -.user-create-fields label { - display: grid; - gap: 8px; -} - -.user-create-actions { - margin-top: 4px; - flex-wrap: wrap; -} - -.user-create-button { - min-height: 42px; - padding-left: 18px; - padding-right: 18px; -} - -.button-link.secondary { - background: var(--button-secondary-bg); -} - -.button-link.secondary:hover { - background: var(--button-secondary-hover); -} - -.user-edit-card { - max-width: 980px; -} - -.user-edit-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - margin-bottom: 16px; -} - -.user-edit-grid { - display: grid; - gap: 16px; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); -} - -.user-edit-panel { - display: grid; - gap: 14px; - margin-bottom: 0; -} - -.user-edit-panel h3 { - margin: 0; -} - -.user-edit-button { - width: 100%; - min-height: 42px; - display: flex; - align-items: center; - justify-content: center; - white-space: nowrap; -} - -.template-field-head { - display: flex; - justify-content: space-between; - gap: 8px; - align-items: center; - margin-bottom: 8px; -} - -.users-table th:last-child { - width: 220px; -} - -.users-row-actions { - justify-content: flex-start; -} - -.user-cell { - display: flex; - align-items: center; - gap: 12px; -} - -.user-avatar--small { - width: 30px; - height: 30px; - min-width: 30px; - font-size: 12px; -} - -.user-inline-form, -.user-password-form { - display: grid; - gap: 8px; -} - -.user-password-form { - grid-template-columns: minmax(120px, 1fr) minmax(120px, 1fr) auto; - align-items: start; -} - -/* Playlist, canvas size, template, and screen edit pages. */ -.user-inline-form .button-link, -.user-password-form .button-link { - width: fit-content; -} - -.account-form { - display: grid; - gap: 16px; -} - -.account-form .actions { - margin-top: 4px; -} - -.account-form .button-link.secondary { - background: var(--button-secondary-bg); -} - -.account-form .button-link.secondary:hover { - background: var(--button-secondary-hover); -} - -.playlist-name-card { - margin-bottom: 16px; -} - -.slide-template-card { - margin-bottom: 16px; -} - -.template-meta-card { - margin-bottom: 16px; -} - -.canvas-size-form { - display: grid; - gap: 16px; -} - -.canvas-size-form .row { - align-items: stretch; -} - -.canvas-size-form button { - margin-top: 0; -} - -.screen-edit-form { - display: grid; - gap: 14px; -} - -.screen-edit-form label { - display: grid; - gap: 8px; -} - -.screen-edit-form input, -.screen-edit-form select, -.screen-edit-form button { - margin-top: 0; -} - -.screen-edit-form button { - width: fit-content; -} - -.screen-edit-actions { - display: flex; - padding-top: 14px; - gap: 10px; - flex-wrap: wrap; - align-items: center; -} - -.screen-edit-actions .inline-form { - display: inline-flex; -} - -.screen-edit-actions button, -.screen-edit-actions .inline-form button { - width: fit-content; - margin-top: 0; -} - -/* Shared table, form, and widget styling used across admin pages. */ -.card h3 { - margin: 0 0 14px; - font-size: 18px; -} - -.stats { - display: grid; - gap: 12px; - grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); - margin-bottom: 0; -} - -.stat { - position: relative; - overflow: hidden; - background: var(--stat-background); - border: 1px solid var(--border); - border-radius: 12px; - padding: 16px; - box-shadow: var(--shadow-sm); - margin-bottom: 0; -} - -.stat::after { - content: ''; - position: absolute; - inset: auto -16px -18px auto; - width: 88px; - height: 88px; - background-repeat: no-repeat; - background-position: center; - background-size: 64% 64%; - opacity: 0.18; - pointer-events: none; -} - -.stats .stat:nth-child(1)::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6h16'/%3E%3Cpath d='M4 12h16'/%3E%3Cpath d='M4 18h10'/%3E%3C/svg%3E"); -} - -.stats .stat:nth-child(2)::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='4' width='16' height='16' rx='2'/%3E%3Cpath d='M8 13l2-2 3 3 2-2 3 3'/%3E%3Cpath d='M8 9h.01'/%3E%3C/svg%3E"); -} - -.stats .stat:nth-child(3)::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='12' rx='2'/%3E%3Cpath d='M8 19h8'/%3E%3Cpath d='M12 17v2'/%3E%3C/svg%3E"); -} - -.stats .stat:nth-child(4)::after { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z'/%3E%3Cpath d='M16 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z'/%3E%3Cpath d='M4.5 19a5.5 5.5 0 0 1 11 0'/%3E%3Cpath d='M14 19a4.5 4.5 0 0 1 5.5-4.4'/%3E%3C/svg%3E"); -} - -.stat strong { - position: relative; - display: block; - font-size: 32px; - line-height: 1; - margin-bottom: 8px; -} - -.stat span { - position: relative; - color: var(--muted); - font-size: 13px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.stat span { - position: relative; - color: var(--muted); - font-size: 13px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.row { - display: flex; - gap: 12px; - flex-wrap: wrap; - align-items: center; -} - -.switch-field { - display: inline-flex; - align-items: center; - gap: 12px; - width: fit-content; - margin-top: 5px; - align-self: center; -} - -.switch-control { - position: relative; - display: inline-flex; - align-items: center; - cursor: pointer; - flex: none; -} - -.switch-control input { - position: absolute; - width: 1px; - height: 1px; - margin: 0; - padding: 0; - border: 0; - clip: rect(0, 0, 0, 0); - clip-path: inset(50%); - overflow: hidden; - white-space: nowrap; -} - -.switch-ui { - position: relative; - width: 54px; - height: 32px; - border-radius: 999px; - background: #cbd5e1; - border: 1px solid rgba(16, 32, 51, 0.14); - box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.12); - flex: none; - transition: background-color 160ms ease, border-color 160ms ease, box-shadow 160ms ease; -} - -.switch-ui::after { - content: ''; - position: absolute; - top: 3px; - left: 3px; - width: 24px; - height: 24px; - border-radius: 50%; - background: #fff; - box-shadow: 0 6px 16px rgba(15, 23, 42, 0.18); - transition: transform 160ms ease; -} - -.switch-label { - font-size: 14px; - font-weight: 700; - color: var(--text); - line-height: 1; -} - -.switch-control input:checked + .switch-ui { - background: linear-gradient(180deg, var(--primary), var(--primary-dark)); - border-color: rgba(37, 99, 235, 0.55); - box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08), 0 0 0 4px rgba(37, 99, 235, 0.12); -} - -.switch-control input:checked + .switch-ui::after { - transform: translateX(22px); -} - -.switch-field:focus-within .switch-ui { - outline: 3px solid rgba(37, 99, 235, 0.18); - outline-offset: 2px; -} - -.actions { - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; -} - -.page-toolbar { - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; - justify-content: flex-end; -} - -/* Shared form controls. */ -label { - display: block; - font-size: 14px; - font-weight: 700; - color: var(--text); -} - -label > input, -label > textarea, -label > select, -label > button { - margin-top: 6px; -} - -input, -textarea, -select, -button { - width: 100%; - box-sizing: border-box; - padding: 10px 12px; - border: 1px solid var(--border-strong); - border-radius: 12px; - font: inherit; - background: var(--surface); - color: var(--text); -} - -input:focus, -textarea:focus, -button:focus-visible, -a.button-link:focus-visible, -button.sidebar-toggle:focus-visible { - outline: 3px solid var(--focus-ring); - outline-offset: 2px; -} - -select:focus-visible { - outline: 3px solid var(--focus-ring); - outline-offset: 2px; -} - -select:focus { - outline: none; -} - -button:focus, -a.button-link:focus, -button.sidebar-toggle:focus { - outline: none; -} - -button { - background: linear-gradient(180deg, var(--primary), var(--primary-dark)); - color: #fff; - border: none; - cursor: pointer; - font-weight: 800; - box-shadow: 0 10px 20px rgba(37, 99, 235, 0.18); -} - -button:hover { - filter: brightness(0.92); -} - -button:active, -a.button-link:active, -button.sidebar-toggle:active { - filter: brightness(1.08); -} - -button.secondary, -a.button-link, -.status-pill { - border: 1px solid transparent; -} - -button.secondary { - background: var(--button-secondary-bg); -} - -button.secondary:hover { - background: var(--button-secondary-hover); -} - -button.danger, -button.is-danger { - background: linear-gradient(180deg, #ef4444, #dc2626); - box-shadow: 0 10px 18px rgba(220, 38, 38, 0.18); -} - -button.danger:hover, -button.is-danger:hover { - background: linear-gradient(180deg, #dc2626, #b91c1c); -} - -button.is-paused, -button.is-blackout { - background: linear-gradient(180deg, #f59e0b, #d97706); -} - -.ce-inline-toolbar__buttons button, -.ce-inline-toolbar__actions button { - background: transparent; - color: inherit; - box-shadow: none; -} - -.ce-inline-toolbar__buttons button:hover, -.ce-inline-toolbar__actions button:hover { - background: rgba(255, 255, 255, 0.08); - filter: none; -} - -a.button-link { - display: inline-flex; - align-items: center; - justify-content: center; - min-height: 42px; - background: linear-gradient(180deg, var(--primary), var(--primary-dark)); - color: #fff; - text-decoration: none; - padding: 10px 14px; - border-radius: 12px; - font-weight: 800; - box-shadow: 0 10px 20px rgba(37, 99, 235, 0.18); -} - -a.button-link:hover { - color: #fff; - filter: brightness(0.92); -} - -.list-action { - display: inline-flex; - align-items: center; - justify-content: center; - width: 104px; - min-width: 104px; - box-sizing: border-box; - font: inherit; - font-size: 14px; - line-height: 1.2; - font-weight: 800; - text-align: center; - box-shadow: none; -} - -.actions a.button-link.list-action, -.actions button.list-action { - min-height: 38px; - padding: 8px 12px; - border-radius: 11px; - font-size: 13px; - line-height: 1.1; -} - -.actions a.button-link.list-action { - min-width: 96px; -} - -.actions button.list-action { - min-width: 96px; -} - -.list-action--nav, -a.button-link.list-action.list-action--nav, -button.list-action.list-action--nav { - width: 36.8px; - min-width: 36.8px; - height: 36.8px; - padding: 0; - display: inline-grid; - place-items: center; - font-size: 15px; - line-height: 1; - border-radius: 12px; - background: linear-gradient(180deg, #f59e0b, #d97706); - color: #fff; -} - -table .inline-form button.list-action--nav { - width: 36.8px; - min-width: 36.8px; - height: 36.8px; - padding: 0; -} - -.list-action--nav:hover { - filter: brightness(0.92); -} - -a.button-link.list-action, -button.list-action { - padding: 10px 14px; -} - -table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - overflow: hidden; - border-radius: 16px; -} - -th, -td { - text-align: left; - padding: 13px 14px; - border-bottom: 1px solid var(--table-border); - vertical-align: middle; - line-height: 1.4; -} - -thead th { - font-size: 13px; - font-weight: 800; - color: var(--muted); - text-transform: uppercase; - letter-spacing: 0.06em; - background: var(--surface-alt); -} - -tbody tr:hover { - background: rgba(37, 99, 235, 0.07); -} - -tbody tr:last-child td { - border-bottom: none; -} - -.inline-form { - display: inline-flex; - margin: 0; -} - -.subtle { - color: var(--muted); - font-size: 13px; -} - -.connection-count { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-radius: 999px; - background: rgba(37, 99, 235, 0.1); - color: #1d4ed8; - font-size: 12px; - font-weight: 800; - margin-bottom: 8px; -} - -.connection-id { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-radius: 999px; - background: rgba(15, 118, 110, 0.12); - color: #0f766e; - font-size: 12px; - font-weight: 700; -} - -#dashboard-screens-table th:last-child, -#dashboard-screens-table td:last-child { - width: auto; - white-space: normal; -} - -.sidebar-toggle { - display: none; - align-items: center; - justify-content: center; - gap: 5px; - width: 46px; - height: 46px; - margin: 0; - padding: 0; - border-radius: 14px; - background: var(--surface); - border: 1px solid var(--border); - box-shadow: var(--shadow-sm); - flex: none; -} - -.sidebar-toggle--shell { - position: fixed; - top: 16px; - right: 16px; - left: auto; - z-index: 70; -} - -.sidebar-toggle-icon { - position: relative; - display: block; - width: 18px; - height: 2px; - border-radius: 999px; - background: #334155; - box-shadow: 0 -6px 0 #334155, 0 6px 0 #334155; -} - -.sidebar-backdrop { - display: none; -} - -.app-shell--frame { - grid-template-columns: 1fr; -} - -.shell-main--frame { - min-height: 100vh; -} - -.topbar--frame { - position: sticky; - top: 0; -} - -.content--frame { - padding: 20px; -} - -.page-shell--frame { - gap: 0; -} - -.admin-shell-body--frame-plain { - background: var(--surface); -} - -.admin-shell-body--frame-plain .content--frame { - padding: 0; - background: var(--surface); -} - -.admin-shell-body--frame-plain .page-shell--frame { - padding-top: 12px; -} - -.admin-shell-body--frame-plain .card { - box-shadow: none; -} - -.admin-shell-body--frame-plain button[type="submit"] { - padding: 8px 12px; -} - -@keyframes fade-up { - from { - opacity: 0; - transform: translateY(8px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes logo-rainbow { - 0% { - background-position: 0% 50%; - } - - 50% { - background-position: 100% 50%; - } - - 100% { - background-position: 0% 50%; - } -} - -/* Responsive shell behavior. */ -@media (max-width: 1100px) { - .app-shell { - grid-template-columns: 1fr; - } - - .sidebar { - position: fixed; - z-index: 60; - inset: 0 auto 0 0; - width: min(88vw, 320px); - transform: translateX(-104%); - transition: transform 220ms ease; - box-shadow: var(--shadow-lg); - } - - .admin-shell-body.is-sidebar-open .sidebar { - transform: translateX(0); - } - - .sidebar-toggle { - display: inline-flex; - } - - .sidebar-toggle--shell { - display: inline-flex; - } - - .sidebar-backdrop { - display: block; - position: fixed; - inset: 0; - z-index: 50; - width: 100%; - height: 100%; - margin: 0; - padding: 0; - border: 0; - border-radius: 0; - background: rgba(15, 23, 42, 0.42); - opacity: 0; - pointer-events: none; - transition: opacity 220ms ease; - } - - .admin-shell-body.is-sidebar-open .sidebar-backdrop { - opacity: 1; - pointer-events: auto; - } - - .content { - padding: 18px; - } -} - -@media (max-width: 720px) { - .toast { - top: auto; - bottom: 12px; - left: auto; - right: 12px; - max-width: none; - } - - .content { - padding: 12px; - } - - .page-shell { - gap: 12px; - } - - .page-header { - align-items: flex-start; - flex-direction: column; - padding-right: 72px; - } - - .card { - padding: 14px; - border-radius: 16px; - } - - .actions, - .playlist-item-actions, - .page-toolbar, - .playlist-edit-actions { - align-items: stretch; - flex-direction: row; - flex-wrap: wrap; - } - - .actions > *, - .playlist-item-actions > *, - .page-toolbar > *, - .playlist-edit-actions > * { - flex: 1 1 calc(50% - 6px); - min-width: 140px; - } - - .page-toolbar > *, - .playlist-edit-actions > * { - min-width: 160px; - } - - .stats { - grid-template-columns: 1fr; - } - - table.table-cards { - display: block; - width: 100%; - border-collapse: separate; - border-spacing: 0 12px; - overflow: visible; - } - - table.table-cards thead { - display: none; - } - - table.table-cards tbody { - display: grid; - gap: 12px; - } - - table.table-cards tbody tr { - display: grid; - gap: 8px; - padding: 14px; - border: 1px solid var(--border); - border-radius: 16px; - background: var(--surface); - box-shadow: var(--shadow-sm); - } - - table.table-cards th, - table.table-cards td { - display: flex; - flex-direction: column; - gap: 6px; - padding: 0; - border: 0; - white-space: normal; - } - - table.table-cards td::before { - content: attr(data-label); - color: var(--muted); - font-size: 11px; - font-weight: 800; - text-transform: uppercase; - letter-spacing: 0.06em; - } - - table.table-cards td.empty::before { - content: ''; - } - - table.table-cards td[data-label="Actions"] { - width: 1%; - white-space: nowrap; - } - - table.table-cards td .actions { - gap: 6px; - justify-content: flex-start; - } - - table.table-cards td[data-label="Actions"] .actions { - display: inline-flex; - flex-wrap: nowrap; - align-items: center; - justify-content: flex-start; - width: auto; - } - - table.table-cards td[data-label="Actions"] .actions > * { - flex: 0 0 auto; - min-width: 0; - } - - table.table-cards td[data-label="Actions"] .actions > * { - width: auto; - align-self: flex-start; - } - - .inline-form { - display: flex; - flex: 0 0 auto; - min-width: 0; - } - - table.table-cards td[data-label="Actions"] .inline-form { - display: inline-flex; - min-width: 0; - width: auto; - } - - table.table-cards td[data-label="Actions"] .inline-form button, - table.table-cards td[data-label="Actions"] .button-link, - table.table-cards td[data-label="Actions"] .list-action { - display: inline-flex; - width: auto; - min-width: 0; - white-space: nowrap; - } - - table.table-cards td[data-label="Actions"] .inline-form button.list-action--nav, - table.table-cards td[data-label="Actions"] .list-action--nav { - flex: 0 0 36.8px; - min-width: 36.8px; - width: 36.8px; - height: 36.8px; - padding: 0; - } - - .inline-form button { - min-width: 0; - width: auto; - } -} - -thead th.sortable { - cursor: pointer; - user-select: none; - position: relative; - padding-right: 36px; -} - -thead th.sortable::after { - content: ''; - position: absolute; - right: 10px; - top: 50%; - display: grid; - place-items: center; - width: 18px; - height: 18px; - margin-top: -9px; - border-radius: 999px; - background: rgba(37, 99, 235, 0.08); - background-repeat: no-repeat; - background-position: center; - background-size: 10px 10px; - color: var(--primary); - font-size: 0; - font-weight: 900; - line-height: 1; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M6 1 L2.5 4.5 H9.5 Z' fill='%232563eb'/%3E%3Cpath d='M6 11 L2.5 7.5 H9.5 Z' fill='%232563eb'/%3E%3C/svg%3E"); -} - -thead th.sortable.sort-asc::after { - background: rgba(37, 99, 235, 0.16); - background-repeat: no-repeat; - background-position: center; - background-size: 10px 10px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M6 1 L2.5 4.5 H9.5 Z' fill='%232563eb'/%3E%3C/svg%3E"); -} - -thead th.sortable.sort-asc, -thead th.sortable.sort-desc { - color: var(--text); -} - -thead th.sortable.sort-desc::after { - background: rgba(37, 99, 235, 0.16); - background-repeat: no-repeat; - background-position: center; - background-size: 10px 10px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M6 11 L2.5 7.5 H9.5 Z' fill='%232563eb'/%3E%3C/svg%3E"); -} - -thead th.unsortable { - cursor: default; -} - -tbody tr:nth-child(odd) { - background: var(--table-row-odd); -} - -tbody tr:nth-child(even) { - background: var(--table-row-even); -} - -table input, -table select, -table textarea, -table button { - margin-top: 0; -} - -td .actions { - align-items: center; -} - -table th:last-child, -table td:last-child { - width: 1%; - white-space: nowrap; -} - -table td .actions { - width: auto; - justify-content: flex-end; - flex-wrap: nowrap; -} - -#dashboard-clients-table th:nth-child(1), -#dashboard-clients-table td:nth-child(1) { - width: 24%; - min-width: 240px; -} - -#dashboard-clients-table th:nth-child(2), -#dashboard-clients-table td:nth-child(2) { - width: 16%; - min-width: 120px; -} - -#dashboard-clients-table th:nth-child(3), -#dashboard-clients-table td:nth-child(3) { - width: 14%; - min-width: 110px; -} - -#dashboard-clients-table th:nth-child(4), -#dashboard-clients-table td:nth-child(4) { - width: 18%; - min-width: 150px; -} - -#dashboard-clients-table th:nth-child(5), -#dashboard-clients-table td:nth-child(5) { - width: 20%; - min-width: 180px; -} - -#dashboard-clients-table th:nth-child(6), -#dashboard-clients-table td:nth-child(6) { - width: 8%; - min-width: 220px; -} - -table td .inline-form, -table td .actions form { - flex: 0 0 auto; -} - -.inline-form button { - width: auto; - min-width: 112px; -} - -.list-action.is-paused { - background: #b45309; - color: #fff; - border-color: rgba(180, 83, 9, 0.24); - animation: action-flash 1.5s ease-in-out infinite alternate; -} - -.list-action.is-paused:hover { - background: #92400e; -} - -.list-action.is-danger { - background: #dc2626; - color: #fff; -} - -.list-action.is-danger:hover { - background: #b91c1c; -} - -.list-action.is-blackout { - background: #1f2937; - color: #fff; - border-color: rgba(31, 41, 55, 0.24); - animation: action-flash-blackout 0.75s ease-in-out infinite alternate; -} - -.list-action.is-blackout:hover { - background: #111827; -} - -@keyframes action-flash { - from { - background: #b45309; - filter: brightness(1); - } - - to { - background: #f59e0b; - filter: brightness(1.08); - } -} - -@keyframes action-flash-blackout { - from { - background: #235ce8; - filter: brightness(1); - } - - to { - background: #dd0b0b; - filter: brightness(1.08); - } -} - -.muted { - color: var(--muted); -} - -.playlist-item-actions { - flex-wrap: nowrap; - align-items: center; -} - -.playlist-order-cell { - width: 88px; - min-width: 88px; - white-space: nowrap; - vertical-align: middle; -} - -.playlist-order-cell-inner { - display: flex; - align-items: center; - gap: 8px; - min-height: 100%; -} - -.playlist-order-number { - min-width: 1.5em; - font-weight: 800; - color: var(--muted); -} - -.playlist-drag-handle { - flex: 0 0 auto; - width: 28px; - height: 28px; - padding: 0; - border: 0; - margin: 0; - border-radius: 0; - color: var(--muted); - background: currentColor; - -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 4L8 8H16L12 4Z'/%3E%3Cpath d='M4 11H20V13H4V11Z'/%3E%3Cpath d='M4 15H20V17H4V15Z'/%3E%3Cpath d='M4 7H20V9H4V7Z'/%3E%3Cpath d='M12 20L8 16H16L12 20Z'/%3E%3C/svg%3E") center / contain no-repeat; - mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 4L8 8H16L12 4Z'/%3E%3Cpath d='M4 11H20V13H4V11Z'/%3E%3Cpath d='M4 15H20V17H4V15Z'/%3E%3Cpath d='M4 7H20V9H4V7Z'/%3E%3Cpath d='M12 20L8 16H16L12 20Z'/%3E%3C/svg%3E") center / contain no-repeat; - cursor: grab; - transition: color 160ms ease; -} - -.playlist-drag-handle { - color: var(--muted); -} - -.playlist-drag-handle:hover, -.playlist-drag-handle:focus-visible { - color: var(--primary); -} - -html[data-theme='dark'] .playlist-drag-handle { - color: var(--sidebar-text); -} - -html[data-theme='dark'] .playlist-drag-handle:hover, -html[data-theme='dark'] .playlist-drag-handle:focus-visible { - color: var(--primary); -} - -.playlist-drag-handle:active, -tr.is-dragging .playlist-drag-handle { - cursor: grabbing; -} - -tr.sortable-chosen { - opacity: 0.55; -} - -tr.sortable-ghost { - opacity: 0.32; - background: var(--primary-soft); -} - -tr.sortable-drag { - box-shadow: var(--shadow-md); - background: var(--surface); -} - -#playlist-items-body tr.sortable-drag { - display: flex; - align-items: stretch; -} - -#playlist-items-body tr.sortable-drag > td { - display: flex; - flex: 0 0 auto; - align-items: center; -} - -#playlist-items-body tr.sortable-drag .playlist-order-cell-inner { - height: 100%; -} - -#playlist-items-body tr.sortable-drag .playlist-drag-handle { - align-self: center; -} - -@media (min-width: 721px) { -} - -.actions form { - display: inline; -} - -.playlist-edit-actions button { - width: auto; -} - -#playlist-add-slide-button { - margin-top: 12px; -} - -.playlist-edit-header { - align-items: flex-end; -} - -.playlist-name-field { - flex: 1; -} - -.empty { - color: var(--muted); - padding: 12px 0 12px 24px; -} - -.chip { - display: inline-block; - background: #e5e7eb; - color: #374151; - border-radius: 999px; - padding: 4px 10px; - font-size: 12px; - margin-left: 6px; -} - -html[data-theme='dark'] .chip { - background: rgba(148, 163, 184, 0.16); - color: var(--sidebar-text); -} - -.slide-editor-top { - display: grid; - grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); - gap: 16px; - align-items: start; - margin-bottom: 16px; -} - -.slide-image-file { - margin-top: 8px; -} - -.slide-preview-card { - display: flex; - flex-direction: column; - gap: 0; - padding: 0; -} - -.slide-preview-header { - margin-bottom: 0; - padding: 16px 16px 8px; -} - -.slide-preview-header h3 { - margin: 0; -} - -.slide-preview-stage { - position: relative; - width: 100%; - aspect-ratio: 16 / 9; - overflow: hidden; - border-radius: 0; - background: linear-gradient(135deg, #111827, #1f2937); -} - -.slide-preview-scroll { - min-height: 0; - padding: 0 16px 16px; - margin-top: 0; -} - -.slide-preview-scroll button { - margin-bottom: 8px; -} - -.slide-preview-background { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; -} - -.slide-preview-empty { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - text-align: center; - padding: 20px; - color: #cbd5e1; - background: rgba(17, 24, 39, 0.35); - z-index: 1; -} - -.slide-preview-overlay { - position: absolute; - inset: 0; - z-index: 2; -} - -.slide-preview-region { - position: absolute; - box-sizing: border-box; - padding: 0; - overflow: hidden; - color: #fff; - border: 1px solid rgba(255, 255, 255, 0.25); - background: rgba(15, 23, 42, 0.2); -} - -.slide-preview-region h1, -.slide-preview-region h2, -.slide-preview-region h3, -.slide-preview-region h4, -.slide-preview-region h5, -.slide-preview-region h6, -.slide-preview-region p, -.slide-preview-region blockquote, -.slide-preview-region ul, -.slide-preview-region ol, -.slide-preview-region pre { - margin: 0; -} - -.slide-preview-region ul, -.slide-preview-region ol { - padding-left: 18px; -} - -.slide-preview-region code { - white-space: pre-wrap; -} - -.slide-preview-text-content { - transform-origin: top left; - display: block; -} - -.slide-preview-image-region { - background: rgba(15, 23, 42, 0.25); -} - -.slide-preview-image { - width: 100%; - height: 100%; - object-fit: contain; - display: block; -} - -.slide-preview-webpage-region { - background: rgba(15, 23, 42, 0.35); - overflow: hidden; -} - -.slide-preview-webpage-frame { - width: 100%; - height: 100%; - border: 0; - display: block; - background: #fff; - overflow: hidden; -} - -.slide-preview-html-region { - background: rgba(15, 23, 42, 0.35); - overflow: hidden; -} - -.slide-preview-html-frame { - width: 100%; - height: 100%; - border: 0; - display: block; - background: transparent; - overflow: hidden; -} - -.slide-schedule-dialog { - width: min(900px, calc(100vw - 32px)); - max-width: 900px; - border: none; - border-radius: 12px; - padding: 16px; - background: var(--surface); - color: var(--text); - box-shadow: 0 24px 80px rgba(15, 23, 42, 0.35); -} - -.slide-schedule-dialog::backdrop { - background: rgba(15, 23, 42, 0.55); -} - -.slide-schedule-dialog iframe { - width: 100%; - height: auto; - min-height: 120px; - border: 0; - margin-top: 0; - background: var(--surface); -} - -.slide-schedule-dialog-head { - display: flex; - justify-content: space-between; - gap: 12px; - align-items: center; -} - -.slide-schedule-dialog button { - width: auto; - margin: 0; -.theme-toggle--floating .theme-toggle__label { - display: none; -} -.theme-toggle--floating .theme-toggle__icon { - width: 18px; - height: 18px; -} -} - -.slide-schedule-dialog button.secondary { - box-shadow: none; -} - -.slide-schedule-dialog button.secondary:hover { - filter: brightness(0.92); -} - -.slide-schedule-dialog form { - display: grid; - gap: 16px; -} - -.slide-schedule-dialog .card { - display: grid; - gap: 12px; -} - -.schedule-type-field { - display: block; - margin-bottom: 20px; -} - -.schedule-day-option { - margin-top: 0; - justify-content: flex-start; - width: 100%; - gap: 14px; -} - -.schedule-day-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); - gap: 8px; - margin-top: 16px; -} - -.schedule-day-label { - font-size: 13px; - font-weight: 700; - color: var(--text); - line-height: 1.1; -} - -.schedule-day-option .switch-ui { - flex: none; -} - -.schedule-day-option input:focus-visible + .switch-ui { - outline: 3px solid var(--focus-ring); - outline-offset: 2px; -} - -.schedule-day-option input:checked + .switch-ui { - background: linear-gradient(180deg, var(--primary), var(--primary-dark)); - border-color: rgba(37, 99, 235, 0.55); - box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.08), 0 0 0 4px rgba(37, 99, 235, 0.12); -} - -.schedule-save-actions { - margin-top: 16px; -} - -.schedule-save-actions button { - margin-top: 0; -} - -.slide-preview-placeholder { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - color: #cbd5e1; - font-size: 12px; -} - -.slide-preview-table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - background: none; -} - -.slide-preview-table tbody tr { - background: none; - border: 0; -} - -.slide-preview-table th, -.slide-preview-table td { - border: 1px solid rgba(255, 255, 255, 0.35); - padding: 6px 8px; - text-align: left; - vertical-align: top; -} - -.slide-preview-table th { - font-weight: 700; -} - -.ckeditor-holder { - min-height: 360px; - background: var(--editor-paper); - color: var(--editor-text); - margin-top: 8px; -} - -html[data-theme='dark'] .ckeditor-holder { - color-scheme: dark; - --editor-paper: #111b2d; - --editor-text: #e6eefb; - --ck-color-base-foreground: #111b2d; - --ck-color-base-background: #111b2d; - --ck-color-base-border: rgba(148, 163, 184, 0.22); - --ck-color-base-text: #e6eefb; - --ck-color-text: #e6eefb; - --ck-color-base-active: #60a5fa; - --ck-color-base-active-focus: #93c5fd; - --ck-color-base-focus: #60a5fa; - --ck-color-focus-border: rgba(96, 165, 250, 0.92); - --ck-color-focus-outer-shadow: rgba(96, 165, 250, 0.28); - --ck-color-toolbar-background: #111b2d; - --ck-color-toolbar-border: rgba(148, 163, 184, 0.2); - --ck-color-dropdown-panel-background: #111b2d; - --ck-color-dropdown-panel-border: rgba(148, 163, 184, 0.22); - --ck-color-panel-background: #111b2d; - --ck-color-panel-border: rgba(148, 163, 184, 0.22); - --ck-color-dialog-background: #111b2d; - --ck-color-dialog-form-header-border: rgba(148, 163, 184, 0.18); - --ck-color-input-background: #0e1728; - --ck-color-input-border: rgba(148, 163, 184, 0.22); - --ck-color-input-text: #e6eefb; - --ck-color-list-background: #111b2d; - --ck-color-list-button-hover-background: #162235; - --ck-color-list-button-on-background: #1b2a41; - --ck-color-list-button-on-background-focus: #22324a; - --ck-color-list-button-on-text: #e6eefb; - --ck-color-button-default-hover-background: #162235; - --ck-color-button-default-active-background: #1b2a41; - --ck-color-button-on-background: #1b2a41; - --ck-color-button-on-hover-background: #22324a; - --ck-color-button-on-active-background: #22324a; - --ck-color-button-on-color: #93c5fd; - --ck-color-button-on-disabled-background: #162235; - --ck-color-button-action-background: #2563eb; - --ck-color-button-action-hover-background: #1d4ed8; - --ck-color-button-action-active-background: #1d4ed8; - --ck-color-button-action-disabled-background: #3b82f6; - --ck-color-button-action-text: #ffffff; - --ck-color-switch-button-off-background: #475569; - --ck-color-switch-button-off-hover-background: #64748b; - --ck-color-switch-button-inner-background: #111b2d; - --ck-color-switch-button-inner-shadow: rgba(2, 6, 23, 0.45); - --ck-color-engine-placeholder-text: #94a3b8; - --ck-powered-by-background: #111b2d; - --ck-powered-by-text-color: #cbd5e1; - --ck-evaluation-badge-background: #111b2d; - --ck-evaluation-badge-text-color: #cbd5e1; -} - -.ckeditor-holder .ckeditor-source { - display: none; -} - -.ckeditor-holder .ck-editor, -.ckeditor-holder .ck-editor__main, -.ckeditor-holder .ck-editor__editable, -.ckeditor-holder .ck-content, -.ckeditor-holder .ck-editor__editable * { - color: var(--editor-text); -} - -.ckeditor-holder .ck button, -.ckeditor-holder .ck button:hover, -.ckeditor-holder .ck button:active, -.ckeditor-holder .ck button:focus, -.ckeditor-holder .ck button:focus-visible { - - box-shadow: none; -} - -.ckeditor-holder .ck-font-size-input, -.ckeditor-holder .ck-font-size-input.ck-input-text, -.ckeditor-holder .ck-font-size-input.ck-input-number, -.ckeditor-holder .ck-font-size-input .ck-input__field, -.ckeditor-holder .ck-font-size-input input { - width: 72px !important; - min-width: 72px !important; - max-width: 72px !important; - flex: 0 0 72px !important; - box-sizing: border-box; -} - -.ckeditor-holder .ck-font-size-input, -.ckeditor-holder .ck-font-size-input .ck-input__field, -.ckeditor-holder .ck-font-size-input input { - text-align: center; -} - -.ckeditor-holder .ck-font-size-input input::-webkit-outer-spin-button, -.ckeditor-holder .ck-font-size-input input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.ckeditor-holder .ck-font-size-input input[type='number'] { - appearance: textfield; - -moz-appearance: textfield; -} - -.ckeditor-holder .ck-content { - font-family: Arial, Helvetica, sans-serif; - font-size: 16px; - line-height: 1.5; - letter-spacing: normal; - text-transform: none; -} - -.ckeditor-holder .ck-editor__editable { - caret-color: var(--editor-text); -} - -.ckeditor-holder .ck-editor__editable.ck-focused { - border-color: var(--primary); - box-shadow: none; -} - -.ckeditor-holder .ck-editor__editable:not(.ck-editor__nested-editable) { - min-height: 360px; -} - -.ckeditor-holder .ck-placeholder:before { - color: rgba(0, 0, 0, 0.45); -} - -@media (max-width: 1100px) { - .slide-editor-top { - grid-template-columns: 1fr; - } -} - -/* Template designer pages. */ -.template-designer-layout { - display: grid; - grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); - gap: 12px; - align-items: start; -} - -.template-designer-main { - display: grid; - gap: 8px; -} - -.template-meta-row { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); - gap: 12px; - align-items: stretch; -} - -.template-meta-row > label { - display: flex; - flex-direction: column; - gap: 8px; - margin-top: 0; -} - -.template-background-row { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - gap: 8px; - align-items: center; -} - -.template-background-row input[type="file"] { - flex: 1 1 auto; - min-width: 0; -} - -.template-background-row button { - flex: 0 0 auto; - white-space: nowrap; -} - -.template-designer-sidebar { - display: grid; - gap: 8px; -} - -.template-designer-actions { - display: flex; - flex-wrap: nowrap; - gap: 8px; - margin: 0 0 8px 0; -} - -#template-form .template-designer-actions button { - flex: 1 1 0; - width: auto; - margin-top: 0; -} - -.region-select { - width: 100%; - margin-bottom: 8px; -} - -#canvas-size-select:disabled { - opacity: 0.55; - cursor: not-allowed; -} - -#canvas-size-summary.is-locked { - color: #94a3b8; -} - -.designer-stage { - position: relative; - width: 100%; - background: #0f172a; - border-radius: 0; - overflow: hidden; - border: 1px solid #1f2937; - cursor: crosshair; - user-select: none; - box-sizing: border-box; -} - -.designer-stage img { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: fill; - pointer-events: none; -} - -.designer-stage .empty-bg { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - color: #94a3b8; - font-size: 14px; - pointer-events: none; -} - -.designer-overlay { - position: absolute; - inset: 0; -} - -.designer-rect { - position: absolute; - border: 2px solid #22c55e; - background: rgba(34, 197, 94, 0.14); - color: #fff; - font-size: 12px; - overflow: hidden; - box-sizing: border-box; -} - -.designer-rect.selected { - border-color: #f59e0b; - background: rgba(245, 158, 11, 0.18); -} - -.designer-rect-label { - position: absolute; - left: 12px; - top: 0; - padding: 2px 6px; - background: rgba(15, 23, 42, 0.8); - font-size: 11px; - pointer-events: none; -} - -.designer-rect .resize-handle { - position: absolute; - width: 24px; - height: 24px; - background: var(--surface); - border: 1px solid var(--border-strong); - box-sizing: border-box; -} - -.designer-rect .resize-handle.nw { - left: -13px; - top: -13px; - cursor: nwse-resize; -} - -.designer-rect .resize-handle.ne { - right: -13px; - top: -13px; - cursor: nesw-resize; -} - -.designer-rect .resize-handle.sw { - left: -13px; - bottom: -13px; - cursor: nesw-resize; -} - -.designer-rect .resize-handle.se { - right: -13px; - bottom: -13px; - cursor: nwse-resize; -} - -.designer-draft { - border-style: dashed; - background: rgba(59, 130, 246, 0.12); - border-color: #60a5fa; -} - -.region-list { - display: grid; - gap: 8px; -} - -#template-form { - display: grid; -} - -#template-form label { - margin-top: 8px; -} - -#template-form input, -#template-form textarea, -#template-form select, -#template-form button { - margin-top: 4px; -} - -#template-form .card { - padding: 12px; -} - -.template-field-card + .template-field-card { - margin-top: 12px; -} - -.template-designer-sidebar .row.template-designer-actions { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 8px; -} - -.template-save-button { - margin-bottom: 0; -} - -@media (max-width: 720px) { - .template-designer-sidebar .row.template-designer-actions { - grid-template-columns: 1fr; - } -} - -.image-filename { - display: block; - margin-top: 8px; -} - -.region-item { - background: var(--surface); - border: 1px solid var(--border); - border-radius: 12px; - padding: 8px; - display: grid; - gap: 8px; -} - -.region-item.selected { - border-color: #f59e0b; - box-shadow: 0 0 0 1px #f59e0b inset; -} - -.region-item .row { - align-items: end; - gap: 6px; -} - -.region-item[hidden] { - display: none !important; -} - diff --git a/src/web/public/css/theme-custom.css b/src/web/public/css/theme-custom.css new file mode 100644 index 0000000..b695e6c --- /dev/null +++ b/src/web/public/css/theme-custom.css @@ -0,0 +1,1251 @@ +.status-dot { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 0.75rem; + height: 0.75rem; + border-radius: 999px; + flex: 0 0 auto; +} + +.status-dot::after { + content: ''; + position: absolute; + inset: -0.28rem; + border-radius: inherit; + opacity: 0; + transform: scale(0.7); +} + +.status-dot--online { + background: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.2); +} + +.status-dot--online::after { + background: rgba(40, 167, 69, 0.32); + animation: status-dot-pulse 1.8s ease-out infinite; +} + +.status-dot--offline { + background: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.2); +} + +.status-dot--unknown { + background: #adb5bd; + box-shadow: 0 0 0 0.2rem rgba(173, 181, 189, 0.18); +} + +.status-dot--unknown::after { + background: rgba(173, 181, 189, 0.26); + animation: status-dot-pulse 1.8s ease-out infinite; +} + +@keyframes status-dot-pulse { + 0% { + opacity: 0.55; + transform: scale(0.7); + } + + 70% { + opacity: 0; + transform: scale(1.75); + } + + 100% { + opacity: 0; + transform: scale(1.75); + } +} + +.user-menu-avatar { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.75rem; + height: 1.75rem; + border-radius: 999px; + background: linear-gradient(135deg, #0d6efd, #6610f2); + color: #fff; + font-size: 0.875rem; + font-weight: 700; + flex: 0 0 auto; +} + +.user-menu-avatar--lg { + width: 3rem; + height: 3rem; + font-size: 1rem; +} + +.user-menu-name { + line-height: 1; +} + +.user-menu-dropdown .user-header { + padding: 1rem; + text-align: center; +} + +.user-menu-dropdown .user-body { + padding: 0.75rem 1rem; +} + +.user-menu-dropdown .user-body a { + color: inherit; + text-decoration: none; +} + +.user-menu-dropdown .user-header p { + margin: 0.75rem 0 0; + line-height: 1.2; +} + +.user-menu-dropdown .user-header small { + display: block; + margin-top: 0.25rem; + opacity: 0.85; +} + +.user-menu-dropdown .user-footer { + display: flex; + gap: 0.5rem; + padding: 0.75rem 1rem 1rem; +} + +.user-menu-dropdown .user-footer .btn { + flex: 1 1 0; +} + +.app-header .navbar-nav { + --bs-navbar-nav-link-padding-x: 10px; +} + +.sidebar-brand .brand-text.fw-light { + margin: 0; +} + +.card { + box-shadow: none; +} + +.admin-form-card { + box-shadow: none; +} + +.admin-form-card .card-header { + background: var(--bs-tertiary-bg); +} + +.dashboard-hero { + overflow: hidden; + background: linear-gradient(135deg, rgba(13, 110, 253, 0.08), rgba(32, 201, 151, 0.08)); +} + +.dashboard-hero-body { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1.5rem; +} + +.dashboard-hero-kicker { + display: inline-flex; + align-items: center; + padding: 0.3rem 0.65rem; + border-radius: 999px; + background: var(--bs-body-bg); + color: var(--bs-primary); + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.dashboard-hero-title { + margin: 0.75rem 0 0; + font-size: clamp(1.4rem, 1.1rem + 1vw, 2.2rem); + line-height: 1.08; + max-width: 28rem; +} + +.dashboard-hero-copy { + margin: 0.75rem 0 0; + max-width: 42rem; + color: var(--bs-secondary-color); +} + +.dashboard-hero-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.75rem; + min-width: min(100%, 22rem); +} + +.dashboard-hero-stat { + display: grid; + gap: 0.15rem; + min-width: 0; + padding: 0.85rem 1rem; + border-radius: 1rem; + background: var(--bs-body-bg); +} + +.dashboard-hero-stat-value { + font-size: 1.5rem; + font-weight: 700; + line-height: 1; +} + +.dashboard-hero-stat-label { + color: var(--bs-secondary-color); + font-size: 0.8rem; + line-height: 1.2; +} + +.dashboard-actions-card .card-header, +.dashboard-table-card .card-header { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.dashboard-card-heading { + display: grid; + gap: 0.2rem; +} + +.dashboard-card-heading .card-title { + float: none; + margin: 0; +} + +.dashboard-card-subtitle { + margin: 0; + color: var(--bs-secondary-color); + font-size: 0.875rem; +} + +.dashboard-action-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem; +} + +.dashboard-action-form { + display: grid; + gap: 0.5rem; + margin: 0; +} + +.dashboard-action-button { + justify-content: center; +} + +.dashboard-action-help { + color: var(--bs-secondary-color); + font-size: 0.875rem; +} + +.page-header { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 1rem; + padding: 0 0 0.5rem; +} + +.page-header h2 { + margin: 0; + font-size: clamp(1.45rem, 1.2rem + 0.6vw, 2rem); + line-height: 1.1; +} + +.page-header p { + margin: 0.35rem 0 0; + color: var(--bs-secondary-color); +} + +.page-header > div { + min-width: 0; +} + +.card.card-outline > .card-header { + align-items: center; + min-height: 3.25rem; +} + +.card-body.table-responsive { + border-bottom-left-radius: calc(var(--bs-border-radius) - 1px); + border-bottom-right-radius: calc(var(--bs-border-radius) - 1px); +} + +.card-body.table-responsive > table.table > thead th { + position: sticky; + top: 0; + z-index: 1; + background: var(--bs-body-bg); + box-shadow: inset 0 -1px 0 var(--bs-border-color); +} + +.card-body.table-responsive > table.table > tbody > tr:last-child > * { + border-bottom-width: 0; +} + +.chip { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.25rem 0.625rem; + border-radius: 999px; + background: var(--bs-secondary-bg); + color: var(--bs-secondary-color); + font-size: 0.875rem; + line-height: 1.2; + white-space: nowrap; +} + +.empty { + color: var(--bs-secondary-color); + font-style: italic; +} + +.subtle { + color: var(--bs-secondary-color); +} + +.connection-count, +td[data-label="Name"], +td[data-label="Title"], +td[data-label="Client"], +td[data-label="Current Screen"], +td[data-label="Current Slide"], +td[data-label="IP"], +td[data-label="Viewport"], +td[data-label="Connected/Updated"], +td[data-label="Template"], +td[data-label="Slides"] { + overflow-wrap: anywhere; +} + +.slide-editor-shell { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(18rem, 24rem); + gap: 1rem; + align-items: start; + position: relative; +} + +.slide-form-stack { + display: grid; + gap: 1rem; + min-width: 0; +} + +.slide-editor-shell .slide-preview-card { + width: 100%; + max-width: 24rem; + justify-self: end; +} + +.slide-editor-shell .slide-preview-card .card-body { + padding: 0.875rem; +} + +.slide-editor-shell .slide-preview-scroll { + max-height: calc(100vh - 8rem); + overflow: auto; +} + +.slide-preview-header h3 { + margin: 0; +} + +.slide-preview-header .muted { + margin-top: 0.25rem; +} + +.slide-form-stack .ck.ck-editor, +.template-field-card .ck.ck-editor { + --ck-custom-background: var(--bs-body-bg); + --ck-custom-foreground: var(--bs-body-color); + --ck-custom-border: var(--bs-border-color); + --ck-color-base-foreground: var(--bs-tertiary-bg); + --ck-color-base-background: var(--bs-body-bg); + --ck-color-base-border: var(--bs-border-color); + --ck-color-base-text: var(--bs-body-color); + --ck-color-base-action: var(--bs-primary); + --ck-color-base-focus: var(--bs-primary); + --ck-color-base-active: var(--bs-primary); + --ck-color-base-active-focus: var(--bs-primary); + --ck-color-base-error: var(--bs-danger); + --ck-color-focus-border: rgba(var(--bs-primary-rgb), 1); + --ck-color-focus-outer-shadow: rgba(var(--bs-primary-rgb), 0.18); + --ck-color-focus-disabled-shadow: rgba(var(--bs-secondary-rgb), 0.14); + --ck-color-focus-error-shadow: rgba(var(--bs-danger-rgb), 0.18); + --ck-color-shadow-drop: rgba(0, 0, 0, 0.16); + --ck-color-shadow-drop-active: rgba(0, 0, 0, 0.22); + --ck-color-shadow-inner: rgba(0, 0, 0, 0.08); + --ck-color-button-default-background: transparent; + --ck-color-button-default-hover-background: var(--bs-secondary-bg); + --ck-color-button-default-active-background: var(--bs-secondary-bg); + --ck-color-button-default-disabled-background: transparent; + --ck-color-button-on-background: rgba(var(--bs-primary-rgb), 0.12); + --ck-color-button-on-hover-background: rgba(var(--bs-primary-rgb), 0.16); + --ck-color-button-on-active-background: rgba(var(--bs-primary-rgb), 0.16); + --ck-color-button-on-disabled-background: var(--bs-secondary-bg); + --ck-color-button-on-color: var(--bs-primary); + --ck-color-button-action-background: var(--bs-primary); + --ck-color-button-action-hover-background: var(--bs-primary); + --ck-color-button-action-active-background: var(--bs-primary); + --ck-color-button-action-disabled-background: var(--bs-primary); + --ck-color-button-action-text: var(--bs-body-bg); + --ck-color-switch-button-off-background: var(--bs-secondary-color); + --ck-color-switch-button-off-hover-background: var(--bs-secondary-color); + --ck-color-switch-button-on-background: var(--bs-primary); + --ck-color-switch-button-on-hover-background: var(--bs-primary); + --ck-color-switch-button-inner-background: var(--bs-body-bg); + --ck-color-switch-button-inner-shadow: rgba(0, 0, 0, 0.08); + --ck-color-dropdown-panel-background: var(--bs-body-bg); + --ck-color-dropdown-panel-border: var(--bs-border-color); + --ck-color-dialog-background: var(--bs-body-bg); + --ck-color-dialog-form-header-border: var(--bs-border-color); + --ck-color-list-button-on-background: rgba(var(--bs-primary-rgb), 0.12); + --ck-color-list-button-on-text: var(--bs-primary); + --ck-color-input-background: var(--bs-body-bg); + --ck-color-input-border: var(--bs-border-color); + --ck-color-input-text: var(--bs-body-color); + --ck-color-input-disabled-background: var(--bs-secondary-bg); + --ck-color-input-disabled-border: var(--bs-border-color); + --ck-color-input-disabled-text: var(--bs-secondary-color); + --ck-color-toolbar-background: var(--bs-tertiary-bg); + --ck-color-toolbar-border: var(--bs-border-color); + --ck-color-toolbar-box-shadow: none; + --ck-color-image-caption-background: var(--bs-secondary-bg); + --ck-color-image-caption-text: var(--bs-secondary-color); + --ck-color-resizer: var(--bs-primary); + --ck-color-resizer-tooltip-background: var(--bs-dark); + --ck-color-resizer-tooltip-text: var(--bs-light); + border-radius: var(--bs-border-radius); + overflow: hidden; + background: var(--bs-body-bg); + border: 1px solid var(--bs-border-color); +} + +.slide-form-stack .ck.ck-editor__top .ck-sticky-panel__content, +.template-field-card .ck.ck-editor__top .ck-sticky-panel__content { + border-bottom: 1px solid var(--bs-border-color); +} + +.slide-form-stack .ck.ck-toolbar, +.template-field-card .ck.ck-toolbar { + background: var(--bs-tertiary-bg); + border: 0; + border-radius: 0; +} + +.slide-form-stack .ck.ck-toolbar .ck-toolbar__items, +.template-field-card .ck.ck-toolbar .ck-toolbar__items { + gap: 0.15rem; +} + +.slide-form-stack .ck.ck-toolbar .ck-button, +.slide-form-stack .ck.ck-toolbar .ck-dropdown__button, +.slide-form-stack .ck.ck-toolbar .ck-splitbutton__action, +.template-field-card .ck.ck-toolbar .ck-button, +.template-field-card .ck.ck-toolbar .ck-dropdown__button, +.template-field-card .ck.ck-toolbar .ck-splitbutton__action { + border-radius: 0.5rem; + color: var(--bs-body-color); +} + +.slide-form-stack .ck.ck-toolbar .ck-button:hover, +.slide-form-stack .ck.ck-toolbar .ck-dropdown__button:hover, +.slide-form-stack .ck.ck-toolbar .ck-splitbutton__action:hover, +.template-field-card .ck.ck-toolbar .ck-button:hover, +.template-field-card .ck.ck-toolbar .ck-dropdown__button:hover, +.template-field-card .ck.ck-toolbar .ck-splitbutton__action:hover { + background: var(--bs-secondary-bg); +} + +.slide-form-stack .ck.ck-toolbar .ck-button.ck-on, +.slide-form-stack .ck.ck-toolbar .ck-dropdown__button.ck-on, +.slide-form-stack .ck.ck-toolbar .ck-splitbutton__action.ck-on, +.template-field-card .ck.ck-toolbar .ck-button.ck-on, +.template-field-card .ck.ck-toolbar .ck-dropdown__button.ck-on, +.template-field-card .ck.ck-toolbar .ck-splitbutton__action.ck-on { + background: rgba(var(--bs-primary-rgb), 0.12); + color: var(--bs-primary); +} + +.slide-form-stack .ck.ck-toolbar .ck-button.ck-disabled, +.slide-form-stack .ck.ck-toolbar .ck-dropdown__button.ck-disabled, +.slide-form-stack .ck.ck-toolbar .ck-splitbutton__action.ck-disabled, +.template-field-card .ck.ck-toolbar .ck-button.ck-disabled, +.template-field-card .ck.ck-toolbar .ck-dropdown__button.ck-disabled, +.template-field-card .ck.ck-toolbar .ck-splitbutton__action.ck-disabled { + color: var(--bs-secondary-color); +} + +.slide-form-stack .ck.ck-dropdown__panel, +.slide-form-stack .ck.ck-list__panel, +.slide-form-stack .ck.ck-balloon-panel, +.template-field-card .ck.ck-dropdown__panel, +.template-field-card .ck.ck-list__panel, +.template-field-card .ck.ck-balloon-panel { + border-color: var(--bs-border-color); + box-shadow: var(--bs-box-shadow); +} + +.slide-form-stack .ck.ck-list__item .ck-button, +.template-field-card .ck.ck-list__item .ck-button { + color: var(--bs-body-color); +} + +.slide-form-stack .ck.ck-list__item .ck-button:hover, +.template-field-card .ck.ck-list__item .ck-button:hover { + background: var(--bs-secondary-bg); +} + +.slide-form-stack .ck.ck-dropdown__panel, +.slide-form-stack .ck.ck-list__panel, +.slide-form-stack .ck.ck-balloon-panel, +.slide-form-stack .ck.ck-toolbar .ck-dropdown__panel, +.template-field-card .ck.ck-dropdown__panel, +.template-field-card .ck.ck-list__panel, +.template-field-card .ck.ck-balloon-panel, +.template-field-card .ck.ck-toolbar .ck-dropdown__panel { + background: var(--bs-body-bg); +} + +.slide-form-stack .ck.ck-input-text, +.slide-form-stack .ck.ck-list__item-text, +.slide-form-stack .ck.ck-list__item-label, +.slide-form-stack .ck.ck-dropdown__panel .ck-button__label, +.template-field-card .ck.ck-input-text, +.template-field-card .ck.ck-list__item-text, +.template-field-card .ck.ck-list__item-label, +.template-field-card .ck.ck-dropdown__panel .ck-button__label { + color: var(--bs-body-color); +} + +.slide-form-stack .ck.ck-input-text, +.template-field-card .ck.ck-input-text { + background: var(--bs-body-bg); + border-color: var(--bs-border-color); +} + +.slide-form-stack .ck.ck-input-text:focus, +.template-field-card .ck.ck-input-text:focus { + border-color: var(--bs-primary); + box-shadow: 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.18); +} + +.slide-form-stack .ck.ck-editor__main > .ck-editor__editable, +.slide-form-stack .ck.ck-editor__editable_inline, +.template-field-card .ck.ck-editor__main > .ck-editor__editable, +.template-field-card .ck.ck-editor__editable_inline { + background: var(--bs-body-bg); + color: var(--bs-body-color); + border: 0; +} + +.slide-form-stack .ck.ck-editor__main > .ck-editor__editable.ck-focused, +.slide-form-stack .ck.ck-editor__editable_inline.ck-focused, +.template-field-card .ck.ck-editor__main > .ck-editor__editable.ck-focused, +.template-field-card .ck.ck-editor__editable_inline.ck-focused { + box-shadow: inset 0 0 0 1px var(--bs-primary), 0 0 0 0.2rem rgba(var(--bs-primary-rgb), 0.18); +} + +.slide-form-stack .ck-content, +.template-field-card .ck-content { + font-family: inherit; + font-size: 1rem; + line-height: 1.55; +} + +.slide-form-stack .ck-content h1, +.slide-form-stack .ck-content h2, +.slide-form-stack .ck-content h3, +.slide-form-stack .ck-content h4, +.slide-form-stack .ck-content h5, +.slide-form-stack .ck-content h6, +.template-field-card .ck-content h1, +.template-field-card .ck-content h2, +.template-field-card .ck-content h3, +.template-field-card .ck-content h4, +.template-field-card .ck-content h5, +.template-field-card .ck-content h6 { + color: var(--bs-body-color); +} + +.slide-form-stack .ck-content p, +.template-field-card .ck-content p { + margin-bottom: 0.75rem; +} + + +.slide-preview-dimensions-chip { + display: inline-flex; + align-items: center; + margin-left: auto; + flex-shrink: 0; + padding: 0.2rem 0.5rem; + border-radius: 999px; + background: var(--bs-secondary-bg); + color: var(--bs-secondary-color); + font-size: 0.75rem; + line-height: 1.2; +} + +.slide-preview-stage { + position: relative; + width: 100%; + overflow: hidden; + border-radius: 0; + background: #111; +} + +.slide-preview-canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: block; + transform-origin: top left; + will-change: transform; +} + +.slide-preview-background, +.slide-preview-overlay, +.slide-preview-empty { + position: absolute; + inset: 0; +} + +.slide-preview-region { + position: absolute; + overflow: hidden; + box-sizing: border-box; +} + +.slide-preview-image { + width: 100%; + height: 100%; + object-fit: contain; + display: block; +} + +.slide-preview-background { + width: 100%; + height: 100%; + object-fit: contain; +} + +.slide-preview-empty { + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + color: rgba(255, 255, 255, 0.75); + text-align: center; + background: linear-gradient(135deg, rgba(13, 110, 253, 0.15), rgba(255, 255, 255, 0.04)); +} + +.slide-preview-overlay { + z-index: 2; +} + +.slide-preview-background { + z-index: 1; +} + +.slide-preview-empty { + z-index: 0; +} + +.template-designer-layout { + display: grid; + grid-template-columns: minmax(0, 1fr) 20rem; + gap: 1rem; + align-items: start; +} + +.template-designer-main, +.template-designer-sidebar { + min-width: 0; +} + +.designer-stage { + position: relative; + width: 100%; + min-height: 18rem; + overflow: hidden; + border: 1px solid var(--bs-border-color); + border-radius: 0; + background: var(--bs-body-bg); +} + +.designer-stage > img, +.designer-stage > .empty-bg, +.designer-stage > .designer-overlay { + position: absolute; + inset: 0; +} + +.designer-stage > img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.designer-stage > .empty-bg { + display: flex; + align-items: center; + justify-content: center; + color: var(--bs-secondary-color); + background: linear-gradient(135deg, rgba(13, 110, 253, 0.08), rgba(108, 117, 125, 0.05)); +} + +.designer-overlay { + z-index: 2; + cursor: crosshair; +} + +.designer-rect { + position: absolute; + border: 2px solid rgba(13, 110, 253, 0.95); + background: rgba(13, 110, 253, 0.12); + box-sizing: border-box; + border-radius: 0.35rem; + min-width: 12px; + min-height: 12px; +} + +.designer-rect.selected { + border-color: rgba(25, 135, 84, 1); + background: rgba(25, 135, 84, 0.14); +} + +.designer-rect-label { + position: absolute; + left: 0; + top: -1.55rem; + max-width: 100%; + padding: 0.15rem 0.45rem; + border-radius: 999px; + background: rgba(33, 37, 41, 0.88); + color: #fff; + font-size: 0.75rem; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.designer-rect.selected .designer-rect-label { + background: rgba(25, 135, 84, 0.95); +} + +.resize-handle { + position: absolute; + width: 0.8rem; + height: 0.8rem; + border-radius: 999px; + border: 2px solid #fff; + background: rgba(13, 110, 253, 1); + box-shadow: 0 0 0 1px rgba(13, 110, 253, 0.35); +} + +.resize-handle.nw { + left: -0.4rem; + top: -0.4rem; + cursor: nwse-resize; +} + +.resize-handle.ne { + right: -0.4rem; + top: -0.4rem; + cursor: nesw-resize; +} + +.resize-handle.sw { + left: -0.4rem; + bottom: -0.4rem; + cursor: nesw-resize; +} + +.resize-handle.se { + right: -0.4rem; + bottom: -0.4rem; + cursor: nwse-resize; +} + +.designer-draft { + border-style: dashed; + background: rgba(13, 110, 253, 0.08); +} + +.template-designer-sidebar { + position: sticky; + top: 1rem; + display: grid; + gap: 1rem; +} + +.template-designer-sidebar .card-body.d-grid { + padding: 1rem; +} + +.template-designer-sidebar .btn-group { + width: 100%; +} + +.template-actions-group { + display: grid; + grid-auto-flow: column; + grid-auto-columns: minmax(0, 1fr); + gap: 0; + width: 100%; +} + +.template-actions-group > * { + width: 100%; +} + +.template-actions-group > .btn-warning, +.template-actions-group > .btn-danger, +.playlist-actions-group > .btn-warning, +.playlist-actions-group > .btn-danger, +.screen-actions-group > .btn-warning, +.screen-actions-group > .btn-danger { + flex: 1 1 0; +} + +.template-actions-group > .btn-warning, +.template-actions-group > .btn-danger, +.playlist-actions-group > .btn-warning, +.playlist-actions-group > .btn-danger, +.screen-actions-group > .btn-warning, +.screen-actions-group > .btn-danger { + text-align: center; +} + +.save-action-group > .dropdown-toggle-split { + flex: 0 0 2.35rem; + width: 2.35rem; + min-width: 2.35rem; + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.save-action-group > .dropdown-toggle-split::after { + margin-left: 0; +} + +.slide-actions-group .save-action-group > .dropdown-toggle-split { + flex-basis: 3rem; + width: 3rem; + min-width: 3rem; +} + +.template-designer-actions { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.template-designer-actions .btn { + width: 100%; +} + +.region-info-card .card-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 1rem; +} + +.region-info-card .card-title { + margin-bottom: 0.15rem; +} + +.region-info-card .card-subtitle { + margin-bottom: 0; +} + +.region-selector-block .form-label { + font-weight: 600; +} + +.region-list { + display: grid; + gap: 0.75rem; +} + +.region-item { + overflow: hidden; +} + +.region-item label { + display: grid; + gap: 0.35rem; + font-size: 0.875rem; + font-weight: 600; + color: var(--bs-body-color); +} + +.region-item input, +.region-item select { + width: 100%; +} + +.region-field-grid { + display: grid; + width: 100%; + gap: 0.75rem; +} + +.region-field-grid--identity { + grid-template-columns: minmax(0, 1fr); +} + +.region-field-grid--position { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.region-field-grid--size { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.region-field-grid > label { + display: grid; + gap: 0.35rem; + min-width: 0; +} + +.region-field-grid > label > .form-control, +.region-field-grid > label > .form-select { + min-width: 0; +} + +.template-field-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + min-height: 3.25rem; +} + +.template-field-actions { + display: inline-flex; + align-items: center; + gap: 0.5rem; + margin-left: auto; +} + +.template-field-head strong { + font-size: 0.95rem; +} + +.template-field-head .chip { + display: inline-flex; + align-items: center; + margin-left: auto; + flex-shrink: 0; + padding: 0.2rem 0.5rem; + border-radius: 999px; + background: var(--bs-secondary-bg); + color: var(--bs-secondary-color); + font-size: 0.75rem; + line-height: 1.2; +} + +.template-field-card { + overflow: hidden; +} + +.template-field-card .card-header, +.region-item .card-header { + background: var(--bs-tertiary-bg); + border-bottom: 1px solid var(--bs-border-color-translucent); +} + +.template-field-card .card-body, +.region-item .card-body { + background: var(--bs-body-bg); +} + +.template-field-card label, +.region-item label { + margin-bottom: 0; +} + +.template-field-card .form-control, +.template-field-card .form-select, +.template-field-card textarea, +.template-field-card input[type='file'], +.region-item .form-control, +.region-item .form-select, +.region-item input[type='number'], +.region-item input[type='text'] { + width: 100%; +} + +.template-field-card .ckeditor-holder { + min-width: 0; +} + +.template-field-card .ck-editor__editable_inline { + min-height: 18rem; +} + +.template-field-card.is-expanded .ck-editor__editable_inline { + min-height: 32rem; +} + +.template-field-card.is-expanded .card-body { + min-height: 36rem; +} + +.template-field-card .slide-image-file, +.region-item .slide-image-file { + margin: 0; +} + +.region-item .remove-region { + justify-self: end; +} + +.region-item .form-control:focus, +.region-item .form-select:focus, +.region-item input[type='number']:focus, +.region-item input[type='text']:focus { + border-color: var(--bs-primary); + box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15); +} + +@media (max-width: 575.98px) { + .region-info-card .card-header { + align-items: stretch; + flex-direction: column; + } + + .region-field-grid--identity, + .region-field-grid--position, + .region-field-grid--size { + grid-template-columns: 1fr; + } +} + +@media (max-width: 1199.98px) { + .template-designer-layout { + grid-template-columns: minmax(0, 1fr); + } + + .template-designer-sidebar, + .slide-editor-shell, + .slide-editor-shell .slide-preview-card { + position: static; + } + + .slide-editor-shell { + grid-template-columns: minmax(0, 1fr); + } + + .slide-editor-shell .slide-preview-card { + max-width: none; + justify-self: stretch; + } + + .template-designer-actions { + grid-template-columns: 1fr; + } +} + +.frame-popup-card-body { + margin: 0; + padding: 0; +} + +.frame-popup-card-body .slide-schedule-card { + width: min(100%, 40rem); + margin: 0 auto; +} + +.toast-container { + z-index: 1085; +} + +.is-hidden { + display: none !important; +} + +.playlist-add-slide-form { + display: flex; +} + +.playlist-add-slide-form.is-hidden, +.playlist-add-slide-empty.is-hidden, +.schedule-panel.is-hidden { + display: none !important; +} + +.schedule-day-grid .schedule-day-button { + flex: 1 1 0; +} + +.slide-schedule-dialog { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border: 0; + padding: 0; + background: transparent; + max-width: none; + overflow: hidden; + width: min(calc(100vw - 1rem), 42rem); + max-height: calc(100vh - 1rem); + height: auto; + margin: 0; +} + +.slide-schedule-dialog::backdrop { + background: rgba(0, 0, 0, 0.35); +} + +.slide-schedule-content { + width: 100%; +} + +.actions, +.playlist-item-actions, +.users-row-actions { + display: flex; + flex-wrap: nowrap; + align-items: center; + gap: 0.5rem; + white-space: nowrap; +} + +td[data-label="Actions"] { + text-align: right; +} + +td[data-label="Actions"] > div { + justify-content: flex-end; +} + +.actions .inline-form, +.playlist-item-actions .inline-form, +.users-row-actions .inline-form { + margin: 0; + flex: 0 0 auto; +} + +table.table > :not(caption) > * > * { + vertical-align: middle; +} + +.playlist-order-cell { + width: 1%; + white-space: nowrap; + padding-bottom: 0 !important; +} + +.playlist-order-cell-inner { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.playlist-drag-handle { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.35rem; + height: 1.9rem; + line-height: 1; + cursor: grab; + text-decoration: none; +} + +.playlist-drag-handle-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.1rem; + height: 1.9rem; +} + +.playlist-drag-handle-svg { + display: block; + width: 100%; + height: 100%; + fill: currentColor; +} + +.playlist-drag-handle:active, +.playlist-drag-handle:hover, +.playlist-drag-handle:focus { + text-decoration: none; +} + +.playlist-drag-handle:active { + cursor: grabbing; +} + +table.table thead th.sortable { + cursor: pointer; + white-space: nowrap; +} + +table.table thead th.sortable .table-sort-indicator { + font-size: 0.8em; + opacity: 0.55; +} + +table.table thead th.sort-asc .table-sort-indicator, +table.table thead th.sort-desc .table-sort-indicator { + opacity: 1; +} + +.navbar-nav>.user-menu>.dropdown-menu>li.user-header { + min-height: 100px; +} + +@media (max-width: 767.98px) { + .dashboard-hero-body { + flex-direction: column; + align-items: stretch; + } + + .dashboard-hero-stats { + grid-template-columns: 1fr; + min-width: 0; + } + + .dashboard-action-grid { + grid-template-columns: 1fr; + } + + .dashboard-hero-body { + flex-direction: column; + align-items: stretch; + } + + .dashboard-hero-stats { + grid-template-columns: 1fr; + min-width: 0; + } + + .page-header { + align-items: flex-start; + flex-direction: column; + } + + .card-body.table-responsive > table.table > thead th { + position: static; + } +} \ No newline at end of file diff --git a/src/web/public/js/admin-page.js b/src/web/public/js/admin-page.js index 23a54a7..7ddbb58 100644 --- a/src/web/public/js/admin-page.js +++ b/src/web/public/js/admin-page.js @@ -31,299 +31,55 @@ return String(client && client.id ? client.id : client && client.clientId ? client.clientId : '').trim(); } - function renderClientActionCell(client) { - var paused = Boolean(client.paused); - var pauseButtonClass = 'button-link list-action' + (paused ? ' is-paused' : ''); - var pauseButtonLabel = paused ? 'Resume' : 'Pause'; - var blackout = Boolean(client.blackout); - var blackoutButtonClass = 'button-link list-action' + (blackout ? ' is-blackout' : ''); - var blackoutButtonLabel = blackout ? 'Restore' : 'Blackout'; - var reloadConfirmMessage = 'Reloading will restart the player page. Continue?'; - var blackoutCommandValue = blackout ? 'false' : 'true'; - - return '
    '; + function getClientDisplayName(client) { + if (client && client.client_name) { + return String(client.client_name).trim(); + } + var clientId = String(client && client.clientId ? client.clientId : '').trim(); + if (clientId) { + return clientId; + } + return ''; } - function updateClientActionCell(cell, client) { - if (!cell) { + function setButtonVariant(button, classesToRemove, classToAdd) { + if (!button) { return; } - var pauseButton = cell.querySelector('button[data-action="pause"]'); - if (!pauseButton) { - cell.innerHTML = renderClientActionCell(client); + if (button.classList) { + classesToRemove.forEach(function (className) { + button.classList.remove(className); + }); + if (classToAdd) { + button.classList.add(classToAdd); + } return; } - var paused = Boolean(client.paused); - pauseButton.className = 'button-link list-action' + (paused ? ' is-paused' : ''); - pauseButton.textContent = paused ? 'Resume' : 'Pause'; - - var pauseForm = pauseButton.form; - if (pauseForm) { - var commandInput = pauseForm.querySelector('input[name="command"]'); - if (commandInput) { - commandInput.value = 'pause'; - } - var connectionInput = pauseForm.querySelector('input[name="connectionId"]'); - if (connectionInput) { - connectionInput.value = client.id || ''; - } - pauseForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; - } - - var reloadButton = cell.querySelector('button[data-action="reload"]'); - if (reloadButton) { - reloadButton.textContent = 'Reload'; - reloadButton.className = 'button-link list-action is-danger'; - var reloadForm = reloadButton.form; - if (reloadForm) { - var reloadInput = reloadForm.querySelector('input[name="connectionId"]'); - if (reloadInput) { - reloadInput.value = client.id || ''; - } - reloadForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; - reloadForm.setAttribute('data-confirm-message', 'Reloading will restart the player page. Continue?'); - } - } - - var blackoutButton = cell.querySelector('button[data-action="blackout"]'); - if (!blackoutButton) { - cell.innerHTML = renderClientActionCell(client); - return; - } - - var blackout = Boolean(client.blackout); - blackoutButton.className = 'button-link list-action' + (blackout ? ' is-blackout' : ''); - blackoutButton.textContent = blackout ? 'Restore' : 'Blackout'; - - var blackoutForm = blackoutButton.form; - if (blackoutForm) { - var blackoutCommandInput = blackoutForm.querySelector('input[name="command"]'); - if (blackoutCommandInput) { - blackoutCommandInput.value = 'blackout'; - } - var blackoutStateInput = blackoutForm.querySelector('input[name="blackout"]'); - if (blackoutStateInput) { - blackoutStateInput.value = blackout ? 'false' : 'true'; - } - var blackoutConnectionInput = blackoutForm.querySelector('input[name="connectionId"]'); - if (blackoutConnectionInput) { - blackoutConnectionInput.value = client.id || ''; - } - blackoutForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; - } - - var previousButton = cell.querySelector('button[data-action="previous"]'); - if (!previousButton) { - cell.innerHTML = renderClientActionCell(client); - return; - } - previousButton.className = 'button-link list-action list-action--nav'; - previousButton.setAttribute('aria-label', 'Previous slide'); - var previousForm = previousButton.form; - if (previousForm) { - var previousCommandInput = previousForm.querySelector('input[name="command"]'); - if (previousCommandInput) { - previousCommandInput.value = 'previous'; - } - var previousConnectionInput = previousForm.querySelector('input[name="connectionId"]'); - if (previousConnectionInput) { - previousConnectionInput.value = client.id || ''; - } - previousForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; - } - - var nextButton = cell.querySelector('button[data-action="next"]'); - if (!nextButton) { - cell.innerHTML = renderClientActionCell(client); - return; - } - nextButton.className = 'button-link list-action list-action--nav'; - nextButton.setAttribute('aria-label', 'Next slide'); - var nextForm = nextButton.form; - if (nextForm) { - var nextCommandInput = nextForm.querySelector('input[name="command"]'); - if (nextCommandInput) { - nextCommandInput.value = 'next'; - } - var nextConnectionInput = nextForm.querySelector('input[name="connectionId"]'); - if (nextConnectionInput) { - nextConnectionInput.value = client.id || ''; - } - nextForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; - } - } - - function renderClientRow(client) { - var connectedAt = client.connectedAt ? '
    ' + escapeHtml(client.connectedAtLabel || formatDashboardDate(client.connectedAt) || client.connectedAt) + '
    ' + (client.lastSeenAt ? '
    ' + escapeHtml(client.lastSeenAtLabel || formatDashboardDate(client.lastSeenAt) || client.lastSeenAt) + '
    ' : '') : 'Unknown'; - var clientIp = client.clientIp ? escapeHtml(client.clientIp) : (client.remoteAddress ? escapeHtml(client.remoteAddress) : 'Unknown'); - var viewport = client.viewport && client.viewport.width && client.viewport.height ? escapeHtml(client.viewport.width + 'x' + client.viewport.height) : 'Unknown'; - var clientId = client.clientId ? escapeHtml(client.clientId) : 'Unknown'; - var connectionId = client.id ? escapeHtml(client.id) : 'Unknown'; - var currentSlide = client.currentSlideTitle ? escapeHtml(client.currentSlideTitle) : 'No slide currently showing'; - - return [ - '', - '
    ' + clientId + '

    ' + connectionId + '
    ', - '' + clientIp + '', - '' + viewport + '', - '' + connectedAt + '', - '
    ' + escapeHtml(client.screen_name) + '
    Showing: ' + currentSlide + '
    ', - '' + renderClientActionCell(client) + '', - '' - ].join(''); - } - - function renderScreenRow(screen) { - var clientCount = Number(screen.player_connection_count || 0); - return [ - '', - '' + escapeHtml(screen.name) + '', - '
    ' + escapeHtml(screen.player_url || '') + '', - '' + escapeHtml(screen.playlist_name || '') + '', - '' + (clientCount ? '
    ' + clientCount + ' connected
    ' : 'No clients connected.') + '', - '' - ].join(''); - } - - function updateStats(state) { - var clientCount = document.getElementById('dashboard-client-count'); - var screenCount = document.getElementById('dashboard-screen-count'); - var slideCount = document.getElementById('dashboard-slide-count'); - var playlistCount = document.getElementById('dashboard-playlist-count'); - - if (playlistCount && Array.isArray(state.playlists)) { - playlistCount.textContent = String(state.playlists.length); - } - if (slideCount && Array.isArray(state.slides)) { - slideCount.textContent = String(state.slides.length); - } - if (screenCount && Array.isArray(state.screens)) { - screenCount.textContent = String(state.screens.length); - } - if (clientCount) { - clientCount.textContent = String(Number(state.connectedClientsCount || 0)); - } - } - - function updateClientTable(state) { - var tbody = document.getElementById('dashboard-clients-table-body'); - if (!tbody || !Array.isArray(state.clients)) { - return; - } - if (!state.clients.length) { - tbody.innerHTML = 'No connected clients yet.'; - return; - } - var existingRows = {}; - Array.prototype.slice.call(tbody.querySelectorAll('tr[data-client-key]')).forEach(function (row) { - existingRows[row.getAttribute('data-client-key')] = row; + var className = String(button.className || ''); + classesToRemove.forEach(function (removeClass) { + className = className.replace(new RegExp('(^|\\s)' + removeClass + '(?=\\s|$)', 'g'), ' '); }); - - Array.prototype.slice.call(tbody.querySelectorAll('tr')).forEach(function (row) { - if (!row.hasAttribute('data-client-key')) { - row.parentNode.removeChild(row); - } - }); - - state.clients.forEach(function (client, index) { - var rowKey = getClientRowKey(client); - var row = existingRows[rowKey]; - if (!row) { - var tempBody = document.createElement('tbody'); - tempBody.innerHTML = renderClientRow(client); - row = tempBody.firstElementChild; - } - - if (!row) { - return; - } - - row.setAttribute('data-client-key', rowKey); - if (row.cells && row.cells.length >= 6) { - var connectedAt = client.connectedAt ? '
    ' + escapeHtml(client.connectedAtLabel || formatDashboardDate(client.connectedAt) || client.connectedAt) + '
    ' + (client.lastSeenAt ? '
    ' + escapeHtml(client.lastSeenAtLabel || formatDashboardDate(client.lastSeenAt) || client.lastSeenAt) + '
    ' : '') : 'Unknown'; - var clientIp = client.clientIp ? escapeHtml(client.clientIp) : (client.remoteAddress ? escapeHtml(client.remoteAddress) : 'Unknown'); - var viewport = client.viewport && client.viewport.width && client.viewport.height ? escapeHtml(client.viewport.width + 'x' + client.viewport.height) : 'Unknown'; - var clientId = client.clientId ? escapeHtml(client.clientId) : 'Unknown'; - var connectionId = client.id ? escapeHtml(client.id) : 'Unknown'; - var currentSlide = client.currentSlideTitle ? escapeHtml(client.currentSlideTitle) : 'No slide currently showing'; - - row.cells[0].innerHTML = '
    ' + clientId + '

    ' + connectionId + '
    '; - row.cells[1].innerHTML = clientIp; - row.cells[2].innerHTML = viewport; - row.cells[3].innerHTML = connectedAt; - row.cells[4].innerHTML = '
    ' + escapeHtml(client.screen_name) + '
    Showing: ' + currentSlide + '
    '; - updateClientActionCell(row.cells[5], client); - } - - var referenceNode = tbody.children[index] || null; - if (referenceNode !== row) { - tbody.insertBefore(row, referenceNode); - } - }); - - while (tbody.children.length > state.clients.length) { - tbody.removeChild(tbody.lastElementChild); + if (classToAdd) { + className += ' ' + classToAdd; } - - window.applyTableSort(document.getElementById('dashboard-clients-table')); + button.className = className.replace(/\s+/g, ' ').trim(); } - function updateScreenTable(state) { - var table = document.getElementById('dashboard-screens-table'); - if (!table || !Array.isArray(state.screens)) { - return; + function normalizeDisplayIp(value) { + var ip = String(value || '').trim(); + if (!ip) { + return ''; } - var tbody = table.tBodies && table.tBodies[0] ? table.tBodies[0] : null; - if (!tbody) { - return; + + if (ip.toLowerCase().indexOf('::ffff:') === 0) { + return ip.slice(7).trim(); } - if (!state.screens.length) { - tbody.innerHTML = 'No screens yet.'; - return; - } - tbody.innerHTML = state.screens.map(renderScreenRow).join(''); - window.applyTableSort(table); + + return ip; } - function updateDashboardQuickActions(state) { - var blackoutButton = document.getElementById('dashboard-blackout-all-button'); - if (!blackoutButton || !state || !Array.isArray(state.clients)) { - return; - } - - var hasClients = state.clients.length > 0; - var allBlackout = hasClients && state.clients.every(function (client) { - return Boolean(client && client.blackout); - }); - var label = allBlackout ? 'Restore all clients' : 'Blackout all clients'; - var blackoutForm = blackoutButton.form; - var blackoutInput = blackoutForm ? blackoutForm.querySelector('input[name="blackout"]') : null; - - blackoutButton.textContent = label; - blackoutButton.className = 'button-link list-action' + (allBlackout ? ' is-blackout' : ''); - if (blackoutInput) { - blackoutInput.value = allBlackout ? 'false' : 'true'; - } - if (blackoutForm) { - blackoutForm.setAttribute('data-confirm-message', allBlackout ? 'Restore all connected clients?' : 'Blackout all connected clients?'); - } - blackoutButton.setAttribute('aria-label', label); - } - - function handleDashboardState(state) { - if (!state) { - return; - } - updateStats(state); - updateScreenTable(state); - updateClientTable(state); - updateDashboardQuickActions(state); - } - - window.webHandleDashboardState = handleDashboardState; - function initConfirmForms() { document.addEventListener('submit', function (event) { var form = event.target; @@ -340,6 +96,62 @@ }); } + function markFormDirty(form) { + if (!form || !form.hasAttribute || form.hasAttribute('data-clean-on-load')) { + return; + } + form.dataset.dirty = 'true'; + } + + function clearFormDirty(form) { + if (!form) { + return; + } + form.dataset.dirty = 'false'; + } + + function isFormDirty(form) { + return Boolean(form && form.dataset && form.dataset.dirty === 'true'); + } + + function initDirtyTracking() { + document.addEventListener('input', function (event) { + var target = event.target; + if (!target || !target.form) { + return; + } + markFormDirty(target.form); + }, true); + + document.addEventListener('change', function (event) { + var target = event.target; + if (!target || !target.form) { + return; + } + markFormDirty(target.form); + }, true); + } + + function initCancelConfirm() { + document.addEventListener('click', function (event) { + var cancelTarget = event.target.closest('[data-confirm-unsaved]'); + if (!cancelTarget) { + return; + } + + var form = cancelTarget.form || cancelTarget.closest('form') || document.querySelector('form[data-dirty="true"]'); + if (!isFormDirty(form)) { + return; + } + + var message = cancelTarget.getAttribute('data-confirm-unsaved') || 'You have unsaved changes. Leave this page?'; + if (!window.confirm(message)) { + event.preventDefault(); + event.stopPropagation(); + } + }, true); + } + function initAsyncCommandForms() { document.addEventListener('submit', function (event) { var form = event.target; @@ -384,6 +196,42 @@ } function initAsyncSaveForms() { + function setSaveActionValue(form, value) { + if (!form) { + return; + } + + var hiddenInput = form.querySelector('input[type="hidden"][name="save_action"]'); + if (!hiddenInput) { + hiddenInput = document.createElement('input'); + hiddenInput.type = 'hidden'; + hiddenInput.name = 'save_action'; + form.appendChild(hiddenInput); + } + + hiddenInput.value = String(value || '').trim().toLowerCase(); + } + + document.addEventListener('click', function (event) { + var target = event.target; + if (!target || !target.closest) { + return; + } + + var button = target.closest('button[name="save_action"]'); + if (!button) { + return; + } + + var form = button.form || button.closest('form'); + if (!form || !form.hasAttribute || !form.hasAttribute('data-async-save')) { + return; + } + + setSaveActionValue(form, button.value || ''); + form.dataset.submitterValue = String(button.value || '').trim().toLowerCase(); + }, true); + document.addEventListener('submit', function (event) { var form = event.target; if (!form || !form.hasAttribute || !form.hasAttribute('data-async-save')) { @@ -404,7 +252,13 @@ event.preventDefault(); form.dataset.busy = 'true'; + var hiddenSaveAction = form.querySelector('input[type="hidden"][name="save_action"]'); var formData = new FormData(form); + var submitterValue = String((hiddenSaveAction && hiddenSaveAction.value) || form.dataset.submitterValue || '').trim().toLowerCase(); + if (event.submitter && event.submitter.name) { + submitterValue = String(event.submitter.value || '').trim().toLowerCase(); + formData.set(event.submitter.name, event.submitter.value || ''); + } var hasFileValue = false; formData.forEach(function (value) { if (value && typeof value === 'object' && typeof value.name === 'string') { @@ -437,10 +291,14 @@ throw new Error(text || 'Unable to save changes.'); }); } - if (form.hasAttribute && form.hasAttribute('data-async-save-reload')) { - window.location.replace(response.url || window.location.href); + if (submitterValue === 'close' || submitterValue === 'new') { + var redirectUrl = submitterValue === 'close' + ? String(form.dataset.asyncSaveCloseUrl || response.url || window.location.href) + : String(form.dataset.asyncSaveNewUrl || response.url || window.location.href); + window.location.replace(redirectUrl); return; } + clearFormDirty(form); return response.text().then(function (text) { var savedMessage = ''; try { @@ -452,12 +310,16 @@ } catch (_error) { savedMessage = ''; } - showToast(savedMessage || 'Saved.'); + showToast(savedMessage || 'Saved.', 'success'); }); }).catch(function (error) { window.alert(error.message || 'Unable to save changes.'); }).finally(function () { delete form.dataset.busy; + delete form.dataset.submitterValue; + if (hiddenSaveAction) { + hiddenSaveAction.value = ''; + } }); }, true); } @@ -479,6 +341,8 @@ } initConfirmForms(); + initDirtyTracking(); + initCancelConfirm(); initAsyncCommandForms(); initAsyncSaveForms(); initSubmitOnChange(); diff --git a/src/web/public/js/dashboard/dashboard-page.js b/src/web/public/js/dashboard/dashboard-page.js new file mode 100644 index 0000000..f180508 --- /dev/null +++ b/src/web/public/js/dashboard/dashboard-page.js @@ -0,0 +1,462 @@ +(function () { + function escapeHtml(value) { + return String(value ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function formatDashboardDate(value) { + if (!value) { + return ''; + } + var date = new Date(value); + if (Number.isNaN(date.getTime())) { + return ''; + } + return new Intl.DateTimeFormat('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + hour: 'numeric', + minute: '2-digit', + second: '2-digit' + }).format(date); + } + + function getClientRowKey(client) { + return String(client && client.id ? client.id : client && client.clientId ? client.clientId : '').trim(); + } + + function getClientDisplayName(client) { + if (client && client.client_name) { + return String(client.client_name).trim(); + } + var clientId = String(client && client.clientId ? client.clientId : '').trim(); + if (clientId) { + return clientId; + } + return ''; + } + + function setButtonVariant(button, classesToRemove, classToAdd) { + if (!button) { + return; + } + + if (button.classList) { + classesToRemove.forEach(function (className) { + button.classList.remove(className); + }); + if (classToAdd) { + button.classList.add(classToAdd); + } + return; + } + + var className = String(button.className || ''); + classesToRemove.forEach(function (removeClass) { + className = className.replace(new RegExp('(^|\\s)' + removeClass + '(?=\\s|$)', 'g'), ' '); + }); + if (classToAdd) { + className += ' ' + classToAdd; + } + button.className = className.replace(/\s+/g, ' ').trim(); + } + + function normalizeDisplayIp(value) { + var ip = String(value || '').trim(); + if (!ip) { + return ''; + } + + if (ip.toLowerCase().indexOf('::ffff:') === 0) { + return ip.slice(7).trim(); + } + + return ip; + } + + function renderClientActionCell(client) { + var paused = Boolean(client.paused); + var pauseButtonClass = 'btn btn-sm btn-info'; + var pauseButtonLabel = paused ? 'Resume' : 'Pause'; + var blackout = Boolean(client.blackout); + var blackoutButtonClass = 'btn btn-sm ' + (blackout ? 'btn-success' : 'btn-secondary'); + var blackoutButtonLabel = blackout ? 'Restore' : 'Blackout'; + var reloadConfirmMessage = 'Reloading will restart the player page. Continue?'; + var blackoutCommandValue = blackout ? 'false' : 'true'; + + return '
    '; + } + + function updateClientActionCell(cell, client) { + if (!cell) { + return; + } + + var pauseButton = cell.querySelector('button[data-action="pause"]'); + if (!pauseButton) { + cell.innerHTML = renderClientActionCell(client); + return; + } + + var paused = Boolean(client.paused); + setButtonVariant(pauseButton, ['btn-secondary', 'btn-outline-primary'], 'btn-info'); + pauseButton.innerHTML = '' + (paused ? 'Resume' : 'Pause'); + + var pauseForm = pauseButton.form; + if (pauseForm) { + var commandInput = pauseForm.querySelector('input[name="command"]'); + if (commandInput) { + commandInput.value = 'pause'; + } + var connectionInput = pauseForm.querySelector('input[name="connectionId"]'); + if (connectionInput) { + connectionInput.value = client.id || ''; + } + pauseForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; + } + + var reloadButton = cell.querySelector('button[data-action="reload"]'); + if (reloadButton) { + reloadButton.innerHTML = 'Reload'; + setButtonVariant(reloadButton, ['btn-danger', 'btn-success', 'btn-outline-secondary', 'btn-outline-dark', 'btn-outline-primary', 'btn-secondary'], 'btn-danger'); + var reloadForm = reloadButton.form; + if (reloadForm) { + var reloadInput = reloadForm.querySelector('input[name="connectionId"]'); + if (reloadInput) { + reloadInput.value = client.id || ''; + } + reloadForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; + reloadForm.setAttribute('data-confirm-message', 'Reloading will restart the player page. Continue?'); + } + } + + var blackoutButton = cell.querySelector('button[data-action="blackout"]'); + if (!blackoutButton) { + cell.innerHTML = renderClientActionCell(client); + return; + } + + var blackout = Boolean(client.blackout); + setButtonVariant(blackoutButton, ['btn-success', 'btn-secondary'], blackout ? 'btn-success' : 'btn-secondary'); + blackoutButton.innerHTML = '' + (blackout ? 'Restore' : 'Blackout'); + + var blackoutForm = blackoutButton.form; + if (blackoutForm) { + var blackoutCommandInput = blackoutForm.querySelector('input[name="command"]'); + if (blackoutCommandInput) { + blackoutCommandInput.value = 'blackout'; + } + var blackoutStateInput = blackoutForm.querySelector('input[name="blackout"]'); + if (blackoutStateInput) { + blackoutStateInput.value = blackout ? 'false' : 'true'; + } + var blackoutConnectionInput = blackoutForm.querySelector('input[name="connectionId"]'); + if (blackoutConnectionInput) { + blackoutConnectionInput.value = client.id || ''; + } + blackoutForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; + } + + var previousButton = cell.querySelector('button[data-action="previous"]'); + if (!previousButton) { + cell.innerHTML = renderClientActionCell(client); + return; + } + setButtonVariant(previousButton, ['btn-outline-secondary', 'btn-success', 'btn-danger', 'btn-primary', 'btn-secondary', 'btn-warning'], 'btn-warning'); + previousButton.setAttribute('aria-label', 'Previous slide'); + var previousForm = previousButton.form; + if (previousForm) { + var previousCommandInput = previousForm.querySelector('input[name="command"]'); + if (previousCommandInput) { + previousCommandInput.value = 'previous'; + } + var previousConnectionInput = previousForm.querySelector('input[name="connectionId"]'); + if (previousConnectionInput) { + previousConnectionInput.value = client.id || ''; + } + previousForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; + } + + var nextButton = cell.querySelector('button[data-action="next"]'); + if (!nextButton) { + cell.innerHTML = renderClientActionCell(client); + return; + } + setButtonVariant(nextButton, ['btn-outline-secondary', 'btn-success', 'btn-danger', 'btn-primary', 'btn-secondary', 'btn-warning'], 'btn-warning'); + nextButton.setAttribute('aria-label', 'Next slide'); + var nextForm = nextButton.form; + if (nextForm) { + var nextCommandInput = nextForm.querySelector('input[name="command"]'); + if (nextCommandInput) { + nextCommandInput.value = 'next'; + } + var nextConnectionInput = nextForm.querySelector('input[name="connectionId"]'); + if (nextConnectionInput) { + nextConnectionInput.value = client.id || ''; + } + nextForm.action = '/admin/screens/' + encodeURIComponent(client.screen_slug) + '/commands'; + } + } + + function renderClientRow(client) { + var connectedAt = client.connectedAt ? '
    ' + escapeHtml(client.connectedAtLabel || formatDashboardDate(client.connectedAt) || client.connectedAt) + '
    ' + (client.lastSeenAt ? '
    ' + escapeHtml(client.lastSeenAtLabel || formatDashboardDate(client.lastSeenAt) || client.lastSeenAt) + '
    ' : '') : 'Unknown'; + var clientIpValue = normalizeDisplayIp(client.clientIp); + var clientIp = clientIpValue ? escapeHtml(clientIpValue) : 'Unknown'; + var viewport = client.viewport && client.viewport.width && client.viewport.height ? escapeHtml(client.viewport.width + 'x' + client.viewport.height) : 'Unknown'; + var clientNameValue = getClientDisplayName(client); + var clientName = clientNameValue ? escapeHtml(clientNameValue) : 'Unknown'; + var screenName = client.screen_name ? escapeHtml(client.screen_name) : 'Unknown'; + var currentSlide = client.currentSlideTitle ? escapeHtml(client.currentSlideTitle) : 'No slide currently showing'; + + return [ + '', + '
    ' + clientName + '
    ', + '
    ' + screenName + '
    ', + '' + currentSlide + '', + '' + clientIp + '', + '' + viewport + '', + '' + connectedAt + '', + '' + renderClientActionCell(client) + '', + '' + ].join(''); + } + + function renderScreenRow(screen) { + var clientCount = Number(screen.player_connection_count || 0); + return [ + '', + '' + escapeHtml(screen.name) + '', + '' + escapeHtml(screen.player_url || '') + '', + '' + escapeHtml(screen.playlist_name || '') + '', + '' + (clientCount ? '
    ' + clientCount + ' connected
    ' : 'No clients connected.') + '', + '' + ].join(''); + } + + function updateStats(state) { + var clientCount = document.getElementById('dashboard-client-count'); + var screenCount = document.getElementById('dashboard-screen-count'); + var slideCount = document.getElementById('dashboard-slide-count'); + var playlistCount = document.getElementById('dashboard-playlist-count'); + + if (playlistCount && Array.isArray(state.playlists)) { + playlistCount.textContent = String(state.playlists.length); + } + if (slideCount && Array.isArray(state.slides)) { + slideCount.textContent = String(state.slides.length); + } + if (screenCount && Array.isArray(state.screens)) { + screenCount.textContent = String(state.screens.length); + } + if (clientCount) { + clientCount.textContent = String(Number(state.connectedClientsCount || 0)); + } + } + + function updateClientTable(state) { + var tbody = document.getElementById('dashboard-clients-table-body'); + if (!tbody || !Array.isArray(state.clients)) { + return; + } + if (!state.clients.length) { + tbody.innerHTML = 'No connected clients yet.'; + return; + } + var existingRows = {}; + Array.prototype.slice.call(tbody.querySelectorAll('tr[data-client-key]')).forEach(function (row) { + existingRows[row.getAttribute('data-client-key')] = row; + }); + + Array.prototype.slice.call(tbody.querySelectorAll('tr')).forEach(function (row) { + if (!row.hasAttribute('data-client-key')) { + row.parentNode.removeChild(row); + } + }); + + state.clients.forEach(function (client, index) { + var rowKey = getClientRowKey(client); + var row = existingRows[rowKey]; + if (!row) { + var tempBody = document.createElement('tbody'); + tempBody.innerHTML = renderClientRow(client); + row = tempBody.firstElementChild; + } + + if (!row) { + return; + } + + row.setAttribute('data-client-key', rowKey); + row.setAttribute('data-client-id', client.clientId || ''); + row.setAttribute('data-client-device-id', client.deviceId || ''); + row.setAttribute('data-client-screen-slug', client.screen_slug || ''); + if (row.cells && row.cells.length >= 7) { + var connectedAt = client.connectedAt ? '
    ' + escapeHtml(client.connectedAtLabel || formatDashboardDate(client.connectedAt) || client.connectedAt) + '
    ' + (client.lastSeenAt ? '
    ' + escapeHtml(client.lastSeenAtLabel || formatDashboardDate(client.lastSeenAt) || client.lastSeenAt) + '
    ' : '') : 'Unknown'; + var clientIpValue = normalizeDisplayIp(client.clientIp); + var clientIp = clientIpValue ? escapeHtml(clientIpValue) : 'Unknown'; + var viewport = client.viewport && client.viewport.width && client.viewport.height ? escapeHtml(client.viewport.width + 'x' + client.viewport.height) : 'Unknown'; + var clientNameValue = getClientDisplayName(client); + var clientName = clientNameValue ? escapeHtml(clientNameValue) : 'Unknown'; + var screenName = client.screen_name ? escapeHtml(client.screen_name) : 'Unknown'; + var currentSlide = client.currentSlideTitle ? escapeHtml(client.currentSlideTitle) : 'No slide currently showing'; + + row.cells[0].innerHTML = '
    ' + clientName + '
    '; + row.cells[1].innerHTML = '
    ' + screenName + '
    '; + row.cells[2].innerHTML = currentSlide; + row.cells[3].innerHTML = clientIp; + row.cells[4].innerHTML = viewport; + row.cells[5].innerHTML = connectedAt; + updateClientActionCell(row.cells[6], client); + } + + var referenceNode = tbody.children[index] || null; + if (referenceNode !== row) { + tbody.insertBefore(row, referenceNode); + } + }); + + while (tbody.children.length > state.clients.length) { + tbody.removeChild(tbody.lastElementChild); + } + + window.applyTableSort(document.getElementById('dashboard-clients-table')); + } + + function updateScreenTable(state) { + var table = document.getElementById('dashboard-screens-table'); + if (!table || !Array.isArray(state.screens)) { + return; + } + var tbody = table.tBodies && table.tBodies[0] ? table.tBodies[0] : null; + if (!tbody) { + return; + } + if (!state.screens.length) { + tbody.innerHTML = 'No screens yet.'; + return; + } + tbody.innerHTML = state.screens.map(renderScreenRow).join(''); + window.applyTableSort(table); + } + + function updateDashboardQuickActions(state) { + var blackoutButton = document.getElementById('dashboard-blackout-all-button'); + if (!blackoutButton || !state || !Array.isArray(state.clients)) { + return; + } + + var hasClients = state.clients.length > 0; + var allBlackout = hasClients && state.clients.every(function (client) { + return Boolean(client && client.blackout); + }); + var label = allBlackout ? 'Restore all clients' : 'Blackout all clients'; + var blackoutForm = blackoutButton.form; + var blackoutInput = blackoutForm ? blackoutForm.querySelector('input[name="blackout"]') : null; + + blackoutButton.innerHTML = (allBlackout ? '' : '') + escapeHtml(label); + setButtonVariant(blackoutButton, ['btn-success', 'btn-danger', 'btn-secondary', 'btn-outline-secondary', 'btn-outline-dark'], 'btn-secondary'); + if (blackoutInput) { + blackoutInput.value = allBlackout ? 'false' : 'true'; + } + if (blackoutForm) { + blackoutForm.setAttribute('data-confirm-message', allBlackout ? 'Restore all connected clients?' : 'Blackout all connected clients?'); + } + blackoutButton.setAttribute('aria-label', label); + } + + function handleDashboardState(state) { + if (!state) { + return; + } + updateStats(state); + updateScreenTable(state); + updateClientTable(state); + updateDashboardQuickActions(state); + } + + function sendClientRename(screenSlug, connectionId, clientId, deviceId, clientName) { + var body = new URLSearchParams(); + body.append('command', 'setClientName'); + body.append('connectionId', String(connectionId || '').trim()); + body.append('clientId', String(clientId || '').trim()); + body.append('deviceId', String(deviceId || '').trim()); + body.append('clientName', String(clientName || '').trim()); + + return fetch('/admin/screens/' + encodeURIComponent(String(screenSlug || '').trim()) + '/commands', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'application/json, text/plain, */*' + }, + body: body.toString(), + credentials: 'same-origin' + }).then(function (response) { + if (!response.ok) { + return response.text().then(function (text) { + throw new Error(text || 'Unable to rename client.'); + }); + } + return response.json().catch(function () { + return { ok: true }; + }); + }); + } + + function initClientRenameHandler() { + var table = document.getElementById('dashboard-clients-table'); + var tbody = document.getElementById('dashboard-clients-table-body'); + if (!table || !tbody) { + return; + } + + tbody.addEventListener('dblclick', function (event) { + var cell = event.target && event.target.closest ? event.target.closest('td[data-label="Client"]') : null; + if (!cell || !tbody.contains(cell)) { + return; + } + + var row = cell.parentElement; + if (!row) { + return; + } + + var connectionId = String(row.getAttribute('data-client-key') || '').trim(); + var clientId = String(row.getAttribute('data-client-id') || '').trim(); + var deviceId = String(row.getAttribute('data-client-device-id') || '').trim(); + var screenSlug = String(row.getAttribute('data-client-screen-slug') || '').trim(); + var currentName = String(cell.textContent || '').trim(); + var nextName = window.prompt('Rename connected client', currentName && currentName !== 'Unknown' ? currentName : ''); + if (nextName === null) { + return; + } + + nextName = String(nextName || '').trim(); + if (!nextName) { + window.alert('Client name is required.'); + return; + } + if (!connectionId || !screenSlug) { + window.alert('Unable to rename this client right now.'); + return; + } + + sendClientRename(screenSlug, connectionId, clientId, deviceId, nextName).then(function () { + if (row && row.cells && row.cells[0]) { + row.cells[0].innerHTML = '
    ' + escapeHtml(nextName) + '
    '; + } + }).catch(function (error) { + window.alert(error && error.message ? error.message : 'Unable to rename client.'); + }); + }); + } + + window.webHandleDashboardState = handleDashboardState; + + initClientRenameHandler(); +}()); \ No newline at end of file diff --git a/src/web/public/js/playlist-schedule.js b/src/web/public/js/playlists/playlist-schedule.js similarity index 69% rename from src/web/public/js/playlist-schedule.js rename to src/web/public/js/playlists/playlist-schedule.js index 5952d68..b7cb70f 100644 --- a/src/web/public/js/playlist-schedule.js +++ b/src/web/public/js/playlists/playlist-schedule.js @@ -23,43 +23,69 @@ function initPlaylistScheduleModal() { var dialog = document.getElementById('slide-schedule-dialog'); - var frame = document.getElementById('slide-schedule-frame'); - var closeButton = document.getElementById('slide-schedule-close'); + var content = document.getElementById('slide-schedule-content'); var triggers = document.querySelectorAll('[data-schedule-config]'); - if (!dialog || !frame || !closeButton || !triggers.length) { + if (!dialog || !content || !triggers.length) { return; } + function initInjectedContent() { + if (typeof window.initPlaylistScheduleForm === 'function') { + window.initPlaylistScheduleForm(content); + } + } + + function collectScheduleParams(row, rowKey) { + var params = new URLSearchParams(); + var scheduleFields = [ + 'schedule_mode[]', + 'schedule_start_datetime[]', + 'schedule_end_datetime[]', + 'schedule_start_time[]', + 'schedule_end_time[]', + 'schedule_days_json[]' + ]; + + params.set('row_key', String(rowKey || '')); + scheduleFields.forEach(function (fieldName) { + var field = row && row.querySelector ? row.querySelector('[name="' + fieldName + '"]') : null; + var value = field && typeof field.value !== 'undefined' ? String(field.value || '') : ''; + if (value) { + params.set(fieldName.replace(/\[\]$/, ''), value); + } + }); + + return params; + } + function openScheduleModal(url) { - frame.src = url; + content.innerHTML = '
    Loading schedule...
    '; if (typeof dialog.showModal === 'function') { dialog.showModal(); } else { dialog.setAttribute('open', 'open'); } - } - function resizeScheduleFrame() { - try { - if (!frame.contentWindow || !frame.contentWindow.document) { - return; + fetch(url, { + credentials: 'same-origin' + }).then(function (response) { + if (!response.ok) { + return response.text().then(function (text) { + throw new Error(text || 'Unable to open schedule editor.'); + }); } - var doc = frame.contentWindow.document; - var height = Math.max( - doc.body.scrollHeight, - doc.documentElement.scrollHeight, - doc.body.offsetHeight, - doc.documentElement.offsetHeight - ); - frame.style.height = height + 'px'; - } catch (_error) { - frame.style.height = '70vh'; - } + return response.text(); + }).then(function (html) { + content.innerHTML = html; + initInjectedContent(); + }).catch(function (error) { + content.innerHTML = '
    ' + String(error && error.message ? error.message : 'Unable to open schedule editor.') + '
    '; + }); } function closeScheduleModal() { - frame.src = 'about:blank'; + content.innerHTML = ''; if (typeof dialog.close === 'function') { dialog.close(); } else { @@ -68,22 +94,23 @@ } window.openScheduleModal = openScheduleModal; - window.resizeScheduleFrame = resizeScheduleFrame; window.closeScheduleModal = closeScheduleModal; Array.prototype.forEach.call(triggers, function (trigger) { trigger.addEventListener('click', function () { var url = trigger.getAttribute('data-schedule-config'); var rowKey = trigger.getAttribute('data-schedule-config-row') || ''; - if (rowKey && url.indexOf('row_key=') === -1) { + var row = trigger.closest('tr[data-playlist-slide-row]'); + if (row) { + var params = collectScheduleParams(row, rowKey || row.getAttribute('data-row-key') || ''); + url += (url.indexOf('?') === -1 ? '?' : '&') + params.toString(); + } else if (rowKey && url.indexOf('row_key=') === -1) { url += (url.indexOf('?') === -1 ? '?' : '&') + 'row_key=' + encodeURIComponent(rowKey); } openScheduleModal(url); }); }); - frame.addEventListener('load', resizeScheduleFrame); - closeButton.addEventListener('click', closeScheduleModal); } function scheduleSummary(values) { @@ -104,15 +131,19 @@ return 'Always visible'; } - function initPlaylistScheduleForm() { - var form = document.querySelector('form[action*="/config"]'); - var select = document.getElementById('schedule-mode-select'); + function initPlaylistScheduleForm(root) { + var scope = root || document; + var form = scope.querySelector('form[action*="/config"]'); + var select = scope.querySelector('#schedule-mode-select'); if (!form || !select) { return; } - var datesPanel = document.getElementById('schedule-dates-panel'); - var timesPanel = document.getElementById('schedule-times-panel'); + var DEFAULT_START_TIME = '00:00'; + var DEFAULT_END_TIME = '23:59'; + + var datesPanel = scope.querySelector('#schedule-dates-panel'); + var timesPanel = scope.querySelector('#schedule-times-panel'); var startDateInput = form.querySelector('[name="schedule_start_datetime"]'); var endDateInput = form.querySelector('[name="schedule_end_datetime"]'); var startTimeInput = form.querySelector('[name="schedule_start_time"]'); @@ -120,16 +151,89 @@ var rowKeyInput = form.querySelector('[name="row_key"]'); var dayCheckboxes = form.querySelectorAll('[name="schedule_days"]'); - function notifyParentResize() { - if (window.parent && typeof window.parent.resizeScheduleFrame === 'function') { - window.parent.resizeScheduleFrame(); + function clearScheduleValidity() { + [startDateInput, endDateInput, startTimeInput, endTimeInput].forEach(function (input) { + if (input) { + input.setCustomValidity(''); + } + }); + } + + function setScheduleError(input, message) { + if (!input) { + return; } + input.setCustomValidity(message); + } + + function validateScheduleForm() { + var mode = select.value; + var firstDayCheckbox = dayCheckboxes.length ? dayCheckboxes[0] : null; + + clearScheduleValidity(); + + if (mode === 'dates') { + if (!startDateInput.value) { + setScheduleError(startDateInput, 'Start datetime is required for this schedule mode.'); + } + if (!endDateInput.value) { + setScheduleError(endDateInput, 'End datetime is required for this schedule mode.'); + } + if (startDateInput.value && endDateInput.value && new Date(endDateInput.value) < new Date(startDateInput.value)) { + setScheduleError(endDateInput, 'End datetime must be after start datetime.'); + } + } + + if (mode === 'times') { + if (!startTimeInput.value) { + setScheduleError(startTimeInput, 'Start time is required for this schedule mode.'); + } + if (!endTimeInput.value) { + setScheduleError(endTimeInput, 'End time is required for this schedule mode.'); + } + if (startTimeInput.value && endTimeInput.value && endTimeInput.value < startTimeInput.value) { + setScheduleError(endTimeInput, 'End time must be after start time.'); + } + if (!Array.prototype.some.call(dayCheckboxes, function (checkbox) { + return checkbox.checked; + })) { + setScheduleError(firstDayCheckbox, 'Select at least one day.'); + } + } + + return form.checkValidity(); + } + + [startDateInput, endDateInput, startTimeInput, endTimeInput].forEach(function (input) { + if (input) { + input.addEventListener('input', clearScheduleValidity); + } + }); + Array.prototype.forEach.call(dayCheckboxes, function (checkbox) { + checkbox.addEventListener('change', clearScheduleValidity); + }); + select.addEventListener('change', clearScheduleValidity); + + function notifyParentResize() { + return; } function updateVisibility() { var mode = select.value; - datesPanel.style.display = mode === 'dates' ? '' : 'none'; - timesPanel.style.display = mode === 'times' ? '' : 'none'; + if (datesPanel) { + datesPanel.classList.toggle('is-hidden', mode !== 'dates'); + } + if (timesPanel) { + timesPanel.classList.toggle('is-hidden', mode !== 'times'); + } + if (mode === 'times') { + if (!startTimeInput.value) { + startTimeInput.value = DEFAULT_START_TIME; + } + if (!endTimeInput.value) { + endTimeInput.value = DEFAULT_END_TIME; + } + } window.requestAnimationFrame(function () { notifyParentResize(); }); @@ -141,37 +245,12 @@ form.addEventListener('submit', function (event) { event.preventDefault(); + if (!validateScheduleForm()) { + form.reportValidity(); + return; + } + var mode = select.value; - var datesIncomplete = mode === 'dates' && (!startDateInput.value || !endDateInput.value); - var timesIncomplete = mode === 'times' && (!startTimeInput.value || !endTimeInput.value || !Array.prototype.some.call(dayCheckboxes, function (checkbox) { - return checkbox.checked; - })); - - if (mode === 'dates' && !datesIncomplete) { - if (new Date(endDateInput.value) < new Date(startDateInput.value)) { - alert('End datetime must be after start datetime.'); - return; - } - } - if (mode === 'times' && !timesIncomplete) { - if (endTimeInput.value < startTimeInput.value) { - alert('End time must be after start time.'); - return; - } - } - - if (datesIncomplete || timesIncomplete) { - mode = 'always'; - select.value = 'always'; - startDateInput.value = ''; - endDateInput.value = ''; - startTimeInput.value = ''; - endTimeInput.value = ''; - Array.prototype.forEach.call(dayCheckboxes, function (checkbox) { - checkbox.checked = false; - }); - updateVisibility(); - } var selectedDays = []; Array.prototype.forEach.call(dayCheckboxes, function (checkbox) { @@ -264,6 +343,12 @@ } } + function markPlaylistDirty() { + if (form && form.dataset) { + form.dataset.dirty = 'true'; + } + } + function scheduleSummaryForRow(row) { var modeInput = row.querySelector('[name="schedule_mode[]"]'); var startDatetime = row.querySelector('[name="schedule_start_datetime[]"]'); @@ -351,15 +436,15 @@ addSlideSelect.disabled = availableCount === 0; } if (addSlideEmpty) { - addSlideEmpty.style.display = availableCount === 0 ? '' : 'none'; + addSlideEmpty.classList.toggle('is-hidden', availableCount !== 0); } if (addSection && addSlideForm && addSlideSelect && addSlideButton) { var controlsVisible = availableCount > 0; - addSlideForm.style.display = controlsVisible ? '' : 'none'; + addSlideForm.classList.toggle('is-hidden', !controlsVisible); } } - function updateRowOrder() { + function updateRowOrder(markDirty) { var rows = getRows(); rows.forEach(function (row, index) { var orderNumber = row.querySelector('.playlist-order-number'); @@ -369,6 +454,9 @@ }); syncAddSlideOptions(); updateEmptyState(); + if (markDirty) { + markPlaylistDirty(); + } } function lockDraggedRowWidths(row) { @@ -435,11 +523,13 @@ if (summary) { summary.textContent = values.summary || scheduleSummaryForRow(row); } + markPlaylistDirty(); } function createRow(values) { var row = document.createElement('tr'); var rowKey = values.row_key || ('new-' + Date.now() + '-' + Math.random().toString(36).slice(2)); + var playlistId = tbody.getAttribute('data-playlist-id') || ''; row.setAttribute('data-playlist-slide-row', ''); row.setAttribute('data-row-key', rowKey); row.setAttribute('data-slide-id', String(values.slide_id)); @@ -447,24 +537,24 @@ row.innerHTML = '' + '' + '
    ' + - '' + + '' + '' + '
    ' + '' + - '' + values.title + '' + + '' + values.title + '' + '' + '
    ' + values.summary + '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + + '' + + '' + + '' + + '' + + '' + + '' + '' + - '' + + '' + '
    ' + - '' + - '' + + '' + + '' + '
    '; return row; } @@ -481,7 +571,7 @@ if (removeButton) { event.preventDefault(); row.remove(); - updateRowOrder(); + updateRowOrder(true); return; } @@ -514,7 +604,7 @@ }, onEnd: function () { unlockDraggedRowWidths(tbody.querySelector('.sortable-drag')); - updateRowOrder(); + updateRowOrder(true); } }); } @@ -544,7 +634,7 @@ summary: 'Always visible' }); tbody.appendChild(row); - updateRowOrder(); + updateRowOrder(true); }); } @@ -559,6 +649,8 @@ updateRowOrder(); } + window.initPlaylistScheduleForm = initPlaylistScheduleForm; + initPlaylistScheduleModal(); initPlaylistScheduleForm(); initPlaylistEditStaging(); diff --git a/src/web/public/js/slide-form.js b/src/web/public/js/slide-form.js index 104568e..efcc0d2 100644 --- a/src/web/public/js/slide-form.js +++ b/src/web/public/js/slide-form.js @@ -21,7 +21,8 @@ import { Subscript, Superscript, Underline -} from '/assets/js/ckeditor5/ckeditor5.js'; +} from '/assets/js/vendor/ckeditor5/ckeditor5.js'; +import { createTemplateSelectorLockController } from '/assets/js/slides/slide-form-template-lock.js'; (function () { var dataElement = document.getElementById('slide-editor-data'); @@ -42,13 +43,25 @@ import { var templateSelect = document.getElementById('template-select'); var templateFields = document.getElementById('template-fields'); var slideForm = document.getElementById('slide-form'); + var slideEditorShell = document.querySelector('.slide-editor-shell'); + var slideEditorSidebar = document.querySelector('.slide-editor-sidebar'); var slidePreviewMeta = document.getElementById('slide-preview-meta'); var slidePreviewStage = document.getElementById('slide-preview-stage'); + var slidePreviewCanvas = document.getElementById('slide-preview-canvas'); var slidePreviewBackground = document.getElementById('slide-preview-background'); var slidePreviewEmpty = document.getElementById('slide-preview-empty'); var slidePreviewOverlay = document.getElementById('slide-preview-overlay'); + var openPreviewPopupButton = document.getElementById('open-preview-popup'); var editorInstances = new Map(); var submitting = false; + var previewRenderFrame = 0; + var previewPopupWindow = null; + var previewPopupRenderFrame = 0; + var currentPreviewCanvasWidth = 0; + var currentPreviewCanvasHeight = 0; + var sidebarSyncFrame = 0; + var sidebarTopOffset = 16; + var templateSelectorLock = createTemplateSelectorLockController(templateSelect); class FontSizeInputUI extends Plugin { static get pluginName() { @@ -211,6 +224,21 @@ import { return String(value || ''); } + function requestPreviewRender() { + if (previewRenderFrame) { + return; + } + + previewRenderFrame = window.requestAnimationFrame(function () { + previewRenderFrame = 0; + renderPreview(); + }); + } + + function getTemplateFieldControls() { + return templateFields ? templateFields.querySelectorAll('input, textarea, select') : []; + } + function sanitizePreviewHtml(html) { var output = String(html || ''); output = output.replace(//gi, ''); @@ -445,30 +473,221 @@ import { }; } + function getPreviewCanvasDimensions(template) { + return { + width: Math.max(1, Number(template && template.canvas_size_width ? template.canvas_size_width : 1920)), + height: Math.max(1, Number(template && template.canvas_size_height ? template.canvas_size_height : 1080)) + }; + } + + function buildPreviewPopupHtml() { + return '' + + '' + + '' + + '' + + '' + + 'Slide preview' + + '' + + '' + + '' + + '' + + '' + + ''; + } + + function syncPopupPreview() { + if (!previewPopupWindow || previewPopupWindow.closed) { + previewPopupWindow = null; + return; + } + + var popupDocument = previewPopupWindow.document; + if (!popupDocument) { + return; + } + + var popupStage = popupDocument.getElementById('popup-preview-stage'); + var popupCanvas = popupDocument.getElementById('popup-preview-canvas'); + var template = getSelectedTemplate(); + + if (!popupStage || !popupCanvas) { + if (previewPopupRenderFrame) { + cancelAnimationFrame(previewPopupRenderFrame); + } + previewPopupRenderFrame = requestAnimationFrame(syncPopupPreview); + return; + } + + if (!template) { + popupStage.style.backgroundColor = '#111111'; + popupCanvas.style.width = ''; + popupCanvas.style.height = ''; + popupCanvas.style.transform = ''; + popupCanvas.innerHTML = slidePreviewCanvas.innerHTML; + var popupEmpty = popupCanvas.querySelector('#slide-preview-empty'); + var popupOverlay = popupCanvas.querySelector('#slide-preview-overlay'); + var popupBackground = popupCanvas.querySelector('#slide-preview-background'); + if (popupBackground) { + popupBackground.style.display = 'none'; + } + if (popupEmpty) { + popupEmpty.style.display = 'flex'; + popupEmpty.textContent = 'Select a template to preview the slide.'; + } + if (popupOverlay) { + popupOverlay.innerHTML = ''; + } + return; + } + + var canvasWidth = currentPreviewCanvasWidth || Math.max(1, Number(template.canvas_size_width || 1920)); + var canvasHeight = currentPreviewCanvasHeight || Math.max(1, Number(template.canvas_size_height || 1080)); + popupStage.style.backgroundColor = template.background_color || '#111111'; + popupCanvas.style.width = canvasWidth + 'px'; + popupCanvas.style.height = canvasHeight + 'px'; + popupCanvas.innerHTML = slidePreviewCanvas.innerHTML; + var popupBackground = popupCanvas.querySelector('#slide-preview-background'); + var popupEmpty = popupCanvas.querySelector('#slide-preview-empty'); + var popupOverlay = popupCanvas.querySelector('#slide-preview-overlay'); + + if (popupBackground) { + popupBackground.style.display = template.background_image_path ? 'block' : 'none'; + popupBackground.src = template.background_image_path || ''; + } + if (popupEmpty) { + popupEmpty.style.display = 'none'; + } + + var stageRect = popupStage.getBoundingClientRect(); + if (!stageRect.width || !stageRect.height) { + if (previewPopupRenderFrame) { + cancelAnimationFrame(previewPopupRenderFrame); + } + previewPopupRenderFrame = requestAnimationFrame(syncPopupPreview); + return; + } + + var scale = Math.min(stageRect.width / canvasWidth, stageRect.height / canvasHeight) || 1; + popupCanvas.style.transform = 'translate3d(0, 0, 0) scale(' + scale + ')'; + } + + function openPreviewPopup() { + if (previewPopupWindow && !previewPopupWindow.closed) { + previewPopupWindow.focus(); + syncPopupPreview(); + return; + } + + var popupWidth = 1280; + var popupHeight = 900; + var left = Math.max(0, Math.round((window.screen.width - popupWidth) / 2)); + var top = Math.max(0, Math.round((window.screen.height - popupHeight) / 2)); + var popupFeatures = [ + 'popup=yes', + 'toolbar=no', + 'location=no', + 'menubar=no', + 'directories=no', + 'status=no', + 'scrollbars=yes', + 'resizable=yes', + 'width=' + popupWidth, + 'height=' + popupHeight, + 'left=' + left, + 'top=' + top + ].join(','); + + previewPopupWindow = window.open('', 'slide-preview-popup', popupFeatures); + if (!previewPopupWindow) { + return; + } + + previewPopupWindow.document.open(); + previewPopupWindow.document.write(buildPreviewPopupHtml()); + previewPopupWindow.document.close(); + previewPopupWindow.addEventListener('resize', syncPopupPreview); + previewPopupWindow.focus(); + syncPopupPreview(); + } + + function syncSlideEditorSidebar() { + sidebarSyncFrame = 0; + + if (!slideEditorShell || !slideEditorSidebar) { + return; + } + + if (window.matchMedia && window.matchMedia('(max-width: 1199.98px)').matches) { + slideEditorSidebar.style.transform = ''; + return; + } + + var shellRect = slideEditorShell.getBoundingClientRect(); + var sidebarHeight = slideEditorSidebar.offsetHeight; + var shellTop = window.scrollY + shellRect.top; + var shellBottom = shellTop + slideEditorShell.offsetHeight; + var maxTranslate = Math.max(0, shellBottom - shellTop - sidebarHeight - sidebarTopOffset); + var desiredTranslate = Math.max(0, Math.min(window.scrollY + sidebarTopOffset - shellTop, maxTranslate)); + + slideEditorSidebar.style.transform = desiredTranslate ? 'translate3d(0, ' + desiredTranslate + 'px, 0)' : ''; + } + + function requestSidebarSync() { + if (sidebarSyncFrame) { + return; + } + + sidebarSyncFrame = window.requestAnimationFrame(syncSlideEditorSidebar); + } + function renderPreview() { var template = getSelectedTemplate(); if (!template) { - slidePreviewMeta.textContent = 'Select a template to preview the slide.'; + slidePreviewMeta.textContent = '--'; slidePreviewBackground.style.display = 'none'; slidePreviewEmpty.style.display = 'flex'; slidePreviewEmpty.textContent = 'Select a template to preview the slide.'; + slidePreviewCanvas.style.width = ''; + slidePreviewCanvas.style.height = ''; slidePreviewOverlay.innerHTML = ''; slidePreviewOverlay.style.width = ''; slidePreviewOverlay.style.height = ''; slidePreviewOverlay.style.transform = ''; slidePreviewStage.style.aspectRatio = '16 / 9'; + slidePreviewStage.style.backgroundColor = '#111111'; return; } - var canvasWidth = Math.max(1, Number(template.canvas_size_width || 1920)); - var canvasHeight = Math.max(1, Number(template.canvas_size_height || 1080)); + var canvasSize = getPreviewCanvasDimensions(template); + var canvasWidth = canvasSize.width; + var canvasHeight = canvasSize.height; + currentPreviewCanvasWidth = canvasWidth; + currentPreviewCanvasHeight = canvasHeight; slidePreviewStage.style.aspectRatio = canvasWidth + ' / ' + canvasHeight; - slidePreviewMeta.textContent = template.name + ' • ' + canvasWidth + 'x' + canvasHeight; + slidePreviewStage.style.backgroundColor = template.background_color || '#111111'; + slidePreviewMeta.textContent = canvasWidth + 'x' + canvasHeight; if (!(template.regions || []).length) { slidePreviewEmpty.style.display = 'flex'; slidePreviewEmpty.textContent = 'This template has no regions.'; slidePreviewBackground.style.display = template.background_image_path ? 'block' : 'none'; slidePreviewBackground.src = template.background_image_path || ''; + slidePreviewCanvas.style.width = canvasWidth + 'px'; + slidePreviewCanvas.style.height = canvasHeight + 'px'; + slidePreviewCanvas.style.transform = ''; slidePreviewOverlay.innerHTML = ''; slidePreviewOverlay.style.width = ''; slidePreviewOverlay.style.height = ''; @@ -481,11 +700,21 @@ import { slidePreviewBackground.src = template.background_image_path || ''; var stageRect = slidePreviewStage.getBoundingClientRect(); + if (!stageRect.width || !stageRect.height) { + if (previewRenderFrame) { + cancelAnimationFrame(previewRenderFrame); + } + previewRenderFrame = requestAnimationFrame(function () { + previewRenderFrame = 0; + renderPreview(); + }); + return; + } var scale = Math.min(stageRect.width / canvasWidth, stageRect.height / canvasHeight) || 1; - slidePreviewOverlay.style.width = canvasWidth + 'px'; - slidePreviewOverlay.style.height = canvasHeight + 'px'; - slidePreviewOverlay.style.transform = 'scale(' + scale + ')'; - slidePreviewOverlay.style.transformOrigin = 'top left'; + slidePreviewCanvas.style.width = canvasWidth + 'px'; + slidePreviewCanvas.style.height = canvasHeight + 'px'; + slidePreviewCanvas.style.transform = 'translate3d(0, 0, 0) scale(' + scale + ')'; + slidePreviewCanvas.style.transformOrigin = 'top left'; var regions = template.regions || []; slidePreviewOverlay.innerHTML = regions.map(function (region) { var box = getRegionBox(region, canvasWidth, canvasHeight); @@ -525,79 +754,93 @@ import { : ' slide-preview-text-region'; return '
    ' + content + '
    '; }).join(''); + + syncPopupPreview(); } function renderTextRegion(region) { var current = getCurrentRegionValue(region); return '' + - '
    ' + - '
    ' + + '
    ' + + '
    ' + '' + escapeHtml(region.label) + '' + - 'Text' + + '
    ' + + '' + + 'Text' + + '
    ' + '
    ' + - '
    ' + - '' + + '
    ' + + '
    ' + + '' + + '
    ' + + '' + + '' + '
    ' + - '' + - '' + '
    '; } function renderWebpageRegion(region) { var current = getCurrentRegionValue(region); return '' + - '
    ' + - '
    ' + + '
    ' + + '
    ' + '' + escapeHtml(region.label) + '' + 'Webpage' + '
    ' + - '' + - '
    The webpage will be loaded in an iframe.
    ' + + '
    ' + + '' + + '
    The webpage will be loaded in an iframe.
    ' + + '
    ' + '
    '; } function renderHtmlRegion(region) { var current = getCurrentRegionValue(region); return '' + - '
    ' + - '
    ' + + '
    ' + + '
    ' + '' + escapeHtml(region.label) + '' + 'HTML' + '
    ' + - '' + - '
    HTML is rendered in a sandboxed iframe preview.
    ' + + '
    ' + + '' + + '
    HTML is rendered in a sandboxed iframe preview.
    ' + + '
    ' + '
    '; } function renderImageRegion(region) { var current = getCurrentRegionValue(region); return '' + - '
    ' + - '
    ' + + '
    ' + + '
    ' + '' + escapeHtml(region.label) + '' + 'Image' + '
    ' + - '' + - '' + - (current - ? '' - : '
    No image selected.
    ') + + '
    ' + + '' + + '' + + (current + ? '' + : '
    No image selected.
    ') + + '
    ' + '
    '; } function renderTemplate() { + templateSelectorLock.reset(); clearImagePreviewUrls(); destroyEditors(); var template = getTemplateById(templateSelect.value); if (!template) { templateFields.innerHTML = ''; - renderPreview(); + requestPreviewRender(); return; } @@ -712,14 +955,28 @@ import { if (hidden) { hidden.value = editor.getData(); } - renderPreview(); + templateSelectorLock.markEdited(); + requestPreviewRender(); }); - renderPreview(); + requestPreviewRender(); }).catch(function (error) { console.error('Failed to initialize CKEditor.', error); }); }); + templateFields.querySelectorAll('[data-toggle-editor-height]').forEach(function (button) { + button.addEventListener('click', function () { + var regionId = button.getAttribute('data-toggle-editor-height'); + var card = templateFields.querySelector('[data-region-id="' + regionId + '"]'); + if (!card) { + return; + } + + var expanded = card.classList.toggle('is-expanded'); + button.textContent = expanded ? 'Collapse' : 'Expand'; + }); + }); + templateFields.querySelectorAll('input[type="file"][name^="region_image_"]').forEach(function (input) { input.addEventListener('change', function () { if (input.dataset.previewUrl) { @@ -729,10 +986,14 @@ import { if (input.files && input.files.length) { input.dataset.previewUrl = URL.createObjectURL(input.files[0]); } - renderPreview(); + templateSelectorLock.markEdited(); + requestPreviewRender(); }); }); - renderPreview(); + window.requestAnimationFrame(function () { + templateSelectorLock.arm(); + }); + requestPreviewRender(); } slideForm.addEventListener('submit', async function (event) { @@ -740,6 +1001,9 @@ import { return; } event.preventDefault(); + var submitterValue = event.submitter && event.submitter.name === 'save_action' + ? String(event.submitter.value || '').trim().toLowerCase() + : ''; var saves = Array.prototype.map.call(templateFields.querySelectorAll('.ckeditor-holder'), function (holder) { var regionId = holder.getAttribute('data-region-id'); var editor = editorInstances.get(regionId); @@ -753,13 +1017,17 @@ import { submitting = true; try { await Promise.all(saves); + var formData = new FormData(slideForm); + if (event.submitter && event.submitter.name) { + formData.set(event.submitter.name, event.submitter.value || ''); + } var response = await fetch(slideForm.action, { method: (slideForm.method || 'POST').toUpperCase(), headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'text/html, application/json, text/plain, */*' }, - body: new FormData(slideForm), + body: formData, credentials: 'same-origin' }); @@ -767,6 +1035,14 @@ import { throw new Error(await response.text() || 'Unable to save slide.'); } + if (submitterValue === 'close' || submitterValue === 'new') { + var redirectUrl = submitterValue === 'close' + ? String(slideForm.dataset.asyncSaveCloseUrl || response.url || slideForm.action) + : String(slideForm.dataset.asyncSaveNewUrl || response.url || slideForm.action); + window.location.replace(redirectUrl); + return; + } + var responseText = await response.text(); var savedMessage = ''; try { @@ -779,19 +1055,53 @@ import { savedMessage = ''; } - showToast(savedMessage || 'Saved slide.'); - window.location.href = response.url || slideForm.action; + showToast(savedMessage || 'Saved slide.', 'success'); + slideForm.dataset.dirty = 'false'; } finally { submitting = false; } }); + slideForm.addEventListener('input', function () { + slideForm.dataset.dirty = 'true'; + }, true); + + slideForm.addEventListener('change', function () { + slideForm.dataset.dirty = 'true'; + }, true); + + if (openPreviewPopupButton) { + openPreviewPopupButton.addEventListener('click', function () { + openPreviewPopup(); + }); + } + templateSelect.addEventListener('change', renderTemplate); - templateFields.addEventListener('change', renderPreview); - templateFields.addEventListener('input', renderPreview); + templateFields.addEventListener('change', function () { + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); + templateFields.addEventListener('input', function () { + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); if (existingTemplateId) { templateSelect.value = String(existingTemplateId); } renderTemplate(); - window.addEventListener('resize', renderPreview); + if (window.ResizeObserver && slidePreviewStage) { + var previewResizeObserver = new ResizeObserver(function () { + requestPreviewRender(); + }); + previewResizeObserver.observe(slidePreviewStage); + } + requestSidebarSync(); + window.addEventListener('scroll', requestSidebarSync, { passive: true }); + window.addEventListener('resize', requestPreviewRender); + window.addEventListener('resize', requestSidebarSync); + window.addEventListener('beforeunload', function () { + if (previewPopupWindow && !previewPopupWindow.closed) { + previewPopupWindow.close(); + } + }); })(); diff --git a/src/web/public/js/slides/slide-form-template-lock.js b/src/web/public/js/slides/slide-form-template-lock.js new file mode 100644 index 0000000..c0e2099 --- /dev/null +++ b/src/web/public/js/slides/slide-form-template-lock.js @@ -0,0 +1,86 @@ +export function createTemplateSelectorLockController(templateSelect) { + var locked = false; + var armed = false; + var lockInput = null; + + function clearLockInput() { + if (lockInput && lockInput.parentNode) { + lockInput.parentNode.removeChild(lockInput); + } + lockInput = null; + } + + function reset() { + locked = false; + armed = false; + clearLockInput(); + if (!templateSelect) { + return; + } + + templateSelect.disabled = false; + templateSelect.removeAttribute('aria-disabled'); + templateSelect.removeAttribute('title'); + templateSelect.classList.remove('is-locked'); + } + + function arm() { + armed = true; + } + + function syncLockedValue() { + if (lockInput) { + lockInput.value = templateSelect.value; + } + } + + function lock() { + if (!templateSelect || locked) { + return; + } + + locked = true; + lockInput = lockInput || document.createElement('input'); + lockInput.type = 'hidden'; + lockInput.name = templateSelect.name; + lockInput.value = templateSelect.value; + templateSelect.insertAdjacentElement('afterend', lockInput); + templateSelect.disabled = true; + templateSelect.setAttribute('aria-disabled', 'true'); + templateSelect.setAttribute('title', 'Template is locked after you edit its content.'); + templateSelect.classList.add('is-locked'); + } + + function markEdited() { + if (!armed) { + return false; + } + + lock(); + syncLockedValue(); + return locked; + } + + function sync() { + if (!templateSelect) { + return false; + } + + if (locked) { + syncLockedValue(); + return true; + } + + return false; + } + + return { + reset: reset, + arm: arm, + markEdited: markEdited, + sync: sync, + isLocked: function () { + return locked; + } + }; +} diff --git a/src/web/public/js/slides/slide-form.js b/src/web/public/js/slides/slide-form.js new file mode 100644 index 0000000..efcc0d2 --- /dev/null +++ b/src/web/public/js/slides/slide-form.js @@ -0,0 +1,1107 @@ +import { + Alignment, + BlockQuote, + Bold, + ClassicEditor, + ClipboardPipeline, + Essentials, + FontBackgroundColor, + FontColor, + FontFamily, + FontSize, + Heading, + HorizontalLine, + Indent, + IndentBlock, + Italic, + InputTextView, + Plugin, + Paragraph, + Strikethrough, + Subscript, + Superscript, + Underline +} from '/assets/js/vendor/ckeditor5/ckeditor5.js'; +import { createTemplateSelectorLockController } from '/assets/js/slides/slide-form-template-lock.js'; + +(function () { + var dataElement = document.getElementById('slide-editor-data'); + if (!dataElement) { + return; + } + + var slideEditorData = {}; + try { + slideEditorData = JSON.parse(dataElement.getAttribute('data-json') || dataElement.textContent || '{}') || {}; + } catch (_error) { + slideEditorData = {}; + } + + var templates = Array.isArray(slideEditorData.templates) ? slideEditorData.templates : []; + var existingTemplateId = slideEditorData.existingTemplateId !== undefined ? slideEditorData.existingTemplateId : null; + var existingContent = slideEditorData.existingContent || {}; + var templateSelect = document.getElementById('template-select'); + var templateFields = document.getElementById('template-fields'); + var slideForm = document.getElementById('slide-form'); + var slideEditorShell = document.querySelector('.slide-editor-shell'); + var slideEditorSidebar = document.querySelector('.slide-editor-sidebar'); + var slidePreviewMeta = document.getElementById('slide-preview-meta'); + var slidePreviewStage = document.getElementById('slide-preview-stage'); + var slidePreviewCanvas = document.getElementById('slide-preview-canvas'); + var slidePreviewBackground = document.getElementById('slide-preview-background'); + var slidePreviewEmpty = document.getElementById('slide-preview-empty'); + var slidePreviewOverlay = document.getElementById('slide-preview-overlay'); + var openPreviewPopupButton = document.getElementById('open-preview-popup'); + var editorInstances = new Map(); + var submitting = false; + var previewRenderFrame = 0; + var previewPopupWindow = null; + var previewPopupRenderFrame = 0; + var currentPreviewCanvasWidth = 0; + var currentPreviewCanvasHeight = 0; + var sidebarSyncFrame = 0; + var sidebarTopOffset = 16; + var templateSelectorLock = createTemplateSelectorLockController(templateSelect); + + class FontSizeInputUI extends Plugin { + static get pluginName() { + return 'FontSizeInputUI'; + } + + init() { + var editor = this.editor; + var fontSizeCommand = editor.commands.get('fontSize'); + var plugin = this; + + if (!fontSizeCommand) { + return; + } + + editor.ui.componentFactory.add('fontSizeInput', function (locale) { + var view = new InputTextView(locale); + + view.extendTemplate({ + attributes: { + class: ['ck-font-size-input'] + } + }); + + view.set({ + placeholder: 'Font size', + ariaLabel: 'Font size' + }); + + function getCurrentFontSizeValue() { + var value = fontSizeCommand.value; + if (value === null || value === undefined || value === '') { + return ''; + } + + var parsed = Math.round(Number(String(value).replace(/[^0-9.]/g, ''))); + return Number.isFinite(parsed) && parsed > 0 ? String(parsed) : ''; + } + + function syncValue() { + if (view.element && document.activeElement === view.element) { + return; + } + + view.value = getCurrentFontSizeValue(); + } + + view.on('render', function () { + if (!view.element) { + return; + } + + view.element.type = 'text'; + view.element.inputMode = 'numeric'; + view.element.autocomplete = 'off'; + view.element.spellcheck = false; + syncValue(); + }); + + function applyValue() { + if (!view.element) { + return; + } + + var size = Math.max(1, Math.round(Number(view.element.value || 0))); + if (!size) { + return; + } + + editor.execute('fontSize', { value: size + 'px' }); + } + + view.on('input', applyValue); + view.on('blur', applyValue); + + view.on('keydown', function (_eventInfo, domEvent) { + if (domEvent.key === 'Enter') { + domEvent.preventDefault(); + if (view.element) { + view.element.blur(); + } + } + }); + + plugin.listenTo(editor.model.document.selection, 'change:range', syncValue); + plugin.listenTo(fontSizeCommand, 'change:value', syncValue); + + syncValue(); + + return view; + }); + } + } + + class ForcePlainTextPaste extends Plugin { + static get pluginName() { + return 'ForcePlainTextPaste'; + } + + static get requires() { + return [ClipboardPipeline]; + } + + init() { + var editor = this.editor; + var clipboardPipeline = editor.plugins.get(ClipboardPipeline); + + this.listenTo(clipboardPipeline, 'inputTransformation', function (_event, data) { + var plainText = data.dataTransfer.getData('text/plain'); + data.content = editor.data.processor.toView(plainTextToHtml(plainText)); + }, { priority: 'high' }); + } + } + + function escapeHtml(value) { + return String(value ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function plainTextToHtml(value) { + var lines = String(value ?? '').replace(/\r\n?/g, '\n').split('\n'); + var paragraphs = []; + var currentParagraph = []; + + lines.forEach(function (line) { + if (line === '') { + if (currentParagraph.length) { + paragraphs.push('

    ' + currentParagraph.join('
    ') + '

    '); + currentParagraph = []; + } else { + paragraphs.push('

    '); + } + return; + } + + currentParagraph.push(escapeHtml(line)); + }); + + if (currentParagraph.length) { + paragraphs.push('

    ' + currentParagraph.join('
    ') + '

    '); + } + + return paragraphs.length ? paragraphs.join('') : '

    '; + } + + function getTemplateById(id) { + return templates.find(function (item) { return Number(item.id) === Number(id); }) || null; + } + + function getCurrentRegionValue(region) { + var current = existingContent[region.region_key]; + return current && current.value !== undefined ? current.value : ''; + } + + function normalizeEditorData(value) { + return String(value || ''); + } + + function requestPreviewRender() { + if (previewRenderFrame) { + return; + } + + previewRenderFrame = window.requestAnimationFrame(function () { + previewRenderFrame = 0; + renderPreview(); + }); + } + + function getTemplateFieldControls() { + return templateFields ? templateFields.querySelectorAll('input, textarea, select') : []; + } + + function sanitizePreviewHtml(html) { + var output = String(html || ''); + output = output.replace(//gi, ''); + output = output.replace(//gi, ''); + return output.replace(/<[^>]+>/g, function (tag) { + var match = tag.match(/^<\s*(\/?)\s*([a-z0-9]+)([\s\S]*?)(\/?)>$/i); + if (!match) { + return ''; + } + var closing = Boolean(match[1]); + var name = String(match[2] || '').toLowerCase(); + var attrText = String(match[3] || ''); + var selfClosing = Boolean(match[4]) || name === 'br' || name === 'hr'; + var allowed = ['a', 'b', 'blockquote', 'br', 'code', 'div', 'em', 'figure', 'figcaption', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'li', 'ol', 'p', 'pre', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'u', 'ul']; + if (allowed.indexOf(name) === -1) { + return ''; + } + if (closing) { + return ''; + } + if (selfClosing) { + return '<' + name + sanitizeTagAttributes(name, attrText) + '>'; + } + return '<' + name + sanitizeTagAttributes(name, attrText) + '>'; + }); + } + + function sanitizeTagAttributes(tagName, attrText) { + var allowedAttributes = { + a: ['href', 'title', 'target', 'rel', 'class', 'style'], + blockquote: ['class', 'style'], + div: ['class', 'style'], + figure: ['class', 'style'], + figcaption: ['class', 'style'], + h1: ['class', 'style'], + h2: ['class', 'style'], + h3: ['class', 'style'], + h4: ['class', 'style'], + h5: ['class', 'style'], + h6: ['class', 'style'], + li: ['class', 'style'], + ol: ['class', 'style', 'start'], + p: ['class', 'style'], + pre: ['class', 'style'], + span: ['class', 'style'], + table: ['class', 'style'], + td: ['class', 'style', 'colspan', 'rowspan'], + th: ['class', 'style', 'colspan', 'rowspan', 'scope'], + tr: ['class', 'style'], + ul: ['class', 'style'] + }; + var allowed = allowedAttributes[tagName] || []; + if (!allowed.length) { + return ''; + } + + var attrs = []; + attrText.replace(/([a-zA-Z0-9:-]+)(?:\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>/=`]+)))?/g, function (_full, key, _valuePart, doubleQuoted, singleQuoted, bareValue) { + var lowerKey = String(key || '').toLowerCase(); + if (allowed.indexOf(lowerKey) === -1) { + return ''; + } + var value = doubleQuoted !== undefined ? doubleQuoted : singleQuoted !== undefined ? singleQuoted : bareValue !== undefined ? bareValue : ''; + if (lowerKey === 'href' && /^(?:\s*javascript:|\s*data:)/i.test(String(value || ''))) { + return ''; + } + if (lowerKey === 'style' && /(?:expression\s*\(|javascript:|url\s*\()/i.test(String(value || ''))) { + return ''; + } + if (lowerKey === 'target') { + var targetValue = String(value || '').trim(); + if (targetValue === '_blank') { + attrs.push(' target="_blank"'); + if (attrs.indexOf(' rel="noreferrer noopener"') === -1) { + attrs.push(' rel="noreferrer noopener"'); + } + return ''; + } + } + attrs.push(' ' + lowerKey + '="' + escapeHtml(value) + '"'); + return ''; + }); + + return attrs.join(''); + } + + function renderPreviewListItem(item, tag) { + if (item && typeof item === 'object') { + var content = item.content !== undefined ? item.content : (item.text !== undefined ? item.text : item.value !== undefined ? item.value : ''); + var children = Array.isArray(item.items) ? item.items : Array.isArray(item.subItems) ? item.subItems : Array.isArray(item.children) ? item.children : []; + var nested = children.length ? '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + children.map(function (child) { return renderPreviewListItem(child, tag); }).join('') + '' : ''; + return '
  • ' + sanitizePreviewHtml(content || '') + nested + '
  • '; + } + return '
  • ' + sanitizePreviewHtml(item || '') + '
  • '; + } + + function renderPreviewTable(data) { + var rows = Array.isArray(data.content) ? data.content : Array.isArray(data.rows) ? data.rows : []; + if (!rows.length) { + return ''; + } + var hasHeadings = Boolean(data.withHeadings); + var body = rows.map(function (row, rowIndex) { + var cells = Array.isArray(row) ? row : []; + var cellTag = hasHeadings && rowIndex === 0 ? 'th' : 'td'; + var cellAttrs = cellTag === 'th' ? ' scope="col"' : ''; + return '' + cells.map(function (cell) { + return '<' + cellTag + cellAttrs + '>' + sanitizePreviewHtml(cell || '') + ''; + }).join('') + ''; + }).join(''); + return '' + body + '
    '; + } + + function renderPreviewBlock(block) { + if (!block || !block.type || !block.data) { + return ''; + } + if (block.type === 'header') { + var level = Math.max(1, Math.min(6, Number(block.data.level || 2))); + return '' + sanitizePreviewHtml(block.data.text || '') + ''; + } + if (block.type === 'list') { + var tag = block.data.style === 'ordered' ? 'ol' : 'ul'; + var items = Array.isArray(block.data.items) ? block.data.items : []; + return '<' + tag + ' style="list-style-type:' + (tag === 'ol' ? 'decimal' : 'disc') + ';padding-left:1.4em;">' + items.map(function (item) { return renderPreviewListItem(item, tag); }).join('') + ''; + } + if (block.type === 'delimiter') { + return '
    '; + } + if (block.type === 'code') { + return '
    ' + sanitizePreviewHtml(block.data.code || '') + '
    '; + } + if (block.type === 'table') { + return renderPreviewTable(block.data); + } + if (block.type === 'paragraph') { + return '

    ' + sanitizePreviewHtml(block.data.text || '') + '

    '; + } + return ''; + } + + function renderPreviewText(value) { + var raw = String(value || ''); + if (!raw) { + return '
    Empty text
    '; + } + return sanitizePreviewHtml(raw); + } + + function renderPreviewTextRegion(region, value, style, scale) { + var fontFamily = style.font_family ? 'font-family:' + escapeHtml(style.font_family) + ';' : ''; + var color = style.font_color ? 'color:' + escapeHtml(style.font_color) + ';' : ''; + var fontSize = style.font_size ? 'font-size:' + Math.max(1, Math.round(Number(style.font_size))) + 'px;' : ''; + var width = Math.max(1, Math.round(Number(region && region.width ? region.width : 0) || 1)); + var height = Math.max(1, Math.round(Number(region && region.height ? region.height : 0) || 1)); + var wrapperStyle = 'width:' + width + 'px;height:' + height + 'px;overflow:hidden;' + fontFamily + fontSize + color; + return '
    ' + renderPreviewText(value) + '
    '; + } + + function renderPreviewWebpageRegion(value) { + var src = String(value || '').trim(); + if (!src) { + return '
    Webpage
    '; + } + return ''; + } + + function renderPreviewHtmlRegion(value) { + var html = String(value || '').trim(); + if (!html) { + return '
    HTML
    '; + } + return ''; + } + + function destroyEditors() { + editorInstances.forEach(function (editor) { + if (editor && typeof editor.destroy === 'function') { + editor.destroy(); + } + }); + editorInstances.clear(); + } + + function getEditorHiddenInput(regionId) { + var card = templateFields.querySelector('[data-region-id="' + regionId + '"]'); + return card ? card.querySelector('input[type="hidden"][name="region_text_' + regionId + '"]') : null; + } + + function getEditorFontSizeHiddenInput(regionId) { + var card = templateFields.querySelector('[data-region-id="' + regionId + '"]'); + return card ? card.querySelector('input[name="region_font_size_' + regionId + '"]') : null; + } + + function normalizeFontSizeValue(value) { + var size = Math.max(1, Math.round(Number(String(value || '').replace(/[^0-9.]/g, '')))); + return size ? String(size) : ''; + } + + function getCurrentTextStyle(region) { + var current = existingContent[region.region_key] || {}; + return { + font_family: String(current.font_family || region.font_family || 'Arial').trim() || 'Arial', + font_size: Math.max(8, Number(current.font_size || 24)), + font_color: String(current.font_color || region.font_color || '#000000').trim() || '#000000' + }; + } + + function getTextStyleFromCard(_card, region) { + return getCurrentTextStyle(region); + } + + function getSelectedTemplate() { + return templates.find(function (item) { return Number(item.id) === Number(templateSelect.value); }) || null; + } + + function clearImagePreviewUrls() { + templateFields.querySelectorAll('input[type="file"][name^="region_image_"]').forEach(function (input) { + if (input.dataset.previewUrl) { + URL.revokeObjectURL(input.dataset.previewUrl); + delete input.dataset.previewUrl; + } + }); + } + + function getRegionBox(region, canvasWidth, canvasHeight) { + return { + left: Math.max(0, Math.round(Number(region.x || 0))), + top: Math.max(0, Math.round(Number(region.y || 0))), + width: Math.max(1, Math.round(Number(region.width || 0) || 1)), + height: Math.max(1, Math.round(Number(region.height || 0) || 1)) + }; + } + + function getPreviewCanvasDimensions(template) { + return { + width: Math.max(1, Number(template && template.canvas_size_width ? template.canvas_size_width : 1920)), + height: Math.max(1, Number(template && template.canvas_size_height ? template.canvas_size_height : 1080)) + }; + } + + function buildPreviewPopupHtml() { + return '' + + '' + + '' + + '' + + '' + + 'Slide preview' + + '' + + '' + + '' + + '' + + '' + + ''; + } + + function syncPopupPreview() { + if (!previewPopupWindow || previewPopupWindow.closed) { + previewPopupWindow = null; + return; + } + + var popupDocument = previewPopupWindow.document; + if (!popupDocument) { + return; + } + + var popupStage = popupDocument.getElementById('popup-preview-stage'); + var popupCanvas = popupDocument.getElementById('popup-preview-canvas'); + var template = getSelectedTemplate(); + + if (!popupStage || !popupCanvas) { + if (previewPopupRenderFrame) { + cancelAnimationFrame(previewPopupRenderFrame); + } + previewPopupRenderFrame = requestAnimationFrame(syncPopupPreview); + return; + } + + if (!template) { + popupStage.style.backgroundColor = '#111111'; + popupCanvas.style.width = ''; + popupCanvas.style.height = ''; + popupCanvas.style.transform = ''; + popupCanvas.innerHTML = slidePreviewCanvas.innerHTML; + var popupEmpty = popupCanvas.querySelector('#slide-preview-empty'); + var popupOverlay = popupCanvas.querySelector('#slide-preview-overlay'); + var popupBackground = popupCanvas.querySelector('#slide-preview-background'); + if (popupBackground) { + popupBackground.style.display = 'none'; + } + if (popupEmpty) { + popupEmpty.style.display = 'flex'; + popupEmpty.textContent = 'Select a template to preview the slide.'; + } + if (popupOverlay) { + popupOverlay.innerHTML = ''; + } + return; + } + + var canvasWidth = currentPreviewCanvasWidth || Math.max(1, Number(template.canvas_size_width || 1920)); + var canvasHeight = currentPreviewCanvasHeight || Math.max(1, Number(template.canvas_size_height || 1080)); + popupStage.style.backgroundColor = template.background_color || '#111111'; + popupCanvas.style.width = canvasWidth + 'px'; + popupCanvas.style.height = canvasHeight + 'px'; + popupCanvas.innerHTML = slidePreviewCanvas.innerHTML; + var popupBackground = popupCanvas.querySelector('#slide-preview-background'); + var popupEmpty = popupCanvas.querySelector('#slide-preview-empty'); + var popupOverlay = popupCanvas.querySelector('#slide-preview-overlay'); + + if (popupBackground) { + popupBackground.style.display = template.background_image_path ? 'block' : 'none'; + popupBackground.src = template.background_image_path || ''; + } + if (popupEmpty) { + popupEmpty.style.display = 'none'; + } + + var stageRect = popupStage.getBoundingClientRect(); + if (!stageRect.width || !stageRect.height) { + if (previewPopupRenderFrame) { + cancelAnimationFrame(previewPopupRenderFrame); + } + previewPopupRenderFrame = requestAnimationFrame(syncPopupPreview); + return; + } + + var scale = Math.min(stageRect.width / canvasWidth, stageRect.height / canvasHeight) || 1; + popupCanvas.style.transform = 'translate3d(0, 0, 0) scale(' + scale + ')'; + } + + function openPreviewPopup() { + if (previewPopupWindow && !previewPopupWindow.closed) { + previewPopupWindow.focus(); + syncPopupPreview(); + return; + } + + var popupWidth = 1280; + var popupHeight = 900; + var left = Math.max(0, Math.round((window.screen.width - popupWidth) / 2)); + var top = Math.max(0, Math.round((window.screen.height - popupHeight) / 2)); + var popupFeatures = [ + 'popup=yes', + 'toolbar=no', + 'location=no', + 'menubar=no', + 'directories=no', + 'status=no', + 'scrollbars=yes', + 'resizable=yes', + 'width=' + popupWidth, + 'height=' + popupHeight, + 'left=' + left, + 'top=' + top + ].join(','); + + previewPopupWindow = window.open('', 'slide-preview-popup', popupFeatures); + if (!previewPopupWindow) { + return; + } + + previewPopupWindow.document.open(); + previewPopupWindow.document.write(buildPreviewPopupHtml()); + previewPopupWindow.document.close(); + previewPopupWindow.addEventListener('resize', syncPopupPreview); + previewPopupWindow.focus(); + syncPopupPreview(); + } + + function syncSlideEditorSidebar() { + sidebarSyncFrame = 0; + + if (!slideEditorShell || !slideEditorSidebar) { + return; + } + + if (window.matchMedia && window.matchMedia('(max-width: 1199.98px)').matches) { + slideEditorSidebar.style.transform = ''; + return; + } + + var shellRect = slideEditorShell.getBoundingClientRect(); + var sidebarHeight = slideEditorSidebar.offsetHeight; + var shellTop = window.scrollY + shellRect.top; + var shellBottom = shellTop + slideEditorShell.offsetHeight; + var maxTranslate = Math.max(0, shellBottom - shellTop - sidebarHeight - sidebarTopOffset); + var desiredTranslate = Math.max(0, Math.min(window.scrollY + sidebarTopOffset - shellTop, maxTranslate)); + + slideEditorSidebar.style.transform = desiredTranslate ? 'translate3d(0, ' + desiredTranslate + 'px, 0)' : ''; + } + + function requestSidebarSync() { + if (sidebarSyncFrame) { + return; + } + + sidebarSyncFrame = window.requestAnimationFrame(syncSlideEditorSidebar); + } + + function renderPreview() { + var template = getSelectedTemplate(); + if (!template) { + slidePreviewMeta.textContent = '--'; + slidePreviewBackground.style.display = 'none'; + slidePreviewEmpty.style.display = 'flex'; + slidePreviewEmpty.textContent = 'Select a template to preview the slide.'; + slidePreviewCanvas.style.width = ''; + slidePreviewCanvas.style.height = ''; + slidePreviewOverlay.innerHTML = ''; + slidePreviewOverlay.style.width = ''; + slidePreviewOverlay.style.height = ''; + slidePreviewOverlay.style.transform = ''; + slidePreviewStage.style.aspectRatio = '16 / 9'; + slidePreviewStage.style.backgroundColor = '#111111'; + return; + } + + var canvasSize = getPreviewCanvasDimensions(template); + var canvasWidth = canvasSize.width; + var canvasHeight = canvasSize.height; + currentPreviewCanvasWidth = canvasWidth; + currentPreviewCanvasHeight = canvasHeight; + slidePreviewStage.style.aspectRatio = canvasWidth + ' / ' + canvasHeight; + slidePreviewStage.style.backgroundColor = template.background_color || '#111111'; + slidePreviewMeta.textContent = canvasWidth + 'x' + canvasHeight; + if (!(template.regions || []).length) { + slidePreviewEmpty.style.display = 'flex'; + slidePreviewEmpty.textContent = 'This template has no regions.'; + slidePreviewBackground.style.display = template.background_image_path ? 'block' : 'none'; + slidePreviewBackground.src = template.background_image_path || ''; + slidePreviewCanvas.style.width = canvasWidth + 'px'; + slidePreviewCanvas.style.height = canvasHeight + 'px'; + slidePreviewCanvas.style.transform = ''; + slidePreviewOverlay.innerHTML = ''; + slidePreviewOverlay.style.width = ''; + slidePreviewOverlay.style.height = ''; + slidePreviewOverlay.style.transform = ''; + return; + } + + slidePreviewEmpty.style.display = 'none'; + slidePreviewBackground.style.display = template.background_image_path ? 'block' : 'none'; + slidePreviewBackground.src = template.background_image_path || ''; + + var stageRect = slidePreviewStage.getBoundingClientRect(); + if (!stageRect.width || !stageRect.height) { + if (previewRenderFrame) { + cancelAnimationFrame(previewRenderFrame); + } + previewRenderFrame = requestAnimationFrame(function () { + previewRenderFrame = 0; + renderPreview(); + }); + return; + } + var scale = Math.min(stageRect.width / canvasWidth, stageRect.height / canvasHeight) || 1; + slidePreviewCanvas.style.width = canvasWidth + 'px'; + slidePreviewCanvas.style.height = canvasHeight + 'px'; + slidePreviewCanvas.style.transform = 'translate3d(0, 0, 0) scale(' + scale + ')'; + slidePreviewCanvas.style.transformOrigin = 'top left'; + var regions = template.regions || []; + slidePreviewOverlay.innerHTML = regions.map(function (region) { + var box = getRegionBox(region, canvasWidth, canvasHeight); + var card = templateFields.querySelector('[data-region-id="' + region.id + '"]'); + var hiddenInput = card && card.querySelector('input[type="hidden"][name="region_text_' + region.id + '"]'); + var htmlInput = card && card.querySelector('textarea[name="region_html_' + region.id + '"]'); + var imageHidden = card && card.querySelector('input[type="hidden"][name="existing_region_image_' + region.id + '"]'); + var imageFileInput = card && card.querySelector('input[type="file"][name="region_image_' + region.id + '"]'); + var webpageInput = card && card.querySelector('input[type="url"][name="region_webpage_' + region.id + '"]'); + var value = region.region_type === 'image' + ? ((imageFileInput && imageFileInput.dataset.previewUrl) ? imageFileInput.dataset.previewUrl : (imageHidden ? imageHidden.value : '')) + : region.region_type === 'webpage' + ? (webpageInput ? webpageInput.value : '') + : region.region_type === 'html' + ? (htmlInput ? htmlInput.value : '') + : (hiddenInput ? hiddenInput.value : ''); + var style = region.region_type === 'image' + ? null + : region.region_type === 'webpage' + ? null + : region.region_type === 'html' + ? null + : getTextStyleFromCard(card, region); + var content = region.region_type === 'image' + ? (value ? '' : '
    Image
    ') + : region.region_type === 'webpage' + ? renderPreviewWebpageRegion(value) + : region.region_type === 'html' + ? renderPreviewHtmlRegion(value) + : renderPreviewTextRegion(region, value, style, scale); + var selected = region.region_type === 'image' + ? ' slide-preview-image-region' + : region.region_type === 'webpage' + ? ' slide-preview-webpage-region' + : region.region_type === 'html' + ? ' slide-preview-html-region' + : ' slide-preview-text-region'; + return '
    ' + content + '
    '; + }).join(''); + + syncPopupPreview(); + } + + function renderTextRegion(region) { + var current = getCurrentRegionValue(region); + return '' + + '
    ' + + '
    ' + + '' + escapeHtml(region.label) + '' + + '
    ' + + '' + + 'Text' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + '' + + '' + + '
    ' + + '
    '; + } + + function renderWebpageRegion(region) { + var current = getCurrentRegionValue(region); + return '' + + '
    ' + + '
    ' + + '' + escapeHtml(region.label) + '' + + 'Webpage' + + '
    ' + + '
    ' + + '' + + '
    The webpage will be loaded in an iframe.
    ' + + '
    ' + + '
    '; + } + + function renderHtmlRegion(region) { + var current = getCurrentRegionValue(region); + return '' + + '
    ' + + '
    ' + + '' + escapeHtml(region.label) + '' + + 'HTML' + + '
    ' + + '
    ' + + '' + + '
    HTML is rendered in a sandboxed iframe preview.
    ' + + '
    ' + + '
    '; + } + + function renderImageRegion(region) { + var current = getCurrentRegionValue(region); + return '' + + '
    ' + + '
    ' + + '' + escapeHtml(region.label) + '' + + 'Image' + + '
    ' + + '
    ' + + '' + + '' + + (current + ? '' + : '
    No image selected.
    ') + + '
    ' + + '
    '; + } + + function renderTemplate() { + templateSelectorLock.reset(); + clearImagePreviewUrls(); + destroyEditors(); + var template = getTemplateById(templateSelect.value); + if (!template) { + templateFields.innerHTML = ''; + requestPreviewRender(); + return; + } + + templateFields.innerHTML = template.regions.length ? template.regions.map(function (region) { + if (region.region_type === 'image') { + return renderImageRegion(region); + } + if (region.region_type === 'webpage') { + return renderWebpageRegion(region); + } + if (region.region_type === 'html') { + return renderHtmlRegion(region); + } + return renderTextRegion(region); + }).join('') : '
    This template has no regions.
    '; + + templateFields.querySelectorAll('.ckeditor-holder').forEach(function (holder) { + var regionId = holder.getAttribute('data-region-id'); + var source = holder.querySelector('.ckeditor-source'); + var hidden = getEditorHiddenInput(regionId); + var editorConfig = { + licenseKey: 'GPL', + placeholder: 'Write content...', + toolbar: { + items: [ + 'undo', + 'redo', + '|', + 'heading', + '|', + 'fontSizeInput', + 'fontFamily', + 'fontColor', + 'fontBackgroundColor', + '|', + 'bold', + 'italic', + 'underline', + 'strikethrough', + 'subscript', + 'superscript', + '|', + 'horizontalLine', + 'blockQuote', + '|', + 'alignment', + '|', + 'outdent', + 'indent' + ], + shouldNotGroupWhenFull: false + }, + plugins: [ + Alignment, + BlockQuote, + Bold, + Essentials, + ForcePlainTextPaste, + FontBackgroundColor, + FontColor, + FontFamily, + FontSize, + FontSizeInputUI, + Heading, + HorizontalLine, + Indent, + IndentBlock, + Italic, + Paragraph, + Strikethrough, + Subscript, + Superscript, + Underline + ], + fontFamily: { + supportAllValues: true + }, + fontSize: { + options: [20, 24, 28, 32, 36, 40, 44], + supportAllValues: true + }, + heading: { + options: [ + { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' }, + { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' }, + { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }, + { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' }, + { model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' } + ] + }, + initialData: normalizeEditorData((source && source.value) || (hidden ? hidden.value : '')) + }; + + ClassicEditor.create(source || holder, editorConfig).then(function (editor) { + editorInstances.set(regionId, editor); + var fontSizeHidden = getEditorFontSizeHiddenInput(regionId); + var fontSizeCommand = editor.commands.get('fontSize'); + if (hidden) { + hidden.value = editor.getData(); + } + if (fontSizeHidden && fontSizeCommand) { + fontSizeHidden.value = normalizeFontSizeValue(fontSizeCommand.value) || fontSizeHidden.value; + fontSizeCommand.on('change:value', function () { + fontSizeHidden.value = normalizeFontSizeValue(fontSizeCommand.value) || fontSizeHidden.value; + }); + } + editor.model.document.on('change:data', function () { + var instance = editorInstances.get(regionId); + if (instance !== editor) { + return; + } + if (hidden) { + hidden.value = editor.getData(); + } + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); + requestPreviewRender(); + }).catch(function (error) { + console.error('Failed to initialize CKEditor.', error); + }); + }); + + templateFields.querySelectorAll('[data-toggle-editor-height]').forEach(function (button) { + button.addEventListener('click', function () { + var regionId = button.getAttribute('data-toggle-editor-height'); + var card = templateFields.querySelector('[data-region-id="' + regionId + '"]'); + if (!card) { + return; + } + + var expanded = card.classList.toggle('is-expanded'); + button.textContent = expanded ? 'Collapse' : 'Expand'; + }); + }); + + templateFields.querySelectorAll('input[type="file"][name^="region_image_"]').forEach(function (input) { + input.addEventListener('change', function () { + if (input.dataset.previewUrl) { + URL.revokeObjectURL(input.dataset.previewUrl); + delete input.dataset.previewUrl; + } + if (input.files && input.files.length) { + input.dataset.previewUrl = URL.createObjectURL(input.files[0]); + } + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); + }); + window.requestAnimationFrame(function () { + templateSelectorLock.arm(); + }); + requestPreviewRender(); + } + + slideForm.addEventListener('submit', async function (event) { + if (submitting) { + return; + } + event.preventDefault(); + var submitterValue = event.submitter && event.submitter.name === 'save_action' + ? String(event.submitter.value || '').trim().toLowerCase() + : ''; + var saves = Array.prototype.map.call(templateFields.querySelectorAll('.ckeditor-holder'), function (holder) { + var regionId = holder.getAttribute('data-region-id'); + var editor = editorInstances.get(regionId); + var hidden = getEditorHiddenInput(regionId); + if (!editor || !hidden) { + return Promise.resolve(); + } + hidden.value = editor.getData(); + return Promise.resolve(); + }); + submitting = true; + try { + await Promise.all(saves); + var formData = new FormData(slideForm); + if (event.submitter && event.submitter.name) { + formData.set(event.submitter.name, event.submitter.value || ''); + } + var response = await fetch(slideForm.action, { + method: (slideForm.method || 'POST').toUpperCase(), + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'text/html, application/json, text/plain, */*' + }, + body: formData, + credentials: 'same-origin' + }); + + if (!response.ok) { + throw new Error(await response.text() || 'Unable to save slide.'); + } + + if (submitterValue === 'close' || submitterValue === 'new') { + var redirectUrl = submitterValue === 'close' + ? String(slideForm.dataset.asyncSaveCloseUrl || response.url || slideForm.action) + : String(slideForm.dataset.asyncSaveNewUrl || response.url || slideForm.action); + window.location.replace(redirectUrl); + return; + } + + var responseText = await response.text(); + var savedMessage = ''; + try { + var doc = new DOMParser().parseFromString(responseText || '', 'text/html'); + var toastBody = doc.querySelector('.toast-body'); + if (toastBody && toastBody.textContent) { + savedMessage = toastBody.textContent.trim(); + } + } catch (_error) { + savedMessage = ''; + } + + showToast(savedMessage || 'Saved slide.', 'success'); + slideForm.dataset.dirty = 'false'; + } finally { + submitting = false; + } + }); + + slideForm.addEventListener('input', function () { + slideForm.dataset.dirty = 'true'; + }, true); + + slideForm.addEventListener('change', function () { + slideForm.dataset.dirty = 'true'; + }, true); + + if (openPreviewPopupButton) { + openPreviewPopupButton.addEventListener('click', function () { + openPreviewPopup(); + }); + } + + templateSelect.addEventListener('change', renderTemplate); + templateFields.addEventListener('change', function () { + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); + templateFields.addEventListener('input', function () { + templateSelectorLock.markEdited(); + requestPreviewRender(); + }); + if (existingTemplateId) { + templateSelect.value = String(existingTemplateId); + } + renderTemplate(); + if (window.ResizeObserver && slidePreviewStage) { + var previewResizeObserver = new ResizeObserver(function () { + requestPreviewRender(); + }); + previewResizeObserver.observe(slidePreviewStage); + } + requestSidebarSync(); + window.addEventListener('scroll', requestSidebarSync, { passive: true }); + window.addEventListener('resize', requestPreviewRender); + window.addEventListener('resize', requestSidebarSync); + window.addEventListener('beforeunload', function () { + if (previewPopupWindow && !previewPopupWindow.closed) { + previewPopupWindow.close(); + } + }); +})(); diff --git a/src/web/public/js/system-status.js b/src/web/public/js/system-status.js index 22c95d0..c908768 100644 --- a/src/web/public/js/system-status.js +++ b/src/web/public/js/system-status.js @@ -64,8 +64,10 @@ socket.onmessage = function (event) { try { var payload = JSON.parse(String(event.data || '{}')); - if (payload && payload.type === 'dashboard-state' && typeof window.webHandleDashboardState === 'function') { - window.webHandleDashboardState(payload.state); + if (payload && payload.type === 'dashboard-state') { + if (typeof window.webHandleDashboardState === 'function') { + window.webHandleDashboardState(payload.state); + } updateSidebarStatus(Boolean(payload.state && payload.state.playerServiceConnected), 'Live player feed'); } } catch (_error) { diff --git a/src/web/public/js/table-sort.js b/src/web/public/js/table-sort.js index 3cc135f..92da331 100644 --- a/src/web/public/js/table-sort.js +++ b/src/web/public/js/table-sort.js @@ -69,6 +69,45 @@ return table._sortableState; } + function ensureSortableHeaderIndicator(headerCell) { + var indicator = headerCell.querySelector && headerCell.querySelector('.table-sort-indicator'); + if (indicator) { + return indicator; + } + + indicator = document.createElement('i'); + indicator.className = 'table-sort-indicator bi bi-arrow-down-up ms-1'; + indicator.setAttribute('aria-hidden', 'true'); + headerCell.appendChild(indicator); + return indicator; + } + + function updateSortableHeaderIndicator(headerCell, isSortable, isActive, direction) { + if (!isSortable) { + var hiddenIndicator = headerCell.querySelector && headerCell.querySelector('.table-sort-indicator'); + if (hiddenIndicator) { + hiddenIndicator.style.display = 'none'; + } + return; + } + + var indicator = ensureSortableHeaderIndicator(headerCell); + indicator.style.display = ''; + indicator.className = 'table-sort-indicator bi ms-1'; + + if (isActive && direction === 'desc') { + indicator.classList.add('bi-caret-down-fill'); + return; + } + + if (isActive && direction === 'asc') { + indicator.classList.add('bi-caret-up-fill'); + return; + } + + indicator.classList.add('bi-arrow-down-up'); + } + function isSortableTableColumn(table, columnIndex) { var headerCell = table.tHead && table.tHead.rows && table.tHead.rows.length ? table.tHead.rows[0].cells[columnIndex] : null; if (!headerCell) { @@ -100,13 +139,15 @@ if (!headerCell) { return; } + var sortable = isSortableTableColumn(table, index); headerCell.classList.remove('sort-asc', 'sort-desc', 'sortable', 'unsortable'); headerCell.removeAttribute('aria-sort'); headerCell.removeAttribute('role'); headerCell.removeAttribute('tabindex'); - if (isSortableTableColumn(table, index)) { + if (sortable) { headerCell.classList.add('sortable'); + updateSortableHeaderIndicator(headerCell, true, state.columnIndex === index, state.direction); headerCell.setAttribute('role', 'button'); headerCell.setAttribute('tabindex', '0'); if (state.columnIndex === index) { @@ -117,6 +158,7 @@ } } else { headerCell.classList.add('unsortable'); + updateSortableHeaderIndicator(headerCell, false); } }); } @@ -168,6 +210,8 @@ return; } + ensureSortableHeaderIndicator(headerCell); + headerCell.addEventListener('click', function () { var state = getSortableTableState(table); var nextDirection = state.columnIndex === index && state.direction === 'asc' ? 'desc' : 'asc'; diff --git a/src/web/public/js/template-designer.js b/src/web/public/js/template-designer.js index 60c1d3b..bd07748 100644 --- a/src/web/public/js/template-designer.js +++ b/src/web/public/js/template-designer.js @@ -4,6 +4,8 @@ return; } + var utils = window.templateDesignerUtils || {}; + var templateData = {}; try { templateData = JSON.parse(dataElement.getAttribute('data-json') || dataElement.textContent || '{}') || {}; @@ -24,27 +26,26 @@ var canvasWidthInput = document.getElementById('canvas-width'); var canvasHeightInput = document.getElementById('canvas-height'); var backgroundInput = document.getElementById('background-image'); + var backgroundColorInput = document.getElementById('background-color'); var backgroundPreview = document.getElementById('background-preview'); var backgroundEmpty = document.getElementById('background-empty'); var removeBackgroundButton = document.getElementById('remove-background-image'); var removeBackgroundFlag = document.getElementById('remove-background-image-flag'); - var addTextRegionButton = document.getElementById('add-text-region'); - var addImageRegionButton = document.getElementById('add-image-region'); + var addRegionButton = document.getElementById('add-region-button'); + var regionAddModal = document.getElementById('region-add-modal'); + var regionCardTemplate = document.getElementById('region-card-template'); var regionsJsonInput = document.getElementById('regions-json'); + var templateForm = document.getElementById('template-form'); var draft = null; var selectedIndex = -1; + var overlayRenderFrame = 0; function escapeHtml(value) { - return String(value === undefined || value === null ? '' : value) - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); + return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value); } function valueOrDefault(value, fallback) { - return value === undefined || value === null || value === '' ? fallback : value; + return utils.valueOrDefault ? utils.valueOrDefault(value, fallback) : (value === undefined || value === null || value === '' ? fallback : value); } function getCanvasSize() { @@ -55,7 +56,7 @@ } function clamp(value, min, max) { - return Math.max(min, Math.min(max, value)); + return utils.clamp ? utils.clamp(value, min, max) : Math.max(min, Math.min(max, value)); } function getCards() { @@ -67,21 +68,62 @@ } function getRegionName(card) { - return String(card.querySelector('[name="region_name[]"]').value || '').trim(); + return utils.getRegionName ? utils.getRegionName(card) : String(card.querySelector('[name="region_name[]"]').value || '').trim(); } function syncRegionIdentity(card, value) { + if (utils.syncRegionIdentity) { + utils.syncRegionIdentity(card, value); + return; + } var next = String(value || '').trim(); card.querySelector('[name="region_name[]"]').value = next; card.querySelector('[name="region_key[]"]').value = next; card.querySelector('[name="region_label[]"]').value = next; } + function validateRegionNames() { + var cards = getCards(); + var names = {}; + var hasDuplicate = false; + + cards.forEach(function (card) { + var input = card.querySelector('[name="region_name[]"]'); + if (!input) { + return; + } + + var normalized = String(input.value || '').trim().toLowerCase(); + if (!normalized) { + input.setCustomValidity('Region name is required.'); + return; + } + + if (!names[normalized]) { + names[normalized] = []; + } + names[normalized].push(input); + }); + + Object.keys(names).forEach(function (key) { + var inputs = names[key]; + if (inputs.length > 1) { + hasDuplicate = true; + inputs.forEach(function (input) { + input.setCustomValidity('Region names must be unique on this template.'); + }); + } else { + inputs[0].setCustomValidity(''); + } + }); + + return !hasDuplicate; + } + function readCard(card) { - var name = getRegionName(card); - return { - region_key: name, - label: name, + return utils.readCard ? utils.readCard(card) : { + region_key: getRegionName(card), + label: getRegionName(card), region_type: card.querySelector('[name="region_type[]"]').value, font_family: card.querySelector('[name="font_family[]"]').value, x: Number(card.querySelector('[name="region_x[]"]').value || 0), @@ -93,6 +135,10 @@ } function writeCard(card, values) { + if (utils.writeCard) { + utils.writeCard(card, values); + return; + } if (values.region_name !== undefined) { syncRegionIdentity(card, values.region_name); } else if (values.region_key !== undefined) { @@ -101,7 +147,7 @@ syncRegionIdentity(card, values.label); } if (values.region_type !== undefined) { card.querySelector('[name="region_type[]"]').value = values.region_type; } - if (values.font_family !== undefined) { card.querySelector('[name="font_family[]"]').value = values.font_family; updateRegionFieldVisibility(card); } + if (values.font_family !== undefined) { card.querySelector('[name="font_family[]"]').value = values.font_family; } if (values.x !== undefined) { card.querySelector('[name="region_x[]"]').value = Math.round(values.x); } if (values.y !== undefined) { card.querySelector('[name="region_y[]"]').value = Math.round(values.y); } if (values.width !== undefined) { card.querySelector('[name="region_width[]"]').value = Math.round(values.width); } @@ -110,28 +156,22 @@ } function getOverlayRect() { - return overlay.getBoundingClientRect(); + return utils.getOverlayRect ? utils.getOverlayRect(overlay) : overlay.getBoundingClientRect(); } function toCanvasPoint(event) { - var rect = getOverlayRect(); - var size = getCanvasSize(); - var x = clamp(event.clientX - rect.left, 0, rect.width); - var y = clamp(event.clientY - rect.top, 0, rect.height); - return { - x: Math.round((x / Math.max(rect.width, 1)) * size.width), - y: Math.round((y / Math.max(rect.height, 1)) * size.height) + return utils.toCanvasPoint ? utils.toCanvasPoint(event, overlay, getCanvasSize()) : { + x: 0, + y: 0 }; } function canvasRectToPixels(region) { - var rect = getOverlayRect(); - var size = getCanvasSize(); - return { - left: (region.x / size.width) * rect.width, - top: (region.y / size.height) * rect.height, - width: (region.width / size.width) * rect.width, - height: (region.height / size.height) * rect.height + return utils.canvasRectToPixels ? utils.canvasRectToPixels(region, overlay, getCanvasSize()) : { + left: 0, + top: 0, + width: 0, + height: 0 }; } @@ -182,40 +222,84 @@ reader.readAsDataURL(file); } - function updateRegionFieldVisibility(card) { - var typeSelect = card.querySelector('[name="region_type[]"]'); - var fontField = card.querySelector('[name="font_family[]"]'); - if (!typeSelect || !fontField) { + function updateStageBackgroundColor() { + if (!stage) { return; } - fontField.value = typeSelect.value === 'text' || typeSelect.value === 'html' ? 'Arial' : ''; + stage.style.backgroundColor = backgroundColorInput && backgroundColorInput.value ? backgroundColorInput.value : '#111111'; + } + + function getRegionChipLabel(regionType) { + return regionType === 'image' ? 'Image' : regionType === 'webpage' ? 'Webpage' : regionType === 'html' ? 'HTML' : 'Text'; + } + + function populateRegionCard(card, region) { + var chip = card.querySelector('[data-region-chip]'); + var title = card.querySelector('[data-region-title]'); + var nameInput = card.querySelector('[name="region_name[]"]'); + var fontFamilyInput = card.querySelector('[name="font_family[]"]'); + var regionTypeInput = card.querySelector('[name="region_type[]"]'); + var regionKeyInput = card.querySelector('[name="region_key[]"]'); + var regionLabelInput = card.querySelector('[name="region_label[]"]'); + + if (title) { + title.textContent = region.label || region.region_key || 'Region'; + } + if (chip) { + chip.textContent = getRegionChipLabel(region.region_type); + } + if (nameInput) { + nameInput.value = region.region_key || region.label || ''; + } + if (fontFamilyInput) { + fontFamilyInput.value = region.region_type === 'image' ? '' : (region.font_family || 'Arial'); + } + if (regionTypeInput) { + regionTypeInput.value = region.region_type || 'text'; + } + if (regionKeyInput) { + regionKeyInput.value = region.region_key || region.label || ''; + } + if (regionLabelInput) { + regionLabelInput.value = region.label || region.region_key || ''; + } + card.querySelector('[name="region_x[]"]').value = valueOrDefault(region.x, 80); + card.querySelector('[name="region_y[]"]').value = valueOrDefault(region.y, 80); + card.querySelector('[name="region_z[]"]').value = valueOrDefault(region.z_index, 1); + card.querySelector('[name="region_width[]"]').value = valueOrDefault(region.width, 300); + card.querySelector('[name="region_height[]"]').value = valueOrDefault(region.height, 120); + } + + function updateRegionLabel(card) { + var label = getRegionName(card) || 'Region'; + var cards = getCards(); + var index = cards.indexOf(card); + var title = card.querySelector('.template-field-head strong'); + if (title) { + title.textContent = label; + } + if (index >= 0 && regionSelect.options[index]) { + regionSelect.options[index].textContent = label; + } } function makeRegionCard(region) { - var card = document.createElement('div'); - card.className = 'region-item'; - var chipLabel = region.region_type === 'image' ? 'Image' : region.region_type === 'webpage' ? 'Webpage' : region.region_type === 'html' ? 'HTML' : 'Text'; - card.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - '
    ' + escapeHtml(region.label || region.region_key || '') + '' + escapeHtml(chipLabel) + '
    ' + - '
    ' + - '
    ' + - '
    '; + var card; + if (regionCardTemplate && regionCardTemplate.content) { + card = regionCardTemplate.content.firstElementChild.cloneNode(true); + } else { + card = document.createElement('div'); + card.className = 'card card-outline card-secondary admin-form-card region-item mb-3'; + } + populateRegionCard(card, region); var nameInput = card.querySelector('[name="region_name[]"]'); - var typeSelect = card.querySelector('[name="region_type[]"]'); nameInput.addEventListener('input', function () { syncRegionIdentity(card, nameInput.value); + updateRegionLabel(card); + validateRegionNames(); renderRegionSidebar(); renderOverlay(); }); - typeSelect.addEventListener('change', function () { - updateRegionFieldVisibility(card); - renderOverlay(); - }); card.addEventListener('click', function (event) { if (event.target && event.target.classList && event.target.classList.contains('remove-region')) { return; @@ -233,7 +317,6 @@ renderRegionSidebar(); renderOverlay(); }); - updateRegionFieldVisibility(card); return card; } @@ -269,6 +352,7 @@ }); regionSelect.value = String(selectedIndex); updateCanvasSizeLock(); + validateRegionNames(); } function renderOverlay() { @@ -290,6 +374,17 @@ } } + function requestOverlayRender() { + if (overlayRenderFrame) { + return; + } + + overlayRenderFrame = window.requestAnimationFrame(function () { + overlayRenderFrame = 0; + renderOverlay(); + }); + } + function render() { updateAspectRatio(); renderRegionSidebar(); @@ -318,6 +413,13 @@ setSelected(getCards().length - 1); } + function openAddRegionModal() { + if (!regionAddModal || !window.bootstrap || !window.bootstrap.Modal) { + return; + } + window.bootstrap.Modal.getOrCreateInstance(regionAddModal).show(); + } + function createDefaultRegion(type) { var count = getCards().length + 1; var name = 'region_' + count; @@ -356,7 +458,7 @@ renderOverlay(); function moveHandler(moveEvent) { draft.end = toCanvasPoint(moveEvent); - renderOverlay(); + requestOverlayRender(); } function upHandler(upEvent) { draft.end = toCanvasPoint(upEvent); @@ -367,7 +469,7 @@ addRegion({ region_key: 'region_' + (getCards().length + 1), label: 'Region ' + (getCards().length + 1), region_type: 'text', x: region.x, y: region.y, width: region.width, height: region.height, z_index: 1 }); } draft = null; - renderOverlay(); + requestOverlayRender(); document.removeEventListener('mousemove', moveHandler); document.removeEventListener('mouseup', upHandler); } @@ -384,7 +486,7 @@ var dy = currentPoint.y - startPoint.y; var next = clampRegion({ x: startRegion.x + dx, y: startRegion.y + dy, width: startRegion.width, height: startRegion.height }); writeCard(cardAt(index), { x: next.x, y: next.y }); - renderOverlay(); + requestOverlayRender(); } function upHandler() { document.removeEventListener('mousemove', moveHandler); @@ -410,7 +512,7 @@ if (next.height < 12) { if (dir.indexOf('n') !== -1) { next.y -= 12 - next.height; } next.height = 12; } next = clampRegion(next); writeCard(cardAt(index), { x: next.x, y: next.y, width: next.width, height: next.height }); - renderOverlay(); + requestOverlayRender(); } function upHandler() { document.removeEventListener('mousemove', moveHandler); @@ -420,15 +522,20 @@ document.addEventListener('mouseup', upHandler); } - addTextRegionButton.addEventListener('click', function () { addRegion(createDefaultRegion('text')); }); - var addHtmlRegionButton = document.getElementById('add-html-region'); - if (addHtmlRegionButton) { - addHtmlRegionButton.addEventListener('click', function () { addRegion(createDefaultRegion('html')); }); - } - addImageRegionButton.addEventListener('click', function () { addRegion(createDefaultRegion('image')); }); - var addWebpageRegionButton = document.getElementById('add-webpage-region'); - if (addWebpageRegionButton) { - addWebpageRegionButton.addEventListener('click', function () { addRegion(createDefaultRegion('webpage')); }); + if (addRegionButton && regionAddModal) { + var addRegionTypeButtons = regionAddModal.querySelectorAll('[data-add-region-type]'); + addRegionButton.addEventListener('click', function () { + openAddRegionModal(); + }); + Array.prototype.forEach.call(addRegionTypeButtons, function (button) { + button.addEventListener('click', function () { + var regionType = button.getAttribute('data-add-region-type'); + addRegion(createDefaultRegion(regionType)); + if (window.bootstrap && window.bootstrap.Modal) { + window.bootstrap.Modal.getOrCreateInstance(regionAddModal).hide(); + } + }); + }); } backgroundInput.addEventListener('change', function () { var file = backgroundInput.files && backgroundInput.files[0]; @@ -445,6 +552,9 @@ backgroundEmpty.style.display = 'block'; }); } + if (backgroundColorInput) { + backgroundColorInput.addEventListener('input', updateStageBackgroundColor); + } canvasSizeSelect.addEventListener('change', function () { syncCanvasSizeSelection(); render(); }); canvasWidthInput.addEventListener('input', render); canvasHeightInput.addEventListener('input', render); @@ -470,12 +580,27 @@ setSelected(-1); startDraw(event); }); - document.getElementById('template-form').addEventListener('submit', function () { - syncCanvasSizeSelection(); - regionsJsonInput.value = JSON.stringify(getCards().map(readCard)); - }); + if (templateForm) { + templateForm.addEventListener('formdata', function (event) { + if (!validateRegionNames()) { + event.preventDefault(); + return; + } + syncCanvasSizeSelection(); + event.formData.set('regions_json', JSON.stringify(getCards().map(readCard))); + }); + + templateForm.addEventListener('submit', function () { + if (!validateRegionNames()) { + return; + } + syncCanvasSizeSelection(); + regionsJsonInput.value = JSON.stringify(getCards().map(readCard)); + }); + } renderRegionList(existingRegions); syncCanvasSizeSelection(); + updateStageBackgroundColor(); render(); })(); diff --git a/src/web/public/js/templates/template-designer-utils.js b/src/web/public/js/templates/template-designer-utils.js new file mode 100644 index 0000000..8dc167d --- /dev/null +++ b/src/web/public/js/templates/template-designer-utils.js @@ -0,0 +1,117 @@ +(function () { + function escapeHtml(value) { + return String(value === undefined || value === null ? '' : value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function valueOrDefault(value, fallback) { + return value === undefined || value === null || value === '' ? fallback : value; + } + + function clamp(value, min, max) { + return Math.max(min, Math.min(max, value)); + } + + function getRegionName(card) { + return String(card.querySelector('[name="region_name[]"]').value || '').trim(); + } + + function syncRegionIdentity(card, value) { + var next = String(value || '').trim(); + card.querySelector('[name="region_name[]"]').value = next; + card.querySelector('[name="region_key[]"]').value = next; + card.querySelector('[name="region_label[]"]').value = next; + } + + function readCard(card) { + var name = getRegionName(card); + return { + region_key: name, + label: name, + region_type: card.querySelector('[name="region_type[]"]').value, + font_family: card.querySelector('[name="font_family[]"]').value, + x: Number(card.querySelector('[name="region_x[]"]').value || 0), + y: Number(card.querySelector('[name="region_y[]"]').value || 0), + width: Number(card.querySelector('[name="region_width[]"]').value || 0), + height: Number(card.querySelector('[name="region_height[]"]').value || 0), + z_index: Number(card.querySelector('[name="region_z[]"]').value || 0) + }; + } + + function writeCard(card, values) { + if (values.region_name !== undefined) { + syncRegionIdentity(card, values.region_name); + } else if (values.region_key !== undefined) { + syncRegionIdentity(card, values.region_key); + } else if (values.label !== undefined) { + syncRegionIdentity(card, values.label); + } + if (values.region_type !== undefined) { card.querySelector('[name="region_type[]"]').value = values.region_type; } + if (values.font_family !== undefined) { card.querySelector('[name="font_family[]"]').value = values.font_family; } + if (values.x !== undefined) { card.querySelector('[name="region_x[]"]').value = Math.round(values.x); } + if (values.y !== undefined) { card.querySelector('[name="region_y[]"]').value = Math.round(values.y); } + if (values.width !== undefined) { card.querySelector('[name="region_width[]"]').value = Math.round(values.width); } + if (values.height !== undefined) { card.querySelector('[name="region_height[]"]').value = Math.round(values.height); } + if (values.z_index !== undefined) { card.querySelector('[name="region_z[]"]').value = Math.round(values.z_index); } + } + + function clampRegion(region, size, minSize) { + var bounds = size || { width: 1920, height: 1080 }; + var minimum = minSize || 12; + var x = clamp(region.x, 0, bounds.width - minimum); + var y = clamp(region.y, 0, bounds.height - minimum); + var width = Math.max(minimum, region.width); + var height = Math.max(minimum, region.height); + if (x + width > bounds.width) { + width = bounds.width - x; + } + if (y + height > bounds.height) { + height = bounds.height - y; + } + return { x: Math.round(x), y: Math.round(y), width: Math.round(Math.max(minimum, width)), height: Math.round(Math.max(minimum, height)) }; + } + + function getOverlayRect(overlay) { + return overlay.getBoundingClientRect(); + } + + function toCanvasPoint(event, overlay, size) { + var rect = getOverlayRect(overlay); + var canvasSize = size || { width: 1920, height: 1080 }; + var x = clamp(event.clientX - rect.left, 0, rect.width); + var y = clamp(event.clientY - rect.top, 0, rect.height); + return { + x: Math.round((x / Math.max(rect.width, 1)) * canvasSize.width), + y: Math.round((y / Math.max(rect.height, 1)) * canvasSize.height) + }; + } + + function canvasRectToPixels(region, overlay, size) { + var rect = getOverlayRect(overlay); + var canvasSize = size || { width: 1920, height: 1080 }; + return { + left: (region.x / canvasSize.width) * rect.width, + top: (region.y / canvasSize.height) * rect.height, + width: (region.width / canvasSize.width) * rect.width, + height: (region.height / canvasSize.height) * rect.height + }; + } + + window.templateDesignerUtils = { + escapeHtml: escapeHtml, + valueOrDefault: valueOrDefault, + clamp: clamp, + getRegionName: getRegionName, + syncRegionIdentity: syncRegionIdentity, + readCard: readCard, + writeCard: writeCard, + clampRegion: clampRegion, + getOverlayRect: getOverlayRect, + toCanvasPoint: toCanvasPoint, + canvasRectToPixels: canvasRectToPixels + }; +}()); diff --git a/src/web/public/js/templates/template-designer.js b/src/web/public/js/templates/template-designer.js new file mode 100644 index 0000000..bd07748 --- /dev/null +++ b/src/web/public/js/templates/template-designer.js @@ -0,0 +1,606 @@ +(function () { + var dataElement = document.getElementById('template-editor-data'); + if (!dataElement) { + return; + } + + var utils = window.templateDesignerUtils || {}; + + var templateData = {}; + try { + templateData = JSON.parse(dataElement.getAttribute('data-json') || dataElement.textContent || '{}') || {}; + } catch (_error) { + templateData = {}; + } + + var existingRegions = Array.isArray(templateData.regions) + ? templateData.regions + : (Array.isArray(templateData) ? templateData : []); + var stage = document.getElementById('designer-stage'); + var overlay = document.getElementById('designer-overlay'); + var regionList = document.getElementById('region-list'); + var regionSelect = document.getElementById('region-select'); + var canvasSizeSelect = document.getElementById('canvas-size-select'); + var canvasSizeIdInput = document.getElementById('canvas-size-id'); + var canvasSizeSummary = document.getElementById('canvas-size-summary'); + var canvasWidthInput = document.getElementById('canvas-width'); + var canvasHeightInput = document.getElementById('canvas-height'); + var backgroundInput = document.getElementById('background-image'); + var backgroundColorInput = document.getElementById('background-color'); + var backgroundPreview = document.getElementById('background-preview'); + var backgroundEmpty = document.getElementById('background-empty'); + var removeBackgroundButton = document.getElementById('remove-background-image'); + var removeBackgroundFlag = document.getElementById('remove-background-image-flag'); + var addRegionButton = document.getElementById('add-region-button'); + var regionAddModal = document.getElementById('region-add-modal'); + var regionCardTemplate = document.getElementById('region-card-template'); + var regionsJsonInput = document.getElementById('regions-json'); + var templateForm = document.getElementById('template-form'); + var draft = null; + var selectedIndex = -1; + var overlayRenderFrame = 0; + + function escapeHtml(value) { + return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value); + } + + function valueOrDefault(value, fallback) { + return utils.valueOrDefault ? utils.valueOrDefault(value, fallback) : (value === undefined || value === null || value === '' ? fallback : value); + } + + function getCanvasSize() { + return { + width: Math.max(1, Number(canvasWidthInput.value || 1920)), + height: Math.max(1, Number(canvasHeightInput.value || 1080)) + }; + } + + function clamp(value, min, max) { + return utils.clamp ? utils.clamp(value, min, max) : Math.max(min, Math.min(max, value)); + } + + function getCards() { + return Array.prototype.slice.call(regionList.querySelectorAll('.region-item')); + } + + function cardAt(index) { + return getCards()[index] || null; + } + + function getRegionName(card) { + return utils.getRegionName ? utils.getRegionName(card) : String(card.querySelector('[name="region_name[]"]').value || '').trim(); + } + + function syncRegionIdentity(card, value) { + if (utils.syncRegionIdentity) { + utils.syncRegionIdentity(card, value); + return; + } + var next = String(value || '').trim(); + card.querySelector('[name="region_name[]"]').value = next; + card.querySelector('[name="region_key[]"]').value = next; + card.querySelector('[name="region_label[]"]').value = next; + } + + function validateRegionNames() { + var cards = getCards(); + var names = {}; + var hasDuplicate = false; + + cards.forEach(function (card) { + var input = card.querySelector('[name="region_name[]"]'); + if (!input) { + return; + } + + var normalized = String(input.value || '').trim().toLowerCase(); + if (!normalized) { + input.setCustomValidity('Region name is required.'); + return; + } + + if (!names[normalized]) { + names[normalized] = []; + } + names[normalized].push(input); + }); + + Object.keys(names).forEach(function (key) { + var inputs = names[key]; + if (inputs.length > 1) { + hasDuplicate = true; + inputs.forEach(function (input) { + input.setCustomValidity('Region names must be unique on this template.'); + }); + } else { + inputs[0].setCustomValidity(''); + } + }); + + return !hasDuplicate; + } + + function readCard(card) { + return utils.readCard ? utils.readCard(card) : { + region_key: getRegionName(card), + label: getRegionName(card), + region_type: card.querySelector('[name="region_type[]"]').value, + font_family: card.querySelector('[name="font_family[]"]').value, + x: Number(card.querySelector('[name="region_x[]"]').value || 0), + y: Number(card.querySelector('[name="region_y[]"]').value || 0), + width: Number(card.querySelector('[name="region_width[]"]').value || 0), + height: Number(card.querySelector('[name="region_height[]"]').value || 0), + z_index: Number(card.querySelector('[name="region_z[]"]').value || 0) + }; + } + + function writeCard(card, values) { + if (utils.writeCard) { + utils.writeCard(card, values); + return; + } + if (values.region_name !== undefined) { + syncRegionIdentity(card, values.region_name); + } else if (values.region_key !== undefined) { + syncRegionIdentity(card, values.region_key); + } else if (values.label !== undefined) { + syncRegionIdentity(card, values.label); + } + if (values.region_type !== undefined) { card.querySelector('[name="region_type[]"]').value = values.region_type; } + if (values.font_family !== undefined) { card.querySelector('[name="font_family[]"]').value = values.font_family; } + if (values.x !== undefined) { card.querySelector('[name="region_x[]"]').value = Math.round(values.x); } + if (values.y !== undefined) { card.querySelector('[name="region_y[]"]').value = Math.round(values.y); } + if (values.width !== undefined) { card.querySelector('[name="region_width[]"]').value = Math.round(values.width); } + if (values.height !== undefined) { card.querySelector('[name="region_height[]"]').value = Math.round(values.height); } + if (values.z_index !== undefined) { card.querySelector('[name="region_z[]"]').value = Math.round(values.z_index); } + } + + function getOverlayRect() { + return utils.getOverlayRect ? utils.getOverlayRect(overlay) : overlay.getBoundingClientRect(); + } + + function toCanvasPoint(event) { + return utils.toCanvasPoint ? utils.toCanvasPoint(event, overlay, getCanvasSize()) : { + x: 0, + y: 0 + }; + } + + function canvasRectToPixels(region) { + return utils.canvasRectToPixels ? utils.canvasRectToPixels(region, overlay, getCanvasSize()) : { + left: 0, + top: 0, + width: 0, + height: 0 + }; + } + + function updateAspectRatio() { + var size = getCanvasSize(); + stage.style.aspectRatio = size.width + ' / ' + size.height; + } + + function updateCanvasSizeSummary() { + var option = canvasSizeSelect.options[canvasSizeSelect.selectedIndex]; + canvasSizeSummary.textContent = option ? option.textContent : ''; + } + + function updateCanvasSizeLock() { + var lockOnExistingTemplate = canvasSizeSelect.dataset.lockOnExistingTemplate === 'true'; + var locked = lockOnExistingTemplate && getCards().length > 0; + canvasSizeSelect.disabled = locked; + canvasSizeSummary.classList.toggle('is-locked', locked); + } + + function syncCanvasSizeSelection() { + var option = canvasSizeSelect.options[canvasSizeSelect.selectedIndex]; + if (!option) { + return; + } + if (canvasSizeIdInput) { + canvasSizeIdInput.value = option.value; + } + canvasWidthInput.value = Math.max(1, Number(option.dataset.width || canvasWidthInput.value || 1920)); + canvasHeightInput.value = Math.max(1, Number(option.dataset.height || canvasHeightInput.value || 1080)); + updateAspectRatio(); + updateCanvasSizeSummary(); + } + + function updateBackgroundPreview(file) { + if (!file) { + return; + } + if (removeBackgroundFlag) { + removeBackgroundFlag.checked = false; + } + var reader = new FileReader(); + reader.onload = function () { + backgroundPreview.src = reader.result; + backgroundPreview.style.display = 'block'; + backgroundEmpty.style.display = 'none'; + }; + reader.readAsDataURL(file); + } + + function updateStageBackgroundColor() { + if (!stage) { + return; + } + stage.style.backgroundColor = backgroundColorInput && backgroundColorInput.value ? backgroundColorInput.value : '#111111'; + } + + function getRegionChipLabel(regionType) { + return regionType === 'image' ? 'Image' : regionType === 'webpage' ? 'Webpage' : regionType === 'html' ? 'HTML' : 'Text'; + } + + function populateRegionCard(card, region) { + var chip = card.querySelector('[data-region-chip]'); + var title = card.querySelector('[data-region-title]'); + var nameInput = card.querySelector('[name="region_name[]"]'); + var fontFamilyInput = card.querySelector('[name="font_family[]"]'); + var regionTypeInput = card.querySelector('[name="region_type[]"]'); + var regionKeyInput = card.querySelector('[name="region_key[]"]'); + var regionLabelInput = card.querySelector('[name="region_label[]"]'); + + if (title) { + title.textContent = region.label || region.region_key || 'Region'; + } + if (chip) { + chip.textContent = getRegionChipLabel(region.region_type); + } + if (nameInput) { + nameInput.value = region.region_key || region.label || ''; + } + if (fontFamilyInput) { + fontFamilyInput.value = region.region_type === 'image' ? '' : (region.font_family || 'Arial'); + } + if (regionTypeInput) { + regionTypeInput.value = region.region_type || 'text'; + } + if (regionKeyInput) { + regionKeyInput.value = region.region_key || region.label || ''; + } + if (regionLabelInput) { + regionLabelInput.value = region.label || region.region_key || ''; + } + card.querySelector('[name="region_x[]"]').value = valueOrDefault(region.x, 80); + card.querySelector('[name="region_y[]"]').value = valueOrDefault(region.y, 80); + card.querySelector('[name="region_z[]"]').value = valueOrDefault(region.z_index, 1); + card.querySelector('[name="region_width[]"]').value = valueOrDefault(region.width, 300); + card.querySelector('[name="region_height[]"]').value = valueOrDefault(region.height, 120); + } + + function updateRegionLabel(card) { + var label = getRegionName(card) || 'Region'; + var cards = getCards(); + var index = cards.indexOf(card); + var title = card.querySelector('.template-field-head strong'); + if (title) { + title.textContent = label; + } + if (index >= 0 && regionSelect.options[index]) { + regionSelect.options[index].textContent = label; + } + } + + function makeRegionCard(region) { + var card; + if (regionCardTemplate && regionCardTemplate.content) { + card = regionCardTemplate.content.firstElementChild.cloneNode(true); + } else { + card = document.createElement('div'); + card.className = 'card card-outline card-secondary admin-form-card region-item mb-3'; + } + populateRegionCard(card, region); + var nameInput = card.querySelector('[name="region_name[]"]'); + nameInput.addEventListener('input', function () { + syncRegionIdentity(card, nameInput.value); + updateRegionLabel(card); + validateRegionNames(); + renderRegionSidebar(); + renderOverlay(); + }); + card.addEventListener('click', function (event) { + if (event.target && event.target.classList && event.target.classList.contains('remove-region')) { + return; + } + setSelected(getCards().indexOf(card)); + }); + card.querySelector('.remove-region').addEventListener('click', function (event) { + event.preventDefault(); + card.remove(); + if (!getCards().length) { + selectedIndex = -1; + } else if (selectedIndex >= getCards().length) { + selectedIndex = getCards().length - 1; + } + renderRegionSidebar(); + renderOverlay(); + }); + return card; + } + + function renderRegionList(initialRegions) { + regionList.innerHTML = ''; + initialRegions.forEach(function (region) { + regionList.appendChild(makeRegionCard(region)); + }); + } + + function renderRegionSidebar() { + var cards = getCards(); + regionSelect.innerHTML = ''; + if (!cards.length) { + regionSelect.disabled = true; + regionList.innerHTML = ''; + updateCanvasSizeLock(); + return; + } + regionSelect.disabled = false; + if (selectedIndex < 0 || selectedIndex >= cards.length) { + selectedIndex = 0; + } + cards.forEach(function (card, index) { + var option = document.createElement('option'); + option.value = String(index); + option.textContent = getRegionName(card) || ('Region ' + (index + 1)); + if (index === selectedIndex) { + option.selected = true; + } + regionSelect.appendChild(option); + card.hidden = index !== selectedIndex; + }); + regionSelect.value = String(selectedIndex); + updateCanvasSizeLock(); + validateRegionNames(); + } + + function renderOverlay() { + var cards = getCards(); + var selectedCard = selectedIndex >= 0 ? cards[selectedIndex] : null; + var selectedNow = selectedCard ? cards.indexOf(selectedCard) : -1; + var regions = cards.map(readCard); + regionsJsonInput.value = JSON.stringify(regions); + overlay.innerHTML = regions.map(function (region, index) { + var box = canvasRectToPixels(region); + var selected = index === selectedNow ? ' selected' : ''; + return '
    ' + escapeHtml(region.label || region.region_key || 'Region') + '
    '; + }).join(''); + if (draft) { + var rect = getOverlayRect(); + var size = getCanvasSize(); + var draftBox = { x: Math.min(draft.start.x, draft.end.x), y: Math.min(draft.start.y, draft.end.y), width: Math.abs(draft.end.x - draft.start.x), height: Math.abs(draft.end.y - draft.start.y) }; + overlay.innerHTML += '
    '; + } + } + + function requestOverlayRender() { + if (overlayRenderFrame) { + return; + } + + overlayRenderFrame = window.requestAnimationFrame(function () { + overlayRenderFrame = 0; + renderOverlay(); + }); + } + + function render() { + updateAspectRatio(); + renderRegionSidebar(); + renderOverlay(); + } + + function setSelected(index) { + var cards = getCards(); + if (!cards.length) { + selectedIndex = -1; + } else if (index < 0) { + selectedIndex = 0; + } else { + selectedIndex = clamp(index, 0, cards.length - 1); + } + renderRegionSidebar(); + renderOverlay(); + } + + function addRegion(region) { + var hint = regionList.querySelector('.muted'); + if (hint) { + hint.remove(); + } + regionList.appendChild(makeRegionCard(region)); + setSelected(getCards().length - 1); + } + + function openAddRegionModal() { + if (!regionAddModal || !window.bootstrap || !window.bootstrap.Modal) { + return; + } + window.bootstrap.Modal.getOrCreateInstance(regionAddModal).show(); + } + + function createDefaultRegion(type) { + var count = getCards().length + 1; + var name = 'region_' + count; + return { + region_key: name, + label: name, + region_type: type, + font_family: type === 'text' || type === 'html' ? 'Arial' : '', + x: 80, + y: 80, + width: type === 'image' || type === 'webpage' || type === 'html' ? 420 : 300, + height: type === 'image' || type === 'webpage' || type === 'html' ? 240 : 120, + z_index: 1 + }; + } + + function clampRegion(region) { + var size = getCanvasSize(); + var minSize = 12; + var x = clamp(region.x, 0, size.width - minSize); + var y = clamp(region.y, 0, size.height - minSize); + var width = Math.max(minSize, region.width); + var height = Math.max(minSize, region.height); + if (x + width > size.width) { + width = size.width - x; + } + if (y + height > size.height) { + height = size.height - y; + } + return { x: Math.round(x), y: Math.round(y), width: Math.round(Math.max(minSize, width)), height: Math.round(Math.max(minSize, height)) }; + } + + function startDraw(event) { + var start = toCanvasPoint(event); + draft = { start: start, end: start }; + renderOverlay(); + function moveHandler(moveEvent) { + draft.end = toCanvasPoint(moveEvent); + requestOverlayRender(); + } + function upHandler(upEvent) { + draft.end = toCanvasPoint(upEvent); + var width = Math.abs(draft.end.x - draft.start.x); + var height = Math.abs(draft.end.y - draft.start.y); + if (width >= 8 && height >= 8) { + var region = clampRegion({ x: Math.min(draft.start.x, draft.end.x), y: Math.min(draft.start.y, draft.end.y), width: width, height: height }); + addRegion({ region_key: 'region_' + (getCards().length + 1), label: 'Region ' + (getCards().length + 1), region_type: 'text', x: region.x, y: region.y, width: region.width, height: region.height, z_index: 1 }); + } + draft = null; + requestOverlayRender(); + document.removeEventListener('mousemove', moveHandler); + document.removeEventListener('mouseup', upHandler); + } + document.addEventListener('mousemove', moveHandler); + document.addEventListener('mouseup', upHandler); + } + + function startMove(index, event) { + var startPoint = toCanvasPoint(event); + var startRegion = readCard(cardAt(index)); + function moveHandler(moveEvent) { + var currentPoint = toCanvasPoint(moveEvent); + var dx = currentPoint.x - startPoint.x; + var dy = currentPoint.y - startPoint.y; + var next = clampRegion({ x: startRegion.x + dx, y: startRegion.y + dy, width: startRegion.width, height: startRegion.height }); + writeCard(cardAt(index), { x: next.x, y: next.y }); + requestOverlayRender(); + } + function upHandler() { + document.removeEventListener('mousemove', moveHandler); + document.removeEventListener('mouseup', upHandler); + } + document.addEventListener('mousemove', moveHandler); + document.addEventListener('mouseup', upHandler); + } + + function resizeFromHandle(index, dir, event) { + var startPoint = toCanvasPoint(event); + var startRegion = readCard(cardAt(index)); + function moveHandler(moveEvent) { + var currentPoint = toCanvasPoint(moveEvent); + var dx = currentPoint.x - startPoint.x; + var dy = currentPoint.y - startPoint.y; + var next = { x: startRegion.x, y: startRegion.y, width: startRegion.width, height: startRegion.height }; + if (dir.indexOf('w') !== -1) { next.x = startRegion.x + dx; next.width = startRegion.width - dx; } + if (dir.indexOf('e') !== -1) { next.width = startRegion.width + dx; } + if (dir.indexOf('n') !== -1) { next.y = startRegion.y + dy; next.height = startRegion.height - dy; } + if (dir.indexOf('s') !== -1) { next.height = startRegion.height + dy; } + if (next.width < 12) { if (dir.indexOf('w') !== -1) { next.x -= 12 - next.width; } next.width = 12; } + if (next.height < 12) { if (dir.indexOf('n') !== -1) { next.y -= 12 - next.height; } next.height = 12; } + next = clampRegion(next); + writeCard(cardAt(index), { x: next.x, y: next.y, width: next.width, height: next.height }); + requestOverlayRender(); + } + function upHandler() { + document.removeEventListener('mousemove', moveHandler); + document.removeEventListener('mouseup', upHandler); + } + document.addEventListener('mousemove', moveHandler); + document.addEventListener('mouseup', upHandler); + } + + if (addRegionButton && regionAddModal) { + var addRegionTypeButtons = regionAddModal.querySelectorAll('[data-add-region-type]'); + addRegionButton.addEventListener('click', function () { + openAddRegionModal(); + }); + Array.prototype.forEach.call(addRegionTypeButtons, function (button) { + button.addEventListener('click', function () { + var regionType = button.getAttribute('data-add-region-type'); + addRegion(createDefaultRegion(regionType)); + if (window.bootstrap && window.bootstrap.Modal) { + window.bootstrap.Modal.getOrCreateInstance(regionAddModal).hide(); + } + }); + }); + } + backgroundInput.addEventListener('change', function () { + var file = backgroundInput.files && backgroundInput.files[0]; + if (file) { + updateBackgroundPreview(file); + } + }); + if (removeBackgroundButton && removeBackgroundFlag) { + removeBackgroundButton.addEventListener('click', function () { + removeBackgroundFlag.checked = true; + backgroundInput.value = ''; + backgroundPreview.removeAttribute('src'); + backgroundPreview.style.display = 'none'; + backgroundEmpty.style.display = 'block'; + }); + } + if (backgroundColorInput) { + backgroundColorInput.addEventListener('input', updateStageBackgroundColor); + } + canvasSizeSelect.addEventListener('change', function () { syncCanvasSizeSelection(); render(); }); + canvasWidthInput.addEventListener('input', render); + canvasHeightInput.addEventListener('input', render); + regionSelect.addEventListener('change', function () { setSelected(Number(regionSelect.value || 0)); }); + overlay.addEventListener('mousedown', function (event) { + var rect = event.target.closest('.designer-rect'); + if (rect) { + var index = Number(rect.getAttribute('data-index')); + var handle = event.target.closest('.resize-handle'); + event.preventDefault(); + setSelected(index); + if (handle) { + resizeFromHandle(index, handle.getAttribute('data-dir'), event); + } else { + startMove(index, event); + } + return; + } + if (event.target !== overlay && !event.target.classList.contains('designer-overlay')) { + return; + } + event.preventDefault(); + setSelected(-1); + startDraw(event); + }); + if (templateForm) { + templateForm.addEventListener('formdata', function (event) { + if (!validateRegionNames()) { + event.preventDefault(); + return; + } + syncCanvasSizeSelection(); + event.formData.set('regions_json', JSON.stringify(getCards().map(readCard))); + }); + + templateForm.addEventListener('submit', function () { + if (!validateRegionNames()) { + return; + } + syncCanvasSizeSelection(); + regionsJsonInput.value = JSON.stringify(getCards().map(readCard)); + }); + } + + renderRegionList(existingRegions); + syncCanvasSizeSelection(); + updateStageBackgroundColor(); + render(); +})(); diff --git a/src/web/public/js/theme-init.js b/src/web/public/js/theme-init.js index f867351..5859470 100644 --- a/src/web/public/js/theme-init.js +++ b/src/web/public/js/theme-init.js @@ -1,20 +1,16 @@ (function () { - var storageKey = 'web-theme'; - var theme = 'light'; + var storageKey = 'lte-theme'; + var theme = 'auto'; try { var storedTheme = window.localStorage.getItem(storageKey); - if (storedTheme === 'dark' || storedTheme === 'light') { + if (storedTheme === 'dark' || storedTheme === 'light' || storedTheme === 'auto') { theme = storedTheme; - } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { - theme = 'dark'; } } catch (error) { - if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { - theme = 'dark'; - } + theme = 'auto'; } - document.documentElement.dataset.theme = theme; + document.documentElement.dataset.bsTheme = theme; document.documentElement.style.colorScheme = theme; }()); \ No newline at end of file diff --git a/src/web/public/js/theme-sidebar.js b/src/web/public/js/theme-sidebar.js index c6a8252..f4704a5 100644 --- a/src/web/public/js/theme-sidebar.js +++ b/src/web/public/js/theme-sidebar.js @@ -33,7 +33,7 @@ var nextTheme = normalizedTheme === 'dark' ? 'light' : 'dark'; var nextThemeLabel = nextTheme === 'dark' ? 'Dark mode' : 'Light mode'; - document.documentElement.dataset.theme = normalizedTheme; + document.documentElement.dataset.bsTheme = normalizedTheme; document.documentElement.style.colorScheme = normalizedTheme; Array.prototype.forEach.call(document.querySelectorAll('[data-theme-toggle]'), function (toggleButton) { @@ -62,7 +62,7 @@ Array.prototype.forEach.call(toggleButtons, function (toggleButton) { toggleButton.addEventListener('click', function () { - var nextTheme = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'; + var nextTheme = document.documentElement.dataset.bsTheme === 'dark' ? 'light' : 'dark'; setStoredTheme(nextTheme); applyTheme(nextTheme); }); diff --git a/src/web/public/js/toast.js b/src/web/public/js/toast.js index b3b850d..6cc268a 100644 --- a/src/web/public/js/toast.js +++ b/src/web/public/js/toast.js @@ -1,57 +1,102 @@ (function () { + function getBootstrapToast(toast) { + if (!toast || !window.bootstrap || !window.bootstrap.Toast) { + return null; + } + + return window.bootstrap.Toast.getOrCreateInstance(toast, { + autohide: true, + delay: 4000 + }); + } + + function removeToast(toast) { + if (toast && toast.parentNode) { + toast.parentNode.removeChild(toast); + } + } + function dismissToast(toast) { - if (!toast) { + var instance = getBootstrapToast(toast); + if (instance) { + instance.hide(); + return; + } + removeToast(toast); + } + + function setToastVariant(toast, variant) { + if (!toast || !toast.classList) { return; } - toast.classList.add('toast-hide'); - window.setTimeout(function () { - if (toast && toast.parentNode) { - toast.parentNode.removeChild(toast); - } - }, 220); + var nextVariant = String(variant || 'success').trim().toLowerCase(); + var variants = ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']; + variants.forEach(function (value) { + toast.classList.remove('text-bg-' + value); + }); + toast.classList.add('text-bg-' + (variants.indexOf(nextVariant) === -1 ? 'success' : nextVariant)); } - function showToast(message) { + function getMessageVariant(message, fallbackVariant) { + var text = String(message || '').trim(); + if (/^(unable to delete|cannot delete|can't delete)/i.test(text)) { + return 'danger'; + } + return String(fallbackVariant || 'success').trim().toLowerCase() || 'success'; + } + + function showToast(message, variant) { var text = String(message || '').trim(); if (!text) { return; } + var container = document.getElementById('app-toast-container'); + if (!container) { + return; + } + var existingToast = document.getElementById('app-toast'); - var existingBody = existingToast ? existingToast.querySelector('.toast-body') : null; - if (existingToast && existingBody) { - existingBody.textContent = text; - existingToast.classList.remove('toast-hide'); - window.clearTimeout(existingToast._dismissTimer); - existingToast._dismissTimer = window.setTimeout(function () { - dismissToast(existingToast); - }, 4000); + if (existingToast) { + var existingBody = existingToast.querySelector('.toast-body'); + if (existingBody) { + existingBody.textContent = text; + } + setToastVariant(existingToast, getMessageVariant(text, variant)); + var existingInstance = getBootstrapToast(existingToast); + if (existingInstance) { + existingInstance.show(); + } return; } var toast = document.createElement('div'); - toast.className = 'toast'; + toast.className = 'toast align-items-center border-0'; + toast.id = 'app-toast'; toast.setAttribute('role', 'status'); toast.setAttribute('aria-live', 'polite'); - toast.innerHTML = '
    '; + toast.setAttribute('aria-atomic', 'true'); + toast.setAttribute('data-bs-autohide', 'true'); + toast.setAttribute('data-bs-delay', '4000'); + toast.innerHTML = '
    '; + setToastVariant(toast, getMessageVariant(text, variant)); toast.querySelector('.toast-body').textContent = text; - var closeButton = toast.querySelector('.toast-close'); - closeButton.addEventListener('click', function () { - dismissToast(toast); + toast.addEventListener('hidden.bs.toast', function () { + removeToast(toast); }); - document.body.appendChild(toast); - toast._dismissTimer = window.setTimeout(function () { - dismissToast(toast); - }, 4000); + container.appendChild(toast); + var instance = getBootstrapToast(toast); + if (instance) { + instance.show(); + } } function initToast() { var toast = document.getElementById('app-toast'); - var closeButton = document.getElementById('app-toast-close'); - if (!toast || !closeButton) { + if (!toast) { return; } @@ -65,13 +110,12 @@ // ignore URL cleanup failures } - closeButton.addEventListener('click', function () { - dismissToast(toast); - }); + setToastVariant(toast, getMessageVariant((toast.querySelector('.toast-body') && toast.querySelector('.toast-body').textContent) || '', 'success')); - window.setTimeout(function () { - dismissToast(toast); - }, 4000); + var instance = getBootstrapToast(toast); + if (instance) { + instance.show(); + } } window.dismissToast = dismissToast; diff --git a/src/web/public/js/ckeditor5/LICENSE-ckeditor5.md b/src/web/public/js/vendor/ckeditor5/LICENSE-ckeditor5.md similarity index 100% rename from src/web/public/js/ckeditor5/LICENSE-ckeditor5.md rename to src/web/public/js/vendor/ckeditor5/LICENSE-ckeditor5.md diff --git a/src/web/public/js/ckeditor5/ckeditor5-content.css b/src/web/public/js/vendor/ckeditor5/ckeditor5-content.css similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5-content.css rename to src/web/public/js/vendor/ckeditor5/ckeditor5-content.css diff --git a/src/web/public/js/ckeditor5/ckeditor5-editor.css b/src/web/public/js/vendor/ckeditor5/ckeditor5-editor.css similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5-editor.css rename to src/web/public/js/vendor/ckeditor5/ckeditor5-editor.css diff --git a/src/web/public/js/ckeditor5/ckeditor5.css b/src/web/public/js/vendor/ckeditor5/ckeditor5.css similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.css rename to src/web/public/js/vendor/ckeditor5/ckeditor5.css diff --git a/src/web/public/js/ckeditor5/ckeditor5.css.map b/src/web/public/js/vendor/ckeditor5/ckeditor5.css.map similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.css.map rename to src/web/public/js/vendor/ckeditor5/ckeditor5.css.map diff --git a/src/web/public/js/ckeditor5/ckeditor5.js b/src/web/public/js/vendor/ckeditor5/ckeditor5.js similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.js rename to src/web/public/js/vendor/ckeditor5/ckeditor5.js diff --git a/src/web/public/js/ckeditor5/ckeditor5.js.map b/src/web/public/js/vendor/ckeditor5/ckeditor5.js.map similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.js.map rename to src/web/public/js/vendor/ckeditor5/ckeditor5.js.map diff --git a/src/web/public/js/ckeditor5/ckeditor5.umd.js b/src/web/public/js/vendor/ckeditor5/ckeditor5.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.umd.js rename to src/web/public/js/vendor/ckeditor5/ckeditor5.umd.js diff --git a/src/web/public/js/ckeditor5/ckeditor5.umd.js.map b/src/web/public/js/vendor/ckeditor5/ckeditor5.umd.js.map similarity index 100% rename from src/web/public/js/ckeditor5/ckeditor5.umd.js.map rename to src/web/public/js/vendor/ckeditor5/ckeditor5.umd.js.map diff --git a/src/web/public/js/ckeditor5/translations/af.d.ts b/src/web/public/js/vendor/ckeditor5/translations/af.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/af.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/af.d.ts diff --git a/src/web/public/js/ckeditor5/translations/af.js b/src/web/public/js/vendor/ckeditor5/translations/af.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/af.js rename to src/web/public/js/vendor/ckeditor5/translations/af.js diff --git a/src/web/public/js/ckeditor5/translations/af.umd.js b/src/web/public/js/vendor/ckeditor5/translations/af.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/af.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/af.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ar.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ar.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ar.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ar.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ar.js b/src/web/public/js/vendor/ckeditor5/translations/ar.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ar.js rename to src/web/public/js/vendor/ckeditor5/translations/ar.js diff --git a/src/web/public/js/ckeditor5/translations/ar.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ar.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ar.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ar.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ast.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ast.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ast.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ast.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ast.js b/src/web/public/js/vendor/ckeditor5/translations/ast.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ast.js rename to src/web/public/js/vendor/ckeditor5/translations/ast.js diff --git a/src/web/public/js/ckeditor5/translations/ast.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ast.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ast.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ast.umd.js diff --git a/src/web/public/js/ckeditor5/translations/az.d.ts b/src/web/public/js/vendor/ckeditor5/translations/az.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/az.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/az.d.ts diff --git a/src/web/public/js/ckeditor5/translations/az.js b/src/web/public/js/vendor/ckeditor5/translations/az.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/az.js rename to src/web/public/js/vendor/ckeditor5/translations/az.js diff --git a/src/web/public/js/ckeditor5/translations/az.umd.js b/src/web/public/js/vendor/ckeditor5/translations/az.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/az.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/az.umd.js diff --git a/src/web/public/js/ckeditor5/translations/be.d.ts b/src/web/public/js/vendor/ckeditor5/translations/be.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/be.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/be.d.ts diff --git a/src/web/public/js/ckeditor5/translations/be.js b/src/web/public/js/vendor/ckeditor5/translations/be.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/be.js rename to src/web/public/js/vendor/ckeditor5/translations/be.js diff --git a/src/web/public/js/ckeditor5/translations/be.umd.js b/src/web/public/js/vendor/ckeditor5/translations/be.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/be.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/be.umd.js diff --git a/src/web/public/js/ckeditor5/translations/bg.d.ts b/src/web/public/js/vendor/ckeditor5/translations/bg.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/bg.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/bg.d.ts diff --git a/src/web/public/js/ckeditor5/translations/bg.js b/src/web/public/js/vendor/ckeditor5/translations/bg.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bg.js rename to src/web/public/js/vendor/ckeditor5/translations/bg.js diff --git a/src/web/public/js/ckeditor5/translations/bg.umd.js b/src/web/public/js/vendor/ckeditor5/translations/bg.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bg.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/bg.umd.js diff --git a/src/web/public/js/ckeditor5/translations/bn.d.ts b/src/web/public/js/vendor/ckeditor5/translations/bn.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/bn.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/bn.d.ts diff --git a/src/web/public/js/ckeditor5/translations/bn.js b/src/web/public/js/vendor/ckeditor5/translations/bn.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bn.js rename to src/web/public/js/vendor/ckeditor5/translations/bn.js diff --git a/src/web/public/js/ckeditor5/translations/bn.umd.js b/src/web/public/js/vendor/ckeditor5/translations/bn.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bn.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/bn.umd.js diff --git a/src/web/public/js/ckeditor5/translations/bs.d.ts b/src/web/public/js/vendor/ckeditor5/translations/bs.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/bs.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/bs.d.ts diff --git a/src/web/public/js/ckeditor5/translations/bs.js b/src/web/public/js/vendor/ckeditor5/translations/bs.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bs.js rename to src/web/public/js/vendor/ckeditor5/translations/bs.js diff --git a/src/web/public/js/ckeditor5/translations/bs.umd.js b/src/web/public/js/vendor/ckeditor5/translations/bs.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/bs.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/bs.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ca.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ca.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ca.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ca.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ca.js b/src/web/public/js/vendor/ckeditor5/translations/ca.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ca.js rename to src/web/public/js/vendor/ckeditor5/translations/ca.js diff --git a/src/web/public/js/ckeditor5/translations/ca.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ca.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ca.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ca.umd.js diff --git a/src/web/public/js/ckeditor5/translations/cs.d.ts b/src/web/public/js/vendor/ckeditor5/translations/cs.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/cs.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/cs.d.ts diff --git a/src/web/public/js/ckeditor5/translations/cs.js b/src/web/public/js/vendor/ckeditor5/translations/cs.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/cs.js rename to src/web/public/js/vendor/ckeditor5/translations/cs.js diff --git a/src/web/public/js/ckeditor5/translations/cs.umd.js b/src/web/public/js/vendor/ckeditor5/translations/cs.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/cs.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/cs.umd.js diff --git a/src/web/public/js/ckeditor5/translations/da.d.ts b/src/web/public/js/vendor/ckeditor5/translations/da.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/da.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/da.d.ts diff --git a/src/web/public/js/ckeditor5/translations/da.js b/src/web/public/js/vendor/ckeditor5/translations/da.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/da.js rename to src/web/public/js/vendor/ckeditor5/translations/da.js diff --git a/src/web/public/js/ckeditor5/translations/da.umd.js b/src/web/public/js/vendor/ckeditor5/translations/da.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/da.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/da.umd.js diff --git a/src/web/public/js/ckeditor5/translations/de-ch.d.ts b/src/web/public/js/vendor/ckeditor5/translations/de-ch.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/de-ch.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/de-ch.d.ts diff --git a/src/web/public/js/ckeditor5/translations/de-ch.js b/src/web/public/js/vendor/ckeditor5/translations/de-ch.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/de-ch.js rename to src/web/public/js/vendor/ckeditor5/translations/de-ch.js diff --git a/src/web/public/js/ckeditor5/translations/de-ch.umd.js b/src/web/public/js/vendor/ckeditor5/translations/de-ch.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/de-ch.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/de-ch.umd.js diff --git a/src/web/public/js/ckeditor5/translations/de.d.ts b/src/web/public/js/vendor/ckeditor5/translations/de.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/de.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/de.d.ts diff --git a/src/web/public/js/ckeditor5/translations/de.js b/src/web/public/js/vendor/ckeditor5/translations/de.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/de.js rename to src/web/public/js/vendor/ckeditor5/translations/de.js diff --git a/src/web/public/js/ckeditor5/translations/de.umd.js b/src/web/public/js/vendor/ckeditor5/translations/de.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/de.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/de.umd.js diff --git a/src/web/public/js/ckeditor5/translations/el.d.ts b/src/web/public/js/vendor/ckeditor5/translations/el.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/el.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/el.d.ts diff --git a/src/web/public/js/ckeditor5/translations/el.js b/src/web/public/js/vendor/ckeditor5/translations/el.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/el.js rename to src/web/public/js/vendor/ckeditor5/translations/el.js diff --git a/src/web/public/js/ckeditor5/translations/el.umd.js b/src/web/public/js/vendor/ckeditor5/translations/el.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/el.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/el.umd.js diff --git a/src/web/public/js/ckeditor5/translations/en-au.d.ts b/src/web/public/js/vendor/ckeditor5/translations/en-au.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-au.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/en-au.d.ts diff --git a/src/web/public/js/ckeditor5/translations/en-au.js b/src/web/public/js/vendor/ckeditor5/translations/en-au.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-au.js rename to src/web/public/js/vendor/ckeditor5/translations/en-au.js diff --git a/src/web/public/js/ckeditor5/translations/en-au.umd.js b/src/web/public/js/vendor/ckeditor5/translations/en-au.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-au.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/en-au.umd.js diff --git a/src/web/public/js/ckeditor5/translations/en-gb.d.ts b/src/web/public/js/vendor/ckeditor5/translations/en-gb.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-gb.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/en-gb.d.ts diff --git a/src/web/public/js/ckeditor5/translations/en-gb.js b/src/web/public/js/vendor/ckeditor5/translations/en-gb.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-gb.js rename to src/web/public/js/vendor/ckeditor5/translations/en-gb.js diff --git a/src/web/public/js/ckeditor5/translations/en-gb.umd.js b/src/web/public/js/vendor/ckeditor5/translations/en-gb.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en-gb.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/en-gb.umd.js diff --git a/src/web/public/js/ckeditor5/translations/en.d.ts b/src/web/public/js/vendor/ckeditor5/translations/en.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/en.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/en.d.ts diff --git a/src/web/public/js/ckeditor5/translations/en.js b/src/web/public/js/vendor/ckeditor5/translations/en.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en.js rename to src/web/public/js/vendor/ckeditor5/translations/en.js diff --git a/src/web/public/js/ckeditor5/translations/en.umd.js b/src/web/public/js/vendor/ckeditor5/translations/en.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/en.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/en.umd.js diff --git a/src/web/public/js/ckeditor5/translations/eo.d.ts b/src/web/public/js/vendor/ckeditor5/translations/eo.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/eo.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/eo.d.ts diff --git a/src/web/public/js/ckeditor5/translations/eo.js b/src/web/public/js/vendor/ckeditor5/translations/eo.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/eo.js rename to src/web/public/js/vendor/ckeditor5/translations/eo.js diff --git a/src/web/public/js/ckeditor5/translations/eo.umd.js b/src/web/public/js/vendor/ckeditor5/translations/eo.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/eo.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/eo.umd.js diff --git a/src/web/public/js/ckeditor5/translations/es-co.d.ts b/src/web/public/js/vendor/ckeditor5/translations/es-co.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/es-co.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/es-co.d.ts diff --git a/src/web/public/js/ckeditor5/translations/es-co.js b/src/web/public/js/vendor/ckeditor5/translations/es-co.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/es-co.js rename to src/web/public/js/vendor/ckeditor5/translations/es-co.js diff --git a/src/web/public/js/ckeditor5/translations/es-co.umd.js b/src/web/public/js/vendor/ckeditor5/translations/es-co.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/es-co.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/es-co.umd.js diff --git a/src/web/public/js/ckeditor5/translations/es.d.ts b/src/web/public/js/vendor/ckeditor5/translations/es.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/es.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/es.d.ts diff --git a/src/web/public/js/ckeditor5/translations/es.js b/src/web/public/js/vendor/ckeditor5/translations/es.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/es.js rename to src/web/public/js/vendor/ckeditor5/translations/es.js diff --git a/src/web/public/js/ckeditor5/translations/es.umd.js b/src/web/public/js/vendor/ckeditor5/translations/es.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/es.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/es.umd.js diff --git a/src/web/public/js/ckeditor5/translations/et.d.ts b/src/web/public/js/vendor/ckeditor5/translations/et.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/et.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/et.d.ts diff --git a/src/web/public/js/ckeditor5/translations/et.js b/src/web/public/js/vendor/ckeditor5/translations/et.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/et.js rename to src/web/public/js/vendor/ckeditor5/translations/et.js diff --git a/src/web/public/js/ckeditor5/translations/et.umd.js b/src/web/public/js/vendor/ckeditor5/translations/et.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/et.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/et.umd.js diff --git a/src/web/public/js/ckeditor5/translations/eu.d.ts b/src/web/public/js/vendor/ckeditor5/translations/eu.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/eu.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/eu.d.ts diff --git a/src/web/public/js/ckeditor5/translations/eu.js b/src/web/public/js/vendor/ckeditor5/translations/eu.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/eu.js rename to src/web/public/js/vendor/ckeditor5/translations/eu.js diff --git a/src/web/public/js/ckeditor5/translations/eu.umd.js b/src/web/public/js/vendor/ckeditor5/translations/eu.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/eu.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/eu.umd.js diff --git a/src/web/public/js/ckeditor5/translations/fa.d.ts b/src/web/public/js/vendor/ckeditor5/translations/fa.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/fa.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/fa.d.ts diff --git a/src/web/public/js/ckeditor5/translations/fa.js b/src/web/public/js/vendor/ckeditor5/translations/fa.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fa.js rename to src/web/public/js/vendor/ckeditor5/translations/fa.js diff --git a/src/web/public/js/ckeditor5/translations/fa.umd.js b/src/web/public/js/vendor/ckeditor5/translations/fa.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fa.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/fa.umd.js diff --git a/src/web/public/js/ckeditor5/translations/fi.d.ts b/src/web/public/js/vendor/ckeditor5/translations/fi.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/fi.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/fi.d.ts diff --git a/src/web/public/js/ckeditor5/translations/fi.js b/src/web/public/js/vendor/ckeditor5/translations/fi.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fi.js rename to src/web/public/js/vendor/ckeditor5/translations/fi.js diff --git a/src/web/public/js/ckeditor5/translations/fi.umd.js b/src/web/public/js/vendor/ckeditor5/translations/fi.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fi.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/fi.umd.js diff --git a/src/web/public/js/ckeditor5/translations/fr.d.ts b/src/web/public/js/vendor/ckeditor5/translations/fr.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/fr.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/fr.d.ts diff --git a/src/web/public/js/ckeditor5/translations/fr.js b/src/web/public/js/vendor/ckeditor5/translations/fr.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fr.js rename to src/web/public/js/vendor/ckeditor5/translations/fr.js diff --git a/src/web/public/js/ckeditor5/translations/fr.umd.js b/src/web/public/js/vendor/ckeditor5/translations/fr.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/fr.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/fr.umd.js diff --git a/src/web/public/js/ckeditor5/translations/gl.d.ts b/src/web/public/js/vendor/ckeditor5/translations/gl.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/gl.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/gl.d.ts diff --git a/src/web/public/js/ckeditor5/translations/gl.js b/src/web/public/js/vendor/ckeditor5/translations/gl.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/gl.js rename to src/web/public/js/vendor/ckeditor5/translations/gl.js diff --git a/src/web/public/js/ckeditor5/translations/gl.umd.js b/src/web/public/js/vendor/ckeditor5/translations/gl.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/gl.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/gl.umd.js diff --git a/src/web/public/js/ckeditor5/translations/gu.d.ts b/src/web/public/js/vendor/ckeditor5/translations/gu.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/gu.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/gu.d.ts diff --git a/src/web/public/js/ckeditor5/translations/gu.js b/src/web/public/js/vendor/ckeditor5/translations/gu.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/gu.js rename to src/web/public/js/vendor/ckeditor5/translations/gu.js diff --git a/src/web/public/js/ckeditor5/translations/gu.umd.js b/src/web/public/js/vendor/ckeditor5/translations/gu.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/gu.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/gu.umd.js diff --git a/src/web/public/js/ckeditor5/translations/he.d.ts b/src/web/public/js/vendor/ckeditor5/translations/he.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/he.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/he.d.ts diff --git a/src/web/public/js/ckeditor5/translations/he.js b/src/web/public/js/vendor/ckeditor5/translations/he.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/he.js rename to src/web/public/js/vendor/ckeditor5/translations/he.js diff --git a/src/web/public/js/ckeditor5/translations/he.umd.js b/src/web/public/js/vendor/ckeditor5/translations/he.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/he.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/he.umd.js diff --git a/src/web/public/js/ckeditor5/translations/hi.d.ts b/src/web/public/js/vendor/ckeditor5/translations/hi.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/hi.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/hi.d.ts diff --git a/src/web/public/js/ckeditor5/translations/hi.js b/src/web/public/js/vendor/ckeditor5/translations/hi.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hi.js rename to src/web/public/js/vendor/ckeditor5/translations/hi.js diff --git a/src/web/public/js/ckeditor5/translations/hi.umd.js b/src/web/public/js/vendor/ckeditor5/translations/hi.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hi.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/hi.umd.js diff --git a/src/web/public/js/ckeditor5/translations/hr.d.ts b/src/web/public/js/vendor/ckeditor5/translations/hr.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/hr.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/hr.d.ts diff --git a/src/web/public/js/ckeditor5/translations/hr.js b/src/web/public/js/vendor/ckeditor5/translations/hr.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hr.js rename to src/web/public/js/vendor/ckeditor5/translations/hr.js diff --git a/src/web/public/js/ckeditor5/translations/hr.umd.js b/src/web/public/js/vendor/ckeditor5/translations/hr.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hr.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/hr.umd.js diff --git a/src/web/public/js/ckeditor5/translations/hu.d.ts b/src/web/public/js/vendor/ckeditor5/translations/hu.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/hu.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/hu.d.ts diff --git a/src/web/public/js/ckeditor5/translations/hu.js b/src/web/public/js/vendor/ckeditor5/translations/hu.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hu.js rename to src/web/public/js/vendor/ckeditor5/translations/hu.js diff --git a/src/web/public/js/ckeditor5/translations/hu.umd.js b/src/web/public/js/vendor/ckeditor5/translations/hu.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hu.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/hu.umd.js diff --git a/src/web/public/js/ckeditor5/translations/hy.d.ts b/src/web/public/js/vendor/ckeditor5/translations/hy.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/hy.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/hy.d.ts diff --git a/src/web/public/js/ckeditor5/translations/hy.js b/src/web/public/js/vendor/ckeditor5/translations/hy.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hy.js rename to src/web/public/js/vendor/ckeditor5/translations/hy.js diff --git a/src/web/public/js/ckeditor5/translations/hy.umd.js b/src/web/public/js/vendor/ckeditor5/translations/hy.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/hy.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/hy.umd.js diff --git a/src/web/public/js/ckeditor5/translations/id.d.ts b/src/web/public/js/vendor/ckeditor5/translations/id.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/id.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/id.d.ts diff --git a/src/web/public/js/ckeditor5/translations/id.js b/src/web/public/js/vendor/ckeditor5/translations/id.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/id.js rename to src/web/public/js/vendor/ckeditor5/translations/id.js diff --git a/src/web/public/js/ckeditor5/translations/id.umd.js b/src/web/public/js/vendor/ckeditor5/translations/id.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/id.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/id.umd.js diff --git a/src/web/public/js/ckeditor5/translations/it.d.ts b/src/web/public/js/vendor/ckeditor5/translations/it.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/it.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/it.d.ts diff --git a/src/web/public/js/ckeditor5/translations/it.js b/src/web/public/js/vendor/ckeditor5/translations/it.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/it.js rename to src/web/public/js/vendor/ckeditor5/translations/it.js diff --git a/src/web/public/js/ckeditor5/translations/it.umd.js b/src/web/public/js/vendor/ckeditor5/translations/it.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/it.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/it.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ja.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ja.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ja.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ja.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ja.js b/src/web/public/js/vendor/ckeditor5/translations/ja.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ja.js rename to src/web/public/js/vendor/ckeditor5/translations/ja.js diff --git a/src/web/public/js/ckeditor5/translations/ja.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ja.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ja.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ja.umd.js diff --git a/src/web/public/js/ckeditor5/translations/jv.d.ts b/src/web/public/js/vendor/ckeditor5/translations/jv.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/jv.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/jv.d.ts diff --git a/src/web/public/js/ckeditor5/translations/jv.js b/src/web/public/js/vendor/ckeditor5/translations/jv.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/jv.js rename to src/web/public/js/vendor/ckeditor5/translations/jv.js diff --git a/src/web/public/js/ckeditor5/translations/jv.umd.js b/src/web/public/js/vendor/ckeditor5/translations/jv.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/jv.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/jv.umd.js diff --git a/src/web/public/js/ckeditor5/translations/kk.d.ts b/src/web/public/js/vendor/ckeditor5/translations/kk.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/kk.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/kk.d.ts diff --git a/src/web/public/js/ckeditor5/translations/kk.js b/src/web/public/js/vendor/ckeditor5/translations/kk.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/kk.js rename to src/web/public/js/vendor/ckeditor5/translations/kk.js diff --git a/src/web/public/js/ckeditor5/translations/kk.umd.js b/src/web/public/js/vendor/ckeditor5/translations/kk.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/kk.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/kk.umd.js diff --git a/src/web/public/js/ckeditor5/translations/km.d.ts b/src/web/public/js/vendor/ckeditor5/translations/km.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/km.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/km.d.ts diff --git a/src/web/public/js/ckeditor5/translations/km.js b/src/web/public/js/vendor/ckeditor5/translations/km.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/km.js rename to src/web/public/js/vendor/ckeditor5/translations/km.js diff --git a/src/web/public/js/ckeditor5/translations/km.umd.js b/src/web/public/js/vendor/ckeditor5/translations/km.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/km.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/km.umd.js diff --git a/src/web/public/js/ckeditor5/translations/kn.d.ts b/src/web/public/js/vendor/ckeditor5/translations/kn.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/kn.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/kn.d.ts diff --git a/src/web/public/js/ckeditor5/translations/kn.js b/src/web/public/js/vendor/ckeditor5/translations/kn.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/kn.js rename to src/web/public/js/vendor/ckeditor5/translations/kn.js diff --git a/src/web/public/js/ckeditor5/translations/kn.umd.js b/src/web/public/js/vendor/ckeditor5/translations/kn.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/kn.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/kn.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ko.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ko.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ko.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ko.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ko.js b/src/web/public/js/vendor/ckeditor5/translations/ko.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ko.js rename to src/web/public/js/vendor/ckeditor5/translations/ko.js diff --git a/src/web/public/js/ckeditor5/translations/ko.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ko.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ko.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ko.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ku.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ku.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ku.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ku.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ku.js b/src/web/public/js/vendor/ckeditor5/translations/ku.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ku.js rename to src/web/public/js/vendor/ckeditor5/translations/ku.js diff --git a/src/web/public/js/ckeditor5/translations/ku.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ku.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ku.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ku.umd.js diff --git a/src/web/public/js/ckeditor5/translations/lt.d.ts b/src/web/public/js/vendor/ckeditor5/translations/lt.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/lt.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/lt.d.ts diff --git a/src/web/public/js/ckeditor5/translations/lt.js b/src/web/public/js/vendor/ckeditor5/translations/lt.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/lt.js rename to src/web/public/js/vendor/ckeditor5/translations/lt.js diff --git a/src/web/public/js/ckeditor5/translations/lt.umd.js b/src/web/public/js/vendor/ckeditor5/translations/lt.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/lt.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/lt.umd.js diff --git a/src/web/public/js/ckeditor5/translations/lv.d.ts b/src/web/public/js/vendor/ckeditor5/translations/lv.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/lv.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/lv.d.ts diff --git a/src/web/public/js/ckeditor5/translations/lv.js b/src/web/public/js/vendor/ckeditor5/translations/lv.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/lv.js rename to src/web/public/js/vendor/ckeditor5/translations/lv.js diff --git a/src/web/public/js/ckeditor5/translations/lv.umd.js b/src/web/public/js/vendor/ckeditor5/translations/lv.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/lv.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/lv.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ms.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ms.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ms.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ms.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ms.js b/src/web/public/js/vendor/ckeditor5/translations/ms.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ms.js rename to src/web/public/js/vendor/ckeditor5/translations/ms.js diff --git a/src/web/public/js/ckeditor5/translations/ms.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ms.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ms.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ms.umd.js diff --git a/src/web/public/js/ckeditor5/translations/nb.d.ts b/src/web/public/js/vendor/ckeditor5/translations/nb.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/nb.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/nb.d.ts diff --git a/src/web/public/js/ckeditor5/translations/nb.js b/src/web/public/js/vendor/ckeditor5/translations/nb.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/nb.js rename to src/web/public/js/vendor/ckeditor5/translations/nb.js diff --git a/src/web/public/js/ckeditor5/translations/nb.umd.js b/src/web/public/js/vendor/ckeditor5/translations/nb.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/nb.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/nb.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ne.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ne.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ne.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ne.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ne.js b/src/web/public/js/vendor/ckeditor5/translations/ne.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ne.js rename to src/web/public/js/vendor/ckeditor5/translations/ne.js diff --git a/src/web/public/js/ckeditor5/translations/ne.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ne.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ne.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ne.umd.js diff --git a/src/web/public/js/ckeditor5/translations/nl.d.ts b/src/web/public/js/vendor/ckeditor5/translations/nl.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/nl.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/nl.d.ts diff --git a/src/web/public/js/ckeditor5/translations/nl.js b/src/web/public/js/vendor/ckeditor5/translations/nl.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/nl.js rename to src/web/public/js/vendor/ckeditor5/translations/nl.js diff --git a/src/web/public/js/ckeditor5/translations/nl.umd.js b/src/web/public/js/vendor/ckeditor5/translations/nl.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/nl.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/nl.umd.js diff --git a/src/web/public/js/ckeditor5/translations/no.d.ts b/src/web/public/js/vendor/ckeditor5/translations/no.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/no.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/no.d.ts diff --git a/src/web/public/js/ckeditor5/translations/no.js b/src/web/public/js/vendor/ckeditor5/translations/no.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/no.js rename to src/web/public/js/vendor/ckeditor5/translations/no.js diff --git a/src/web/public/js/ckeditor5/translations/no.umd.js b/src/web/public/js/vendor/ckeditor5/translations/no.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/no.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/no.umd.js diff --git a/src/web/public/js/ckeditor5/translations/oc.d.ts b/src/web/public/js/vendor/ckeditor5/translations/oc.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/oc.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/oc.d.ts diff --git a/src/web/public/js/ckeditor5/translations/oc.js b/src/web/public/js/vendor/ckeditor5/translations/oc.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/oc.js rename to src/web/public/js/vendor/ckeditor5/translations/oc.js diff --git a/src/web/public/js/ckeditor5/translations/oc.umd.js b/src/web/public/js/vendor/ckeditor5/translations/oc.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/oc.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/oc.umd.js diff --git a/src/web/public/js/ckeditor5/translations/pl.d.ts b/src/web/public/js/vendor/ckeditor5/translations/pl.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/pl.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/pl.d.ts diff --git a/src/web/public/js/ckeditor5/translations/pl.js b/src/web/public/js/vendor/ckeditor5/translations/pl.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pl.js rename to src/web/public/js/vendor/ckeditor5/translations/pl.js diff --git a/src/web/public/js/ckeditor5/translations/pl.umd.js b/src/web/public/js/vendor/ckeditor5/translations/pl.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pl.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/pl.umd.js diff --git a/src/web/public/js/ckeditor5/translations/pt-br.d.ts b/src/web/public/js/vendor/ckeditor5/translations/pt-br.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt-br.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/pt-br.d.ts diff --git a/src/web/public/js/ckeditor5/translations/pt-br.js b/src/web/public/js/vendor/ckeditor5/translations/pt-br.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt-br.js rename to src/web/public/js/vendor/ckeditor5/translations/pt-br.js diff --git a/src/web/public/js/ckeditor5/translations/pt-br.umd.js b/src/web/public/js/vendor/ckeditor5/translations/pt-br.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt-br.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/pt-br.umd.js diff --git a/src/web/public/js/ckeditor5/translations/pt.d.ts b/src/web/public/js/vendor/ckeditor5/translations/pt.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/pt.d.ts diff --git a/src/web/public/js/ckeditor5/translations/pt.js b/src/web/public/js/vendor/ckeditor5/translations/pt.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt.js rename to src/web/public/js/vendor/ckeditor5/translations/pt.js diff --git a/src/web/public/js/ckeditor5/translations/pt.umd.js b/src/web/public/js/vendor/ckeditor5/translations/pt.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/pt.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/pt.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ro.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ro.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ro.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ro.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ro.js b/src/web/public/js/vendor/ckeditor5/translations/ro.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ro.js rename to src/web/public/js/vendor/ckeditor5/translations/ro.js diff --git a/src/web/public/js/ckeditor5/translations/ro.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ro.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ro.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ro.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ru.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ru.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ru.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ru.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ru.js b/src/web/public/js/vendor/ckeditor5/translations/ru.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ru.js rename to src/web/public/js/vendor/ckeditor5/translations/ru.js diff --git a/src/web/public/js/ckeditor5/translations/ru.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ru.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ru.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ru.umd.js diff --git a/src/web/public/js/ckeditor5/translations/si.d.ts b/src/web/public/js/vendor/ckeditor5/translations/si.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/si.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/si.d.ts diff --git a/src/web/public/js/ckeditor5/translations/si.js b/src/web/public/js/vendor/ckeditor5/translations/si.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/si.js rename to src/web/public/js/vendor/ckeditor5/translations/si.js diff --git a/src/web/public/js/ckeditor5/translations/si.umd.js b/src/web/public/js/vendor/ckeditor5/translations/si.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/si.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/si.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sk.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sk.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sk.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sk.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sk.js b/src/web/public/js/vendor/ckeditor5/translations/sk.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sk.js rename to src/web/public/js/vendor/ckeditor5/translations/sk.js diff --git a/src/web/public/js/ckeditor5/translations/sk.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sk.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sk.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sk.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sl.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sl.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sl.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sl.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sl.js b/src/web/public/js/vendor/ckeditor5/translations/sl.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sl.js rename to src/web/public/js/vendor/ckeditor5/translations/sl.js diff --git a/src/web/public/js/ckeditor5/translations/sl.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sl.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sl.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sl.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sq.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sq.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sq.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sq.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sq.js b/src/web/public/js/vendor/ckeditor5/translations/sq.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sq.js rename to src/web/public/js/vendor/ckeditor5/translations/sq.js diff --git a/src/web/public/js/ckeditor5/translations/sq.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sq.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sq.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sq.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sr-latn.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sr-latn.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr-latn.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sr-latn.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sr-latn.js b/src/web/public/js/vendor/ckeditor5/translations/sr-latn.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr-latn.js rename to src/web/public/js/vendor/ckeditor5/translations/sr-latn.js diff --git a/src/web/public/js/ckeditor5/translations/sr-latn.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sr-latn.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr-latn.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sr-latn.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sr.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sr.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sr.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sr.js b/src/web/public/js/vendor/ckeditor5/translations/sr.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr.js rename to src/web/public/js/vendor/ckeditor5/translations/sr.js diff --git a/src/web/public/js/ckeditor5/translations/sr.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sr.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sr.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sr.umd.js diff --git a/src/web/public/js/ckeditor5/translations/sv.d.ts b/src/web/public/js/vendor/ckeditor5/translations/sv.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/sv.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/sv.d.ts diff --git a/src/web/public/js/ckeditor5/translations/sv.js b/src/web/public/js/vendor/ckeditor5/translations/sv.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sv.js rename to src/web/public/js/vendor/ckeditor5/translations/sv.js diff --git a/src/web/public/js/ckeditor5/translations/sv.umd.js b/src/web/public/js/vendor/ckeditor5/translations/sv.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/sv.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/sv.umd.js diff --git a/src/web/public/js/ckeditor5/translations/th.d.ts b/src/web/public/js/vendor/ckeditor5/translations/th.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/th.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/th.d.ts diff --git a/src/web/public/js/ckeditor5/translations/th.js b/src/web/public/js/vendor/ckeditor5/translations/th.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/th.js rename to src/web/public/js/vendor/ckeditor5/translations/th.js diff --git a/src/web/public/js/ckeditor5/translations/th.umd.js b/src/web/public/js/vendor/ckeditor5/translations/th.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/th.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/th.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ti.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ti.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ti.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ti.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ti.js b/src/web/public/js/vendor/ckeditor5/translations/ti.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ti.js rename to src/web/public/js/vendor/ckeditor5/translations/ti.js diff --git a/src/web/public/js/ckeditor5/translations/ti.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ti.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ti.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ti.umd.js diff --git a/src/web/public/js/ckeditor5/translations/tk.d.ts b/src/web/public/js/vendor/ckeditor5/translations/tk.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/tk.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/tk.d.ts diff --git a/src/web/public/js/ckeditor5/translations/tk.js b/src/web/public/js/vendor/ckeditor5/translations/tk.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tk.js rename to src/web/public/js/vendor/ckeditor5/translations/tk.js diff --git a/src/web/public/js/ckeditor5/translations/tk.umd.js b/src/web/public/js/vendor/ckeditor5/translations/tk.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tk.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/tk.umd.js diff --git a/src/web/public/js/ckeditor5/translations/tr.d.ts b/src/web/public/js/vendor/ckeditor5/translations/tr.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/tr.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/tr.d.ts diff --git a/src/web/public/js/ckeditor5/translations/tr.js b/src/web/public/js/vendor/ckeditor5/translations/tr.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tr.js rename to src/web/public/js/vendor/ckeditor5/translations/tr.js diff --git a/src/web/public/js/ckeditor5/translations/tr.umd.js b/src/web/public/js/vendor/ckeditor5/translations/tr.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tr.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/tr.umd.js diff --git a/src/web/public/js/ckeditor5/translations/tt.d.ts b/src/web/public/js/vendor/ckeditor5/translations/tt.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/tt.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/tt.d.ts diff --git a/src/web/public/js/ckeditor5/translations/tt.js b/src/web/public/js/vendor/ckeditor5/translations/tt.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tt.js rename to src/web/public/js/vendor/ckeditor5/translations/tt.js diff --git a/src/web/public/js/ckeditor5/translations/tt.umd.js b/src/web/public/js/vendor/ckeditor5/translations/tt.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/tt.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/tt.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ug.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ug.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ug.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ug.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ug.js b/src/web/public/js/vendor/ckeditor5/translations/ug.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ug.js rename to src/web/public/js/vendor/ckeditor5/translations/ug.js diff --git a/src/web/public/js/ckeditor5/translations/ug.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ug.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ug.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ug.umd.js diff --git a/src/web/public/js/ckeditor5/translations/uk.d.ts b/src/web/public/js/vendor/ckeditor5/translations/uk.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/uk.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/uk.d.ts diff --git a/src/web/public/js/ckeditor5/translations/uk.js b/src/web/public/js/vendor/ckeditor5/translations/uk.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/uk.js rename to src/web/public/js/vendor/ckeditor5/translations/uk.js diff --git a/src/web/public/js/ckeditor5/translations/uk.umd.js b/src/web/public/js/vendor/ckeditor5/translations/uk.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/uk.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/uk.umd.js diff --git a/src/web/public/js/ckeditor5/translations/ur.d.ts b/src/web/public/js/vendor/ckeditor5/translations/ur.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/ur.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/ur.d.ts diff --git a/src/web/public/js/ckeditor5/translations/ur.js b/src/web/public/js/vendor/ckeditor5/translations/ur.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ur.js rename to src/web/public/js/vendor/ckeditor5/translations/ur.js diff --git a/src/web/public/js/ckeditor5/translations/ur.umd.js b/src/web/public/js/vendor/ckeditor5/translations/ur.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/ur.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/ur.umd.js diff --git a/src/web/public/js/ckeditor5/translations/uz.d.ts b/src/web/public/js/vendor/ckeditor5/translations/uz.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/uz.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/uz.d.ts diff --git a/src/web/public/js/ckeditor5/translations/uz.js b/src/web/public/js/vendor/ckeditor5/translations/uz.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/uz.js rename to src/web/public/js/vendor/ckeditor5/translations/uz.js diff --git a/src/web/public/js/ckeditor5/translations/uz.umd.js b/src/web/public/js/vendor/ckeditor5/translations/uz.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/uz.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/uz.umd.js diff --git a/src/web/public/js/ckeditor5/translations/vi.d.ts b/src/web/public/js/vendor/ckeditor5/translations/vi.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/vi.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/vi.d.ts diff --git a/src/web/public/js/ckeditor5/translations/vi.js b/src/web/public/js/vendor/ckeditor5/translations/vi.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/vi.js rename to src/web/public/js/vendor/ckeditor5/translations/vi.js diff --git a/src/web/public/js/ckeditor5/translations/vi.umd.js b/src/web/public/js/vendor/ckeditor5/translations/vi.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/vi.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/vi.umd.js diff --git a/src/web/public/js/ckeditor5/translations/zh-cn.d.ts b/src/web/public/js/vendor/ckeditor5/translations/zh-cn.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh-cn.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/zh-cn.d.ts diff --git a/src/web/public/js/ckeditor5/translations/zh-cn.js b/src/web/public/js/vendor/ckeditor5/translations/zh-cn.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh-cn.js rename to src/web/public/js/vendor/ckeditor5/translations/zh-cn.js diff --git a/src/web/public/js/ckeditor5/translations/zh-cn.umd.js b/src/web/public/js/vendor/ckeditor5/translations/zh-cn.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh-cn.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/zh-cn.umd.js diff --git a/src/web/public/js/ckeditor5/translations/zh.d.ts b/src/web/public/js/vendor/ckeditor5/translations/zh.d.ts similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh.d.ts rename to src/web/public/js/vendor/ckeditor5/translations/zh.d.ts diff --git a/src/web/public/js/ckeditor5/translations/zh.js b/src/web/public/js/vendor/ckeditor5/translations/zh.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh.js rename to src/web/public/js/vendor/ckeditor5/translations/zh.js diff --git a/src/web/public/js/ckeditor5/translations/zh.umd.js b/src/web/public/js/vendor/ckeditor5/translations/zh.umd.js similarity index 100% rename from src/web/public/js/ckeditor5/translations/zh.umd.js rename to src/web/public/js/vendor/ckeditor5/translations/zh.umd.js diff --git a/src/web/public/js/sortable.min.js b/src/web/public/js/vendor/sortable.min.js similarity index 100% rename from src/web/public/js/sortable.min.js rename to src/web/public/js/vendor/sortable.min.js diff --git a/src/web/routes/account/password.js b/src/web/routes/account/password.js index 0b6ec1a..8686bc5 100644 --- a/src/web/routes/account/password.js +++ b/src/web/routes/account/password.js @@ -1,12 +1,24 @@ const { renderView } = require('../../view'); -module.exports = function renderAccountPage(currentUser, message) { +function normalizeReturnUrl(value) { + const url = String(value || '').trim(); + if (!url || url === '/admin/account' || url.indexOf('/admin/account?') === 0) { + return '/admin'; + } + if (!/^\/admin(?:\/|\?|$)/.test(url)) { + return '/admin'; + } + return url; +} + +module.exports = function renderAccountPage(currentUser, message, returnUrl) { return renderView('account/password', { title: 'My account', active: 'account', currentUser: currentUser || null, message: message || '', username: currentUser ? currentUser.username : '', - name: currentUser ? String(currentUser.name || '') : '' + name: currentUser ? String(currentUser.name || '') : '', + returnUrl: normalizeReturnUrl(returnUrl) }); }; \ No newline at end of file diff --git a/src/web/routes/admin-account.js b/src/web/routes/admin-account.js new file mode 100644 index 0000000..d53e1e6 --- /dev/null +++ b/src/web/routes/admin-account.js @@ -0,0 +1,69 @@ +module.exports = function registerAdminAccountRoutes(app, deps) { + const pool = deps.pool; + const pages = deps.pages; + const formatDashboardDate = deps.formatDashboardDate; + const getAuditUserId = deps.getAuditUserId; + const verifyPassword = deps.verifyPassword; + const hashPassword = deps.hashPassword; + const createUserSession = deps.createUserSession; + const setSessionCookie = deps.setSessionCookie; + + app.get('/admin/account', function (req, res) { + res.send(pages.renderAccountPage(req.currentUser, req.query.message ? String(req.query.message) : '', req.query.return_url ? String(req.query.return_url) : '')); + }); + + app.post('/admin/account/name', async function (req, res, next) { + try { + const name = String(req.body.name || '').trim(); + if (!name) { + return res.status(400).send('Name is required.'); + } + + const actorId = getAuditUserId(req); + const [result] = await pool.query('UPDATE users SET name = ?, modified_by = ? WHERE id = ?', [name, actorId, req.currentUser.id]); + if (!result.affectedRows) { + return res.status(404).send('User not found.'); + } + + res.redirect('/admin/account?message=' + encodeURIComponent('Name updated.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/account/password', async function (req, res, next) { + try { + const currentPassword = String(req.body.current_password || ''); + const newPassword = String(req.body.new_password || ''); + const confirmPassword = String(req.body.confirm_password || ''); + + const [rows] = await pool.query('SELECT id, name, username, password_hash, password_salt, password_iterations FROM users WHERE id = ? LIMIT 1', [req.currentUser.id]); + const user = rows[0] || null; + if (!user) { + return res.status(404).send('User not found.'); + } + if (!verifyPassword(currentPassword, user)) { + return res.status(400).send('Current password is incorrect.'); + } + if (!newPassword || newPassword.length < 8) { + return res.status(400).send('New password must be at least 8 characters.'); + } + if (newPassword !== confirmPassword) { + return res.status(400).send('New passwords do not match.'); + } + + const passwordRecord = hashPassword(newPassword); + await pool.query( + 'UPDATE users SET password_hash = ?, password_salt = ?, password_iterations = ?, modified_by = ? WHERE id = ?', + [passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, getAuditUserId(req), user.id] + ); + await pool.query('DELETE FROM auth_sessions WHERE user_id = ?', [user.id]); + + const token = await createUserSession(pool, user.id); + setSessionCookie(res, token); + res.redirect('/admin/account?message=' + encodeURIComponent('Password updated.')); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/admin-content.js b/src/web/routes/admin-content.js new file mode 100644 index 0000000..1530bea --- /dev/null +++ b/src/web/routes/admin-content.js @@ -0,0 +1,392 @@ +module.exports = function registerAdminContentRoutes(app, deps) { + const pool = deps.pool; + const common = deps.common; + const pages = deps.pages; + const upload = deps.upload; + const fetchScreensBySlideId = deps.fetchScreensBySlideId; + const fetchScreensByTemplateId = deps.fetchScreensByTemplateId; + const collectUploadReferencesFromSlide = deps.collectUploadReferencesFromSlide; + const collectUploadReferencesFromTemplate = deps.collectUploadReferencesFromTemplate; + const collectUploadReferencesFromPayload = deps.collectUploadReferencesFromPayload; + const syncPlaylistUploadsOnChange = deps.syncPlaylistUploadsOnChange; + const getAuditUserId = deps.getAuditUserId; + const redirectAfterSave = deps.redirectAfterSave; + const notifyPlayerScreens = deps.notifyPlayerScreens; + const broadcastDashboardState = deps.broadcastDashboardState; + const getSlideDeleteBlockMessage = deps.getSlideDeleteBlockMessage; + const getTemplateDeleteBlockMessage = deps.getTemplateDeleteBlockMessage; + const getCanvasSizeDeleteBlockMessage = deps.getCanvasSizeDeleteBlockMessage; + + if (!pool || !common || !pages || !upload || typeof fetchScreensBySlideId !== 'function' || typeof fetchScreensByTemplateId !== 'function' || typeof collectUploadReferencesFromSlide !== 'function' || typeof collectUploadReferencesFromTemplate !== 'function' || typeof collectUploadReferencesFromPayload !== 'function' || typeof syncPlaylistUploadsOnChange !== 'function' || typeof getAuditUserId !== 'function' || typeof redirectAfterSave !== 'function' || typeof notifyPlayerScreens !== 'function' || typeof broadcastDashboardState !== 'function' || typeof getSlideDeleteBlockMessage !== 'function' || typeof getTemplateDeleteBlockMessage !== 'function' || typeof getCanvasSizeDeleteBlockMessage !== 'function') { + throw new Error('registerAdminContentRoutes requires the content route dependencies.'); + } + + async function canvasSizeExists(width, height, ignoreId) { + const params = [width, height]; + let query = 'SELECT COUNT(*) AS count FROM canvas_sizes WHERE width = ? AND height = ?'; + if (ignoreId) { + query += ' AND id <> ?'; + params.push(ignoreId); + } + const [rows] = await pool.query(query, params); + return Number(rows[0] && rows[0].count) > 0; + } + + async function fetchScreenSlideCountsBySlug(screenSlugs) { + const uniqueSlugs = Array.from(new Set(Array.isArray(screenSlugs) ? screenSlugs : [])).map(function (value) { + return String(value || '').trim(); + }).filter(Boolean); + if (!uniqueSlugs.length) { + return {}; + } + + const [rows] = await pool.query( + `SELECT s.slug, COUNT(ps.id) AS slide_count + FROM screens s + LEFT JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id + WHERE s.slug IN (?) + GROUP BY s.id, s.slug`, + [uniqueSlugs] + ); + + return rows.reduce(function (counts, row) { + counts[String(row.slug || '').trim()] = Number(row.slide_count) || 0; + return counts; + }, {}); + } + + app.get('/admin/slides', async function (req, res, next) { + try { + const data = await common.fetchAdminData(pool); + res.send(pages.renderSlidesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/slides/new', async function (req, res, next) { + try { + const data = await common.fetchTemplatesData(pool); + res.send(pages.renderSlideFormPage(data, 'create', null, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/slides/:id/edit', async function (req, res, next) { + try { + const slide = await common.fetchSlideById(pool, Number(req.params.id)); + if (!slide) { + return res.status(404).send('Slide not found'); + } + const data = await common.fetchTemplatesData(pool); + res.send(pages.renderSlideFormPage(data, 'edit', slide, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/slides', upload.any(), async function (req, res, next) { + try { + const payload = await common.buildSlidePayload(pool, req, null); + const actorId = getAuditUserId(req); + const [result] = await pool.query( + 'INSERT INTO slides (title, body, template_id, content_json, media_path, media_type, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', + [payload.title, payload.body, payload.templateId, payload.contentJson, payload.mediaPath, payload.mediaType, actorId, actorId] + ); + await syncPlaylistUploadsOnChange({ + key: 'slide:create:' + result.insertId, + pool: pool, + localUploadDir: deps.uploadDir, + nextUploadRefs: collectUploadReferencesFromPayload(payload) + }); + redirectAfterSave(req, res, '/admin/slides/' + result.insertId + '/edit', { + closeUrl: '/admin/slides', + newUrl: '/admin/slides/new', + message: 'Slide created.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/slides/:id', upload.any(), async function (req, res, next) { + try { + const slide = await common.fetchSlideById(pool, Number(req.params.id)); + if (!slide) { + return res.status(404).send('Slide not found'); + } + const affectedScreens = await fetchScreensBySlideId(pool, slide.id); + const screenSlideCounts = await fetchScreenSlideCountsBySlug(affectedScreens); + const existingUploadRefs = collectUploadReferencesFromSlide(slide); + const payload = await common.buildSlidePayload(pool, req, slide); + const nextUploadRefs = collectUploadReferencesFromPayload(payload); + const actorId = getAuditUserId(req); + await pool.query( + 'UPDATE slides SET title = ?, body = ?, template_id = ?, content_json = ?, media_path = ?, media_type = ?, modified_by = ? WHERE id = ?', + [payload.title, payload.body, payload.templateId, payload.contentJson, payload.mediaPath, payload.mediaType, actorId, slide.id] + ); + await syncPlaylistUploadsOnChange({ + key: 'slide:update:' + slide.id, + pool: pool, + localUploadDir: deps.uploadDir, + previousUploadRefs: existingUploadRefs, + nextUploadRefs: nextUploadRefs, + blockedSlideIds: [slide.id], + refreshScreenSlugs: affectedScreens, + screenSlideCounts: screenSlideCounts + }); + await broadcastDashboardState(); + redirectAfterSave(req, res, '/admin/slides/' + slide.id + '/edit', { + closeUrl: '/admin/slides', + newUrl: '/admin/slides/new', + message: 'Slide updated.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/slides/:id/delete', async function (req, res, next) { + try { + const slide = await common.fetchSlideById(pool, Number(req.params.id)); + if (!slide) { + return res.status(404).send('Slide not found'); + } + const blockMessage = await getSlideDeleteBlockMessage(pool, slide); + if (blockMessage) { + return res.redirect('/admin/slides?message=' + encodeURIComponent(blockMessage)); + } + const affectedScreens = await fetchScreensBySlideId(pool, slide.id); + const screenSlideCounts = await fetchScreenSlideCountsBySlug(affectedScreens); + const uploadRefs = collectUploadReferencesFromSlide(slide); + await pool.query('DELETE FROM slides WHERE id = ?', [slide.id]); + await syncPlaylistUploadsOnChange({ + key: 'slide:delete:' + slide.id, + pool: pool, + localUploadDir: deps.uploadDir, + previousUploadRefs: uploadRefs, + blockedSlideIds: [slide.id], + refreshScreenSlugs: affectedScreens, + screenSlideCounts: screenSlideCounts + }); + await broadcastDashboardState(); + res.redirect('/admin/slides?message=' + encodeURIComponent('Slide deleted.')); + } catch (error) { + next(error); + } + }); + + app.get('/admin/templates', async function (req, res, next) { + try { + const data = await common.fetchTemplatesData(pool); + res.send(pages.renderTemplatesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/templates/new', async function (req, res, next) { + try { + const data = await common.fetchCanvasSizesData(pool); + res.send(pages.renderTemplateFormPage(null, 'create', req.query.message ? String(req.query.message) : '', data.canvasSizes, req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/templates', upload.any(), async function (req, res, next) { + try { + const payload = await common.buildTemplatePayload(pool, req, null); + const actorId = getAuditUserId(req); + const [result] = await pool.query( + 'INSERT INTO slide_templates (name, canvas_size_id, background_image_path, background_color, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?)', + [payload.name, payload.canvasSizeId, payload.backgroundImagePath, payload.backgroundColor, actorId, actorId] + ); + for (let i = 0; i < payload.regions.length; i += 1) { + const region = payload.regions[i]; + await pool.query( + 'INSERT INTO slide_template_regions (template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [result.insertId, region.region_key, region.region_type, region.label, region.font_family, region.x, region.y, region.width, region.height, region.z_index, actorId, actorId] + ); + } + await syncPlaylistUploadsOnChange({ + key: 'template:create:' + result.insertId, + pool: pool, + localUploadDir: deps.uploadDir, + nextUploadRefs: collectUploadReferencesFromPayload(payload) + }); + redirectAfterSave(req, res, '/admin/templates/' + result.insertId + '/edit', { + closeUrl: '/admin/templates', + newUrl: '/admin/templates/new', + message: 'Template created.' + }); + } catch (error) { + next(error); + } + }); + + app.get('/admin/templates/:id/edit', async function (req, res, next) { + try { + const template = await common.fetchTemplateById(pool, Number(req.params.id)); + if (!template) { + return res.status(404).send('Template not found'); + } + const sizeData = await common.fetchCanvasSizesData(pool); + res.send(pages.renderTemplateFormPage(template, 'edit', req.query.message ? String(req.query.message) : '', sizeData.canvasSizes, req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/templates/:id', upload.any(), async function (req, res, next) { + try { + const template = await common.fetchTemplateById(pool, Number(req.params.id)); + if (!template) { + return res.status(404).send('Template not found'); + } + const existingUploadRefs = collectUploadReferencesFromTemplate(template); + const payload = await common.buildTemplatePayload(pool, req, template); + const nextUploadRefs = collectUploadReferencesFromPayload(payload); + const affectedScreens = await fetchScreensByTemplateId(pool, template.id); + const actorId = getAuditUserId(req); + await pool.query( + 'UPDATE slide_templates SET name = ?, canvas_size_id = ?, background_image_path = ?, background_color = ?, modified_by = ? WHERE id = ?', + [payload.name, payload.canvasSizeId, payload.backgroundImagePath, payload.backgroundColor, actorId, template.id] + ); + await pool.query('DELETE FROM slide_template_regions WHERE template_id = ?', [template.id]); + for (let i = 0; i < payload.regions.length; i += 1) { + const region = payload.regions[i]; + await pool.query( + 'INSERT INTO slide_template_regions (template_id, region_key, region_type, label, font_family, x, y, width, height, z_index, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [template.id, region.region_key, region.region_type, region.label, region.font_family, region.x, region.y, region.width, region.height, region.z_index, actorId, actorId] + ); + } + await syncPlaylistUploadsOnChange({ + key: 'template:update:' + template.id, + pool: pool, + localUploadDir: deps.uploadDir, + previousUploadRefs: existingUploadRefs, + nextUploadRefs: nextUploadRefs + }); + await notifyPlayerScreens(affectedScreens, 'refresh'); + redirectAfterSave(req, res, '/admin/templates/' + template.id + '/edit', { + closeUrl: '/admin/templates', + newUrl: '/admin/templates/new', + message: 'Template updated.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/templates/:id/delete', async function (req, res, next) { + try { + const template = await common.fetchTemplateById(pool, Number(req.params.id)); + if (!template) { + return res.status(404).send('Template not found'); + } + const blockMessage = await getTemplateDeleteBlockMessage(pool, template); + if (blockMessage) { + return res.redirect('/admin/templates?message=' + encodeURIComponent(blockMessage)); + } + const uploadRefs = collectUploadReferencesFromTemplate(template); + const affectedScreens = await fetchScreensByTemplateId(pool, template.id); + await pool.query('UPDATE slides SET template_id = NULL, modified_by = ? WHERE template_id = ?', [getAuditUserId(req), template.id]); + await pool.query('DELETE FROM slide_template_regions WHERE template_id = ?', [template.id]); + await pool.query('DELETE FROM slide_templates WHERE id = ?', [template.id]); + await syncPlaylistUploadsOnChange({ + key: 'template:delete:' + template.id, + pool: pool, + localUploadDir: deps.uploadDir, + previousUploadRefs: uploadRefs + }); + await notifyPlayerScreens(affectedScreens, 'refresh'); + res.redirect('/admin/templates?message=' + encodeURIComponent('Template deleted.')); + } catch (error) { + next(error); + } + }); + + app.get('/admin/canvas-sizes', async function (req, res, next) { + try { + const data = await common.fetchAdminData(pool); + res.send(pages.renderCanvasSizesPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/canvas-sizes/new', function (req, res) { + res.send(pages.renderCanvasSizeFormPage(null, 'create', req.query.message ? String(req.query.message) : '', req.currentUser)); + }); + + app.post('/admin/canvas-sizes', async function (req, res, next) { + try { + const payload = common.buildCanvasSizePayload(req, null); + if (await canvasSizeExists(payload.width, payload.height)) { + return res.redirect('/admin/canvas-sizes/new?message=' + encodeURIComponent('That canvas size already exists.')); + } + const actorId = getAuditUserId(req); + await pool.query('INSERT INTO canvas_sizes (name, width, height, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [payload.name, payload.width, payload.height, actorId, actorId]); + redirectAfterSave(req, res, '/admin/canvas-sizes', { + closeUrl: '/admin/canvas-sizes', + newUrl: '/admin/canvas-sizes/new', + message: 'Canvas size created.' + }); + } catch (error) { + next(error); + } + }); + + app.get('/admin/canvas-sizes/:id/edit', async function (req, res, next) { + try { + const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); + if (!canvasSize) { + return res.status(404).send('Canvas size not found'); + } + res.send(pages.renderCanvasSizeEditPage(canvasSize, null, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/canvas-sizes/:id', async function (req, res, next) { + try { + const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); + if (!canvasSize) { + return res.status(404).send('Canvas size not found'); + } + const payload = common.buildCanvasSizePayload(req, canvasSize); + if (await canvasSizeExists(payload.width, payload.height, canvasSize.id)) { + return res.redirect('/admin/canvas-sizes/' + canvasSize.id + '/edit?message=' + encodeURIComponent('That canvas size already exists.')); + } + await pool.query('UPDATE canvas_sizes SET name = ?, width = ?, height = ?, modified_by = ? WHERE id = ?', [payload.name, payload.width, payload.height, getAuditUserId(req), canvasSize.id]); + redirectAfterSave(req, res, '/admin/canvas-sizes', { + closeUrl: '/admin/canvas-sizes', + newUrl: '/admin/canvas-sizes/new', + message: 'Canvas size updated.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/canvas-sizes/:id/delete', async function (req, res, next) { + try { + const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id)); + if (!canvasSize) { + return res.status(404).send('Canvas size not found'); + } + const blockMessage = await getCanvasSizeDeleteBlockMessage(pool, canvasSize); + if (blockMessage) { + return res.redirect('/admin/canvas-sizes?message=' + encodeURIComponent(blockMessage)); + } + await pool.query('UPDATE slide_templates SET canvas_size_id = NULL, modified_by = ? WHERE canvas_size_id = ?', [getAuditUserId(req), canvasSize.id]); + await pool.query('DELETE FROM canvas_sizes WHERE id = ?', [canvasSize.id]); + res.redirect('/admin/canvas-sizes?message=' + encodeURIComponent('Canvas size deleted.')); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/admin-manage.js b/src/web/routes/admin-manage.js new file mode 100644 index 0000000..175e059 --- /dev/null +++ b/src/web/routes/admin-manage.js @@ -0,0 +1,542 @@ +module.exports = function registerAdminManageRoutes(app, deps) { + const pool = deps.pool; + const common = deps.common; + const pages = deps.pages; + const fetchOrderedPlaylistSlides = deps.fetchOrderedPlaylistSlides; + const fetchScreensByPlaylistId = deps.fetchScreensByPlaylistId; + const fetchPlaylistCanvasSignature = deps.fetchPlaylistCanvasSignature; + const getCanvasSignature = deps.getCanvasSignature; + const normalizeScheduleMode = deps.normalizeScheduleMode; + const parseDateTimeLocal = deps.parseDateTimeLocal; + const parseTimeLocal = deps.parseTimeLocal; + const readArrayField = deps.readArrayField; + const getAuditUserId = deps.getAuditUserId; + const redirectAfterSave = deps.redirectAfterSave; + const notifyPlayerScreens = deps.notifyPlayerScreens; + const broadcastDashboardState = deps.broadcastDashboardState; + const getScreenDeleteBlockMessage = deps.getScreenDeleteBlockMessage; + const getPlaylistDeleteBlockMessage = deps.getPlaylistDeleteBlockMessage; + const forwardPlayerCommand = deps.forwardPlayerCommand; + const PLAYER_PUBLIC_BASE_URL = deps.playerPublicBaseUrl; + + app.post('/admin/playlists', async function (req, res, next) { + try { + const name = String(req.body.name || '').trim(); + const fadeBetweenSlides = req.body.fade_between_slides ? 1 : 0; + if (!name) { + return res.status(400).send('Playlist name is required.'); + } + const actorId = getAuditUserId(req); + await pool.query('INSERT INTO playlists (name, fade_between_slides, created_by, modified_by) VALUES (?, ?, ?, ?)', [name, fadeBetweenSlides, actorId, actorId]); + redirectAfterSave(req, res, '/admin/playlists', { + closeUrl: '/admin/playlists', + newUrl: '/admin/playlists/new', + message: 'Playlist created.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id', async function (req, res, next) { + const connection = await pool.getConnection(); + try { + const name = String(req.body.name || '').trim(); + const fadeBetweenSlides = req.body.fade_between_slides ? 1 : 0; + if (!name) { + return res.status(400).send('Playlist name is required.'); + } + const playlist = await common.fetchPlaylistById(connection, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + + const affectedScreens = await fetchScreensByPlaylistId(connection, playlist.id); + + const slideIds = readArrayField(req.body, ['slide_id[]', 'slide_id']); + const durations = readArrayField(req.body, ['duration_seconds[]', 'duration_seconds']); + const scheduleModes = readArrayField(req.body, ['schedule_mode[]', 'schedule_mode']); + const scheduleStartDateTimes = readArrayField(req.body, ['schedule_start_datetime[]', 'schedule_start_datetime']); + const scheduleEndDateTimes = readArrayField(req.body, ['schedule_end_datetime[]', 'schedule_end_datetime']); + const scheduleStartTimes = readArrayField(req.body, ['schedule_start_time[]', 'schedule_start_time']); + const scheduleEndTimes = readArrayField(req.body, ['schedule_end_time[]', 'schedule_end_time']); + const scheduleDaysJsonValues = readArrayField(req.body, ['schedule_days_json[]', 'schedule_days_json']); + + if (durations.length && durations.length !== slideIds.length) { + return res.status(400).send('Playlist slide data is invalid.'); + } + if (scheduleModes.length && scheduleModes.length !== slideIds.length) { + return res.status(400).send('Playlist schedule data is invalid.'); + } + + const normalizedSlides = []; + const seenSlideIds = new Set(); + for (let i = 0; i < slideIds.length; i += 1) { + const slideId = Number(slideIds[i]); + if (!Number.isInteger(slideId) || slideId <= 0) { + return res.status(400).send('Invalid slide selection.'); + } + if (seenSlideIds.has(slideId)) { + return res.status(400).send('A slide can only be added to a playlist once.'); + } + seenSlideIds.add(slideId); + + const durationRaw = Number(durations[i]); + const durationSeconds = Number.isFinite(durationRaw) ? Math.max(1, Math.trunc(durationRaw)) : 10; + const scheduleMode = normalizeScheduleMode(scheduleModes[i]); + + let scheduleStartDatetime = null; + let scheduleEndDatetime = null; + let scheduleStartTime = null; + let scheduleEndTime = null; + let scheduleDaysJson = null; + + if (scheduleMode === 'dates') { + scheduleStartDatetime = parseDateTimeLocal(scheduleStartDateTimes[i]); + scheduleEndDatetime = parseDateTimeLocal(scheduleEndDateTimes[i]); + if (!scheduleStartDatetime || !scheduleEndDatetime) { + return res.status(400).send('Start and end datetimes are required for date scheduling.'); + } + if (scheduleEndDatetime < scheduleStartDatetime) { + return res.status(400).send('End datetime must be after start datetime.'); + } + } else if (scheduleMode === 'times') { + scheduleStartTime = parseTimeLocal(scheduleStartTimes[i]); + scheduleEndTime = parseTimeLocal(scheduleEndTimes[i]); + if (!scheduleStartTime || !scheduleEndTime) { + return res.status(400).send('Start and end times are required for time scheduling.'); + } + + let scheduleDays = []; + try { + const parsedDays = JSON.parse(String(scheduleDaysJsonValues[i] || '[]')); + scheduleDays = Array.isArray(parsedDays) ? parsedDays : []; + } catch (_error) { + scheduleDays = []; + } + scheduleDays = scheduleDays + .map(function (value) { return Number(value); }) + .filter(function (value) { return Number.isInteger(value) && value >= 0 && value <= 6; }); + if (!scheduleDays.length) { + return res.status(400).send('Select at least one day for time scheduling.'); + } + scheduleDaysJson = JSON.stringify(Array.from(new Set(scheduleDays)).sort()); + } + + normalizedSlides.push({ + slideId, + position: i, + durationSeconds, + scheduleMode, + scheduleStartDatetime, + scheduleEndDatetime, + scheduleStartTime, + scheduleEndTime, + scheduleDaysJson + }); + } + + if (normalizedSlides.length) { + const [slides] = await connection.query( + `SELECT sl.id, cs.width AS canvas_width, cs.height AS canvas_height + FROM slides sl + LEFT JOIN slide_templates st ON st.id = sl.template_id + LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id + WHERE sl.id IN (?)`, + [normalizedSlides.map(function (item) { return item.slideId; })] + ); + if (slides.length !== normalizedSlides.length) { + return res.status(400).send('One or more selected slides no longer exist.'); + } + const signatures = Array.from(new Set( + slides + .map(function (slide) { return getCanvasSignature(slide.canvas_width, slide.canvas_height); }) + .filter(Boolean) + )); + if (signatures.length > 1) { + return res.status(400).send('All playlist slides must share the same canvas size.'); + } + } + + const actorId = getAuditUserId(req); + + await connection.beginTransaction(); + await connection.query('UPDATE playlists SET name = ?, fade_between_slides = ?, modified_by = ? WHERE id = ?', [name, fadeBetweenSlides, actorId, playlist.id]); + await connection.query('DELETE FROM playlist_slides WHERE playlist_id = ?', [playlist.id]); + for (let i = 0; i < normalizedSlides.length; i += 1) { + const item = normalizedSlides[i]; + await connection.query( + 'INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, schedule_mode, schedule_start_datetime, schedule_end_datetime, schedule_start_time, schedule_end_time, schedule_days_json, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [ + playlist.id, + item.slideId, + item.position, + item.durationSeconds, + item.scheduleMode, + item.scheduleStartDatetime, + item.scheduleEndDatetime, + item.scheduleStartTime, + item.scheduleEndTime, + item.scheduleDaysJson, + actorId, + actorId + ] + ); + } + await connection.commit(); + await notifyPlayerScreens(affectedScreens, 'refresh'); + await broadcastDashboardState(); + redirectAfterSave(req, res, '/admin/playlists?edit=' + playlist.id, { + closeUrl: '/admin/playlists', + newUrl: '/admin/playlists/new', + message: 'Playlist updated.' + }); + } catch (error) { + try { + await connection.rollback(); + } catch (_rollbackError) { + // Ignore rollback failures and surface the original error. + } + next(error); + } finally { + connection.release(); + } + }); + + app.post('/admin/playlists/:id/delete', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const blockMessage = await getPlaylistDeleteBlockMessage(pool, playlist); + if (blockMessage) { + return res.redirect('/admin/playlists?message=' + encodeURIComponent(blockMessage)); + } + await pool.query('DELETE FROM playlists WHERE id = ?', [playlist.id]); + res.redirect('/admin/playlists?message=' + encodeURIComponent('Playlist deleted.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id/slides', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const slideId = Number(req.body.slide_id); + if (!slideId) { + return res.status(400).send('Slide is required.'); + } + const playlistCanvasSignature = await fetchPlaylistCanvasSignature(pool, playlist.id); + if (playlistCanvasSignature === 'mismatch') { + return res.status(400).send('This playlist already contains slides with different canvas sizes.'); + } + const slide = await common.fetchSlideById(pool, slideId); + if (!slide) { + return res.status(404).send('Slide not found'); + } + const slideCanvasSignature = getCanvasSignature(slide.canvas_width, slide.canvas_height); + if (playlistCanvasSignature && slideCanvasSignature !== playlistCanvasSignature) { + return res.status(400).send('The slide canvas size must match the existing playlist items.'); + } + const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10)); + const [positionRows] = await pool.query('SELECT COALESCE(MAX(position), -1) AS max_position FROM playlist_slides WHERE playlist_id = ?', [playlist.id]); + const nextPosition = Number(positionRows[0].max_position) + 1; + const actorId = getAuditUserId(req); + await pool.query('INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?)', [playlist.id, slideId, nextPosition, durationSeconds, actorId, actorId]); + await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); + await broadcastDashboardState(); + res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide added to playlist.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id/slides/:playlistSlideId', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const playlistSlideId = Number(req.params.playlistSlideId); + const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10)); + const actorId = getAuditUserId(req); + const [result] = await pool.query( + 'UPDATE playlist_slides SET duration_seconds = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', + [durationSeconds, actorId, playlistSlideId, playlist.id] + ); + if (!result.affectedRows) { + return res.status(404).send('Playlist slide not found'); + } + await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); + await broadcastDashboardState(); + res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide duration updated.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id/slides/:playlistSlideId/move', async function (req, res, next) { + const connection = await pool.getConnection(); + try { + const playlist = await common.fetchPlaylistById(connection, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const playlistSlideId = Number(req.params.playlistSlideId); + const direction = String(req.body.direction || '').toLowerCase(); + if (direction !== 'up' && direction !== 'down') { + return res.status(400).send('Invalid move direction.'); + } + + await connection.beginTransaction(); + const orderedSlides = await fetchOrderedPlaylistSlides(connection, playlist.id); + const currentIndex = orderedSlides.findIndex(function (item) { + return Number(item.id) === playlistSlideId; + }); + if (currentIndex === -1) { + await connection.rollback(); + return res.status(404).send('Playlist slide not found'); + } + + const swapIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1; + if (swapIndex < 0 || swapIndex >= orderedSlides.length) { + await connection.rollback(); + return res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide is already at the ' + (direction === 'up' ? 'top' : 'bottom') + '.')); + } + + const currentSlide = orderedSlides[currentIndex]; + const swapSlide = orderedSlides[swapIndex]; + const actorId = getAuditUserId(req); + + await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [swapSlide.position, actorId, currentSlide.id, playlist.id]); + await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [currentSlide.position, actorId, swapSlide.id, playlist.id]); + await connection.commit(); + await notifyPlayerScreens(await fetchScreensByPlaylistId(connection, playlist.id), 'refresh'); + await broadcastDashboardState(); + res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide order updated.')); + } catch (error) { + await connection.rollback(); + next(error); + } finally { + connection.release(); + } + }); + + app.get('/admin/playlists/:id/slides/:playlistSlideId/config', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const data = await common.fetchAdminData(pool); + let playlistSlide = (data.playlistSlides || []).find(function (item) { + return item.id === Number(req.params.playlistSlideId) && item.playlist_id === playlist.id; + }); + if (!playlistSlide && Number(req.params.playlistSlideId) !== 0) { + return res.status(404).send('Playlist slide not found'); + } + const scheduleMode = typeof req.query.schedule_mode === 'string' && req.query.schedule_mode ? String(req.query.schedule_mode) : String(playlistSlide && playlistSlide.schedule_mode || 'always'); + const scheduleStartDatetime = typeof req.query.schedule_start_datetime === 'string' ? String(req.query.schedule_start_datetime) : (playlistSlide && playlistSlide.schedule_start_datetime) || null; + const scheduleEndDatetime = typeof req.query.schedule_end_datetime === 'string' ? String(req.query.schedule_end_datetime) : (playlistSlide && playlistSlide.schedule_end_datetime) || null; + const scheduleStartTime = typeof req.query.schedule_start_time === 'string' ? String(req.query.schedule_start_time) : (playlistSlide && playlistSlide.schedule_start_time) || null; + const scheduleEndTime = typeof req.query.schedule_end_time === 'string' ? String(req.query.schedule_end_time) : (playlistSlide && playlistSlide.schedule_end_time) || null; + const scheduleDaysJson = typeof req.query.schedule_days_json === 'string' ? String(req.query.schedule_days_json) : (playlistSlide && playlistSlide.schedule_days_json) || '[]'; + const scheduleDays = common.parseJsonSafe(scheduleDaysJson) || []; + + playlistSlide = Object.assign({}, playlistSlide || {}, { + id: playlistSlide ? playlistSlide.id : 0, + schedule_mode: scheduleMode, + schedule_days_json: scheduleDaysJson, + schedule_days: scheduleDays, + schedule_start_datetime: scheduleStartDatetime, + schedule_end_datetime: scheduleEndDatetime, + schedule_start_time: scheduleStartTime, + schedule_end_time: scheduleEndTime + }); + return res.send(pages.renderPlaylistSlideConfigPage(playlist, playlistSlide, req.query.message ? String(req.query.message) : '', req.query.row_key ? String(req.query.row_key) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id/slides/:playlistSlideId/config', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const rowKey = String(req.body.row_key || '').trim(); + if (rowKey) { + return res.status(400).send('Schedule changes from the playlist editor are staged until you click Save changes.'); + } + const playlistSlideId = Number(req.params.playlistSlideId); + let scheduleMode = normalizeScheduleMode(req.body.schedule_mode); + let scheduleStartDatetime = null; + let scheduleEndDatetime = null; + let scheduleStartTime = null; + let scheduleEndTime = null; + let scheduleDaysJson = null; + + const hasDateRange = Boolean(req.body.schedule_start_datetime && req.body.schedule_end_datetime); + const hasTimeRange = Boolean(req.body.schedule_start_time && req.body.schedule_end_time); + const hasSelectedDays = Boolean(readArrayField(req.body, ['schedule_days', 'schedule_days[]']).length); + + if (scheduleMode === 'dates' && !hasDateRange) { + scheduleMode = 'always'; + } else if (scheduleMode === 'times' && (!hasTimeRange || !hasSelectedDays)) { + scheduleMode = 'always'; + } + + if (scheduleMode === 'dates') { + scheduleStartDatetime = parseDateTimeLocal(req.body.schedule_start_datetime); + scheduleEndDatetime = parseDateTimeLocal(req.body.schedule_end_datetime); + if (!scheduleStartDatetime || !scheduleEndDatetime) { + scheduleMode = 'always'; + scheduleStartDatetime = null; + scheduleEndDatetime = null; + } else if (scheduleEndDatetime < scheduleStartDatetime) { + return res.status(400).send('End datetime must be after start datetime.'); + } + } else if (scheduleMode === 'times') { + scheduleStartTime = parseTimeLocal(req.body.schedule_start_time); + scheduleEndTime = parseTimeLocal(req.body.schedule_end_time); + const scheduleDays = readArrayField(req.body, ['schedule_days', 'schedule_days[]']).map(function (value) { + return Number(value); + }).filter(function (value) { + return Number.isInteger(value) && value >= 0 && value <= 6; + }); + if (!scheduleStartTime || !scheduleEndTime) { + scheduleMode = 'always'; + scheduleStartTime = null; + scheduleEndTime = null; + scheduleDaysJson = null; + } else if (!scheduleDays.length) { + scheduleMode = 'always'; + scheduleStartTime = null; + scheduleEndTime = null; + scheduleDaysJson = null; + } else { + if (scheduleEndTime < scheduleStartTime) { + return res.status(400).send('End time must be after start time.'); + } + scheduleDaysJson = JSON.stringify(Array.from(new Set(scheduleDays)).sort()); + } + } + + const actorId = getAuditUserId(req); + const [result] = await pool.query( + 'UPDATE playlist_slides SET schedule_mode = ?, schedule_start_datetime = ?, schedule_end_datetime = ?, schedule_start_time = ?, schedule_end_time = ?, schedule_days_json = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', + [scheduleMode, scheduleStartDatetime, scheduleEndDatetime, scheduleStartTime, scheduleEndTime, scheduleDaysJson, actorId, playlistSlideId, playlist.id] + ); + if (!result.affectedRows) { + return res.status(404).send('Playlist slide not found'); + } + await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); + await broadcastDashboardState(); + res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide timings updated.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/playlists/:id/slides/:playlistSlideId/delete', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + await pool.query('DELETE FROM playlist_slides WHERE id = ? AND playlist_id = ?', [Number(req.params.playlistSlideId), playlist.id]); + await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh'); + await broadcastDashboardState(); + res.redirect('/admin/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide removed.')); + } catch (error) { + next(error); + } + }); + + app.get('/admin/screens/new', async function (req, res, next) { + try { + const data = await common.fetchScreenEditData(pool); + res.send(pages.renderScreenFormPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/screens', async function (req, res, next) { + try { + const name = String(req.body.name || '').trim(); + if (!name) { + return res.status(400).send('Screen name is required.'); + } + const slugInput = String(req.body.slug || '').trim(); + const playlistId = req.body.playlist_id ? Number(req.body.playlist_id) : null; + const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name)); + const actorId = getAuditUserId(req); + await pool.query('INSERT INTO screens (name, slug, playlist_id, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, slug, playlistId, actorId, actorId]); + redirectAfterSave(req, res, '/admin/screens', { + closeUrl: '/admin/screens', + newUrl: '/admin/screens/new', + message: 'Screen created.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/screens/:id', async function (req, res, next) { + try { + const name = String(req.body.name || '').trim(); + if (!name) { + return res.status(400).send('Screen name is required.'); + } + const screen = await common.fetchScreenById(pool, Number(req.params.id)); + if (!screen) { + return res.status(404).send('Screen not found'); + } + const slugInput = String(req.body.slug || '').trim(); + const playlistId = req.body.playlist_id ? Number(req.body.playlist_id) : null; + const previousPlaylistId = screen.playlist_id; + const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name), screen.id); + const previousSlug = String(screen.slug || '').trim(); + await pool.query('UPDATE screens SET name = ?, slug = ?, playlist_id = ?, modified_by = ? WHERE id = ?', [name, slug, playlistId, getAuditUserId(req), screen.id]); + if (previousPlaylistId !== playlistId && previousSlug) { + await notifyPlayerScreens([previousSlug], 'refresh'); + } + if (previousSlug && previousSlug !== slug) { + await forwardPlayerCommand(previousSlug, { + command: 'redirect', + url: `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(slug)}` + }); + } + redirectAfterSave(req, res, '/admin/screens?edit=' + screen.id, { + closeUrl: '/admin/screens', + newUrl: '/admin/screens/new', + message: 'Screen updated.' + }); + } catch (error) { + next(error); + } + }); + + app.post('/admin/screens/:id/delete', async function (req, res, next) { + try { + const screen = await common.fetchScreenById(pool, Number(req.params.id)); + if (!screen) { + return res.status(404).send('Screen not found'); + } + const blockMessage = await getScreenDeleteBlockMessage(pool, screen); + if (blockMessage) { + return res.redirect('/admin/screens?message=' + encodeURIComponent(blockMessage)); + } + await pool.query('DELETE FROM screens WHERE id = ?', [screen.id]); + res.redirect('/admin/screens?message=' + encodeURIComponent('Screen deleted.')); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/admin-pages.js b/src/web/routes/admin-pages.js new file mode 100644 index 0000000..d734a86 --- /dev/null +++ b/src/web/routes/admin-pages.js @@ -0,0 +1,87 @@ +module.exports = function registerAdminPagesRoutes(app, deps) { + const pool = deps.pool; + const common = deps.common; + const pages = deps.pages; + const buildDashboardState = deps.buildDashboardState; + + app.get('/admin', async function (req, res, next) { + try { + const data = await buildDashboardState(pool); + res.send(pages.renderDashboardPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/clients', async function (req, res, next) { + try { + const data = await buildDashboardState(pool); + res.send(pages.renderConnectedClientsPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/screens', async function (req, res, next) { + try { + const data = await buildDashboardState(pool); + if (req.query.edit) { + const screen = await common.fetchScreenById(pool, Number(req.query.edit)); + if (!screen) { + return res.status(404).send('Screen not found'); + } + const editData = await common.fetchScreenEditData(pool); + return res.send(pages.renderScreenEditPage(screen, editData, req.query.message ? String(req.query.message) : '', req.currentUser)); + } + res.send(pages.renderScreensPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/screens/:id/edit', async function (req, res, next) { + try { + const screen = await common.fetchScreenById(pool, Number(req.params.id)); + if (!screen) { + return res.status(404).send('Screen not found'); + } + const editData = await common.fetchScreenEditData(pool); + return res.send(pages.renderScreenEditPage(screen, editData, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/playlists', async function (req, res, next) { + try { + const data = await common.fetchAdminData(pool); + if (req.query.edit) { + const playlist = await common.fetchPlaylistById(pool, Number(req.query.edit)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + return res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } + res.send(pages.renderPlaylistsPage(data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/playlists/new', function (req, res) { + res.send(pages.renderPlaylistFormPage(req.query.message ? String(req.query.message) : '', req.currentUser)); + }); + + app.get('/admin/playlists/:id/edit', async function (req, res, next) { + try { + const playlist = await common.fetchPlaylistById(pool, Number(req.params.id)); + if (!playlist) { + return res.status(404).send('Playlist not found'); + } + const data = await common.fetchAdminData(pool); + res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/admin-screen-commands.js b/src/web/routes/admin-screen-commands.js new file mode 100644 index 0000000..5459f2e --- /dev/null +++ b/src/web/routes/admin-screen-commands.js @@ -0,0 +1,47 @@ +module.exports = function registerAdminScreenCommandRoutes(app, deps) { + const pool = deps.pool; + const forwardPlayerCommand = deps.forwardPlayerCommand; + + app.post('/admin/screens/:slug/commands', async function (req, res, next) { + try { + const slug = String(req.params.slug || '').trim(); + const command = String((req.body && req.body.command) || req.query.command || '').trim().toLowerCase(); + const connectionId = String((req.body && (req.body.connectionId || req.body.clientId)) || req.query.connectionId || req.query.clientId || '').trim(); + const blackoutValue = req.body && Object.prototype.hasOwnProperty.call(req.body, 'blackout') + ? req.body.blackout + : req.query.blackout; + + if (!slug) { + return res.status(400).json({ error: 'Screen slug is required' }); + } + if (!command) { + return res.status(400).json({ error: 'Command is required' }); + } + + const [screenRows] = await pool.query('SELECT id, name, slug FROM screens WHERE slug = ?', [slug]); + if (!screenRows.length) { + return res.status(404).json({ error: 'Screen not found' }); + } + + const commandPayload = req.body && typeof req.body === 'object' && !Array.isArray(req.body) + ? Object.assign({}, req.body, { command: command }) + : { command: command }; + if (command === 'blackout' && blackoutValue !== undefined && commandPayload && typeof commandPayload === 'object') { + commandPayload.blackout = blackoutValue; + } + + const result = connectionId + ? await forwardPlayerCommand(slug, commandPayload, connectionId) + : await forwardPlayerCommand(slug, commandPayload); + + return res.json(Object.assign({ + screen: screenRows[0], + screenSlug: slug, + command: command, + connectionId: connectionId || null + }, result && typeof result === 'object' ? result : {})); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/admin-users.js b/src/web/routes/admin-users.js new file mode 100644 index 0000000..5b74066 --- /dev/null +++ b/src/web/routes/admin-users.js @@ -0,0 +1,185 @@ +module.exports = function registerAdminUsersRoutes(app, deps) { + const pool = deps.pool; + const pages = deps.pages; + const formatDashboardDate = deps.formatDashboardDate; + const getAuditUserId = deps.getAuditUserId; + const hashPassword = deps.hashPassword; + + app.get('/admin/users', async function (req, res, next) { + try { + const [rows] = await pool.query('SELECT id, name, username, created_at, modified_at FROM users ORDER BY id ASC'); + const users = rows.map(function (user) { + return Object.assign({}, user, { + isCurrentUser: Number(user.id) === Number(req.currentUser.id), + createdAtLabel: formatDashboardDate(user.created_at), + modifiedAtLabel: formatDashboardDate(user.modified_at) + }); + }); + res.send(pages.renderUsersPage({ users: users }, req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.get('/admin/users/new', function (req, res) { + res.send(pages.renderUsersAddPage(req.query.message ? String(req.query.message) : '', req.currentUser)); + }); + + app.get('/admin/users/:id/edit', async function (req, res, next) { + try { + const userId = Number(req.params.id); + if (!Number.isInteger(userId) || userId <= 0) { + return res.status(400).send('Invalid user.'); + } + + const [rows] = await pool.query('SELECT id, name, username, created_at, modified_at FROM users WHERE id = ? LIMIT 1', [userId]); + const user = rows[0] || null; + if (!user) { + return res.status(404).send('User not found.'); + } + if (Number(req.currentUser.id) === userId) { + return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to update your own login details.')); + } + + res.send(pages.renderUsersEditPage(Object.assign({}, user, { + isCurrentUser: false, + createdAtLabel: formatDashboardDate(user.created_at), + modifiedAtLabel: formatDashboardDate(user.modified_at) + }), req.query.message ? String(req.query.message) : '', req.currentUser)); + } catch (error) { + next(error); + } + }); + + app.post('/admin/users', async function (req, res, next) { + try { + const name = String(req.body.name || '').trim(); + const username = String(req.body.username || '').trim(); + const password = String(req.body.password || ''); + const confirmPassword = String(req.body.confirm_password || ''); + + if (!name) { + return res.redirect('/admin/users/new?message=' + encodeURIComponent('Name is required.')); + } + if (!username) { + return res.redirect('/admin/users/new?message=' + encodeURIComponent('Username is required.')); + } + if (!password || password.length < 8) { + return res.redirect('/admin/users/new?message=' + encodeURIComponent('Password must be at least 8 characters.')); + } + if (password !== confirmPassword) { + return res.redirect('/admin/users/new?message=' + encodeURIComponent('Passwords do not match.')); + } + + const [existingRows] = await pool.query('SELECT id FROM users WHERE username = ? LIMIT 1', [username]); + if (existingRows.length) { + return res.redirect('/admin/users/new?message=' + encodeURIComponent('That username already exists.')); + } + + const passwordRecord = hashPassword(password); + const actorId = getAuditUserId(req); + await pool.query( + 'INSERT INTO users (name, username, password_hash, password_salt, password_iterations, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?)', + [name, username, passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, actorId, actorId] + ); + res.redirect('/admin/users?message=' + encodeURIComponent('User created.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/users/:id/username', async function (req, res, next) { + try { + const userId = Number(req.params.id); + const name = String(req.body.name || '').trim(); + const username = String(req.body.username || '').trim(); + + if (!Number.isInteger(userId) || userId <= 0) { + return res.status(400).send('Invalid user.'); + } + if (!name) { + return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('Name is required.')); + } + if (Number(req.currentUser.id) === userId) { + return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to update your own username or password.')); + } + if (!username) { + return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('Username is required.')); + } + + const [existingRows] = await pool.query('SELECT id FROM users WHERE username = ? AND id <> ? LIMIT 1', [username, userId]); + if (existingRows.length) { + return res.redirect('/admin/users/' + userId + '/edit?message=' + encodeURIComponent('That username already exists.')); + } + + const [result] = await pool.query('UPDATE users SET name = ?, username = ?, modified_by = ? WHERE id = ?', [name, username, getAuditUserId(req), userId]); + if (!result.affectedRows) { + return res.status(404).send('User not found.'); + } + res.redirect('/admin/users?message=' + encodeURIComponent('Username updated.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/users/:id/password', async function (req, res, next) { + try { + const userId = Number(req.params.id); + const password = String(req.body.password || ''); + const confirmPassword = String(req.body.confirm_password || ''); + + if (!Number.isInteger(userId) || userId <= 0) { + return res.status(400).send('Invalid user.'); + } + if (Number(req.currentUser.id) === userId) { + return res.redirect('/admin/account?message=' + encodeURIComponent('Use My Account to change your own password.')); + } + if (!password || password.length < 8) { + return res.redirect('/admin/users?message=' + encodeURIComponent('Password must be at least 8 characters.')); + } + if (password !== confirmPassword) { + return res.redirect('/admin/users?message=' + encodeURIComponent('Passwords do not match.')); + } + + const [rows] = await pool.query('SELECT id FROM users WHERE id = ? LIMIT 1', [userId]); + if (!rows.length) { + return res.status(404).send('User not found.'); + } + + const passwordRecord = hashPassword(password); + await pool.query( + 'UPDATE users SET password_hash = ?, password_salt = ?, password_iterations = ?, modified_by = ? WHERE id = ?', + [passwordRecord.hash, passwordRecord.salt, passwordRecord.iterations, getAuditUserId(req), userId] + ); + await pool.query('DELETE FROM auth_sessions WHERE user_id = ?', [userId]); + res.redirect('/admin/users?message=' + encodeURIComponent('Password updated.')); + } catch (error) { + next(error); + } + }); + + app.post('/admin/users/:id/delete', async function (req, res, next) { + try { + const userId = Number(req.params.id); + if (!Number.isInteger(userId) || userId <= 0) { + return res.status(400).send('Invalid user.'); + } + if (Number(req.currentUser.id) === userId) { + return res.redirect('/admin/users?message=' + encodeURIComponent('You cannot delete your own account from the users page.')); + } + + const [countRows] = await pool.query('SELECT COUNT(*) AS user_count FROM users'); + if (!countRows.length || Number(countRows[0].user_count) <= 1) { + return res.redirect('/admin/users?message=' + encodeURIComponent('At least one user must remain.')); + } + + const [result] = await pool.query('DELETE FROM users WHERE id = ?', [userId]); + if (!result.affectedRows) { + return res.status(404).send('User not found.'); + } + res.redirect('/admin/users?message=' + encodeURIComponent('User deleted.')); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/auth.js b/src/web/routes/auth.js new file mode 100644 index 0000000..9c8e907 --- /dev/null +++ b/src/web/routes/auth.js @@ -0,0 +1,58 @@ +module.exports = function registerAuthRoutes(app, deps) { + const pool = deps.pool; + const pages = deps.pages; + const createUserSession = deps.createUserSession; + const setSessionCookie = deps.setSessionCookie; + const clearSessionCookie = deps.clearSessionCookie; + const parseCookies = deps.parseCookies; + const hashSessionToken = deps.hashSessionToken; + const verifyPassword = deps.verifyPassword; + const sessionCookieName = deps.sessionCookieName; + + app.get('/', function (req, res) { + res.redirect(req.currentUser ? '/admin' : '/login'); + }); + + app.get('/login', function (req, res) { + if (req.currentUser) { + return res.redirect('/admin'); + } + res.send(pages.renderLoginPage(req.query.message ? String(req.query.message) : '')); + }); + + app.post('/login', async function (req, res, next) { + try { + const username = String(req.body.username || '').trim(); + const password = String(req.body.password || ''); + if (!username || !password) { + return res.status(400).send('Username and password are required.'); + } + + const [rows] = await pool.query('SELECT id, name, username, password_hash, password_salt, password_iterations FROM users WHERE username = ? LIMIT 1', [username]); + const user = rows[0] || null; + if (!user || !verifyPassword(password, user)) { + return res.redirect('/login?message=' + encodeURIComponent('Invalid username or password.')); + } + + const token = await createUserSession(pool, user.id); + setSessionCookie(res, token); + res.redirect('/admin'); + } catch (error) { + next(error); + } + }); + + app.get('/logout', async function (req, res, next) { + try { + const cookies = parseCookies(req.headers.cookie || ''); + const token = cookies[sessionCookieName]; + if (token) { + await pool.query('DELETE FROM auth_sessions WHERE session_hash = ?', [hashSessionToken(token)]); + } + clearSessionCookie(res); + res.redirect('/login?message=' + encodeURIComponent('You have been signed out.')); + } catch (error) { + next(error); + } + }); +}; \ No newline at end of file diff --git a/src/web/routes/clients/list.js b/src/web/routes/clients/list.js index 2cd965a..eb2e52a 100644 --- a/src/web/routes/clients/list.js +++ b/src/web/routes/clients/list.js @@ -6,6 +6,7 @@ module.exports = function renderConnectedClientsPage(data, message, currentUser) active: 'clients', message: message, currentUser: currentUser || null, + scripts: ['js/dashboard/dashboard-page.js'], clients: data.clients || [] }); }; \ No newline at end of file diff --git a/src/web/routes/common.js b/src/web/routes/common.js index 2d1f189..76b5343 100644 --- a/src/web/routes/common.js +++ b/src/web/routes/common.js @@ -13,44 +13,7 @@ function screenPlayerUrl(slug) { return `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(slug)}`; } -function renderAdminShell(active, title, body, message) { - const navItems = [ - { key: 'dashboard', label: 'Dashboard', href: '/admin' }, - { key: 'playlists', label: 'Playlists', href: '/admin/playlists' }, - { key: 'screens', label: 'Screens', href: '/admin/screens' }, - { key: 'slides', label: 'Slides', href: '/admin/slides' }, - { key: 'templates', label: 'Slide templates', href: '/admin/templates' } - ].map((item) => ` - ${escapeHtml(item.label)} - `).join(''); - - return ` - - - - - ${escapeHtml(title)} - Pulse Signage - - - -
    - -
    - - ${body} -
    -
    - - `; -} - module.exports = { escapeHtml, - screenPlayerUrl, - renderAdminShell + screenPlayerUrl }; diff --git a/src/web/routes/dashboard/index.js b/src/web/routes/dashboard/index.js index 0c67cf0..0f9fe0d 100644 --- a/src/web/routes/dashboard/index.js +++ b/src/web/routes/dashboard/index.js @@ -10,6 +10,7 @@ module.exports = function renderDashboardPage(data, message, currentUser) { screens: data.screens || [], clients: data.clients || [], slides: data.slides || [], - connectedClientsCount: Number(data.connectedClientsCount || 0) + connectedClientsCount: Number(data.connectedClientsCount || 0), + scripts: ['js/dashboard/dashboard-page.js'] }); }; diff --git a/src/web/routes/playlists/edit.js b/src/web/routes/playlists/edit.js index 815c40e..6eb3713 100644 --- a/src/web/routes/playlists/edit.js +++ b/src/web/routes/playlists/edit.js @@ -110,6 +110,6 @@ module.exports = function renderPlaylistEditPage(playlist, data, message, curren selectableSlides: selectableSlides, playlistCanvasSignature: playlistCanvasSignature, playlistCanvasMismatch: playlistCanvasMismatch, - scripts: ['js/sortable.min.js', 'js/playlist-schedule.js'] + scripts: ['js/vendor/sortable.min.js', 'js/playlists/playlist-schedule.js'] }); }; diff --git a/src/web/routes/playlists/slide-config.js b/src/web/routes/playlists/slide-config.js index 4ce7b66..ff05bd4 100644 --- a/src/web/routes/playlists/slide-config.js +++ b/src/web/routes/playlists/slide-config.js @@ -10,6 +10,9 @@ const DAY_OPTIONS = [ { value: 6, label: 'Sat' } ]; +const DEFAULT_START_TIME = '00:00'; +const DEFAULT_END_TIME = '23:59'; + function formatDateTimeInput(value) { if (!value) { return ''; @@ -34,31 +37,43 @@ function formatTimeInput(value) { } module.exports = function renderPlaylistSlideConfigPage(playlist, playlistSlide, message, rowKey, currentUser) { - const scheduleMode = String(playlistSlide.schedule_mode || 'always'); - const selectedDays = new Set(Array.isArray(playlistSlide.schedule_days) ? playlistSlide.schedule_days.map(Number) : []); + const slide = playlistSlide || { + id: 0, + schedule_mode: 'always', + schedule_days: [], + schedule_start_datetime: null, + schedule_end_datetime: null, + schedule_start_time: null, + schedule_end_time: null + }; + const scheduleMode = String(slide.schedule_mode || 'always'); + const selectedDays = new Set(Array.isArray(slide.schedule_days) ? slide.schedule_days.map(Number) : []); + const startTimeValue = formatTimeInput(slide.schedule_start_time) || (scheduleMode === 'times' ? DEFAULT_START_TIME : ''); + const endTimeValue = formatTimeInput(slide.schedule_end_time) || (scheduleMode === 'times' ? DEFAULT_END_TIME : ''); return renderFragment('playlists/slide-config', { title: 'Slide schedule', + framePopupCard: true, hideFrameHeader: true, hideThemeToggle: true, frameBodyClass: 'admin-shell-body--frame-plain', message: message, currentUser: currentUser || null, playlist: playlist, - playlistSlide: playlistSlide, + playlistSlide: slide, scheduleMode: scheduleMode, isAlwaysMode: scheduleMode === 'always', isDatesMode: scheduleMode === 'dates', isTimesMode: scheduleMode === 'times', rowKey: String(rowKey || ''), - startDateTimeValue: formatDateTimeInput(playlistSlide.schedule_start_datetime), - endDateTimeValue: formatDateTimeInput(playlistSlide.schedule_end_datetime), - startTimeValue: formatTimeInput(playlistSlide.schedule_start_time), - endTimeValue: formatTimeInput(playlistSlide.schedule_end_time), + startDateTimeValue: formatDateTimeInput(slide.schedule_start_datetime), + endDateTimeValue: formatDateTimeInput(slide.schedule_end_datetime), + startTimeValue: startTimeValue, + endTimeValue: endTimeValue, dayOptions: DAY_OPTIONS.map((day) => ({ ...day, checked: selectedDays.has(day.value) })), - scripts: ['js/playlist-schedule.js'] + scripts: ['js/playlists/playlist-schedule.js'] }); }; diff --git a/src/web/routes/slides/form.js b/src/web/routes/slides/form.js index 46e129f..de8ee5f 100644 --- a/src/web/routes/slides/form.js +++ b/src/web/routes/slides/form.js @@ -13,9 +13,11 @@ module.exports = function renderSlideFormPage(data, mode, slide, message, curren active: 'slides', message: message, isEdit: mode === 'edit', + saveLabel: 'Save', action: mode === 'edit' ? `/admin/slides/${slide.id}` : '/admin/slides', slide: slide || { title: '', template_id: null, content: {} }, templates: templates, + stylesheets: ['js/vendor/ckeditor5/ckeditor5.css'], slideEditorData: { templates: templates, existingTemplateId: slide && slide.template_id ? slide.template_id : null, diff --git a/src/web/routes/templates/add.js b/src/web/routes/templates/add.js index 9b543ad..df8b87d 100644 --- a/src/web/routes/templates/add.js +++ b/src/web/routes/templates/add.js @@ -7,6 +7,7 @@ function buildDefaultTemplate() { canvas_size_id: null, canvas_size_width: 1920, canvas_size_height: 1080, + background_color: '#111111', background_image_path: '', regions: [{ region_key: 'region_1', @@ -33,7 +34,8 @@ function resolveTemplateCanvasSize(template, canvasSizes) { canvas_size_id: matched.id, canvas_size_label: matched.name, canvas_size_width: matched.width, - canvas_size_height: matched.height + canvas_size_height: matched.height, + background_color: String(template.background_color || '#111111').trim() || '#111111' }); } @@ -41,7 +43,8 @@ function resolveTemplateCanvasSize(template, canvasSizes) { canvas_size_id: '', canvas_size_label: 'Current size (' + currentWidth + 'x' + currentHeight + ')', canvas_size_width: currentWidth, - canvas_size_height: currentHeight + canvas_size_height: currentHeight, + background_color: String(template.background_color || '#111111').trim() || '#111111' }); } @@ -59,6 +62,6 @@ module.exports = function renderTemplateFormPage(template, mode, message, canvas currentUser: currentUser || null, template: current, canvasSizes: canvasSizes || [], - scripts: ['js/template-designer.js'] + scripts: ['js/templates/template-designer-utils.js', 'js/templates/template-designer.js'] }); }; diff --git a/src/web/session.js b/src/web/session.js new file mode 100644 index 0000000..631b945 --- /dev/null +++ b/src/web/session.js @@ -0,0 +1,102 @@ +function createSessionService(options) { + const sessionCookieName = String(options && options.sessionCookieName || '').trim(); + const sessionMaxAgeMs = Number(options && options.sessionMaxAgeMs); + const hashSessionToken = options && options.hashSessionToken; + const createSessionToken = options && options.createSessionToken; + + if (!sessionCookieName || !Number.isFinite(sessionMaxAgeMs) || typeof hashSessionToken !== 'function' || typeof createSessionToken !== 'function') { + throw new Error('createSessionService requires the session dependencies.'); + } + + function parseCookies(cookieHeader) { + return String(cookieHeader || '').split(/;\s*/).reduce(function (cookies, pair) { + if (!pair) { + return cookies; + } + const separatorIndex = pair.indexOf('='); + if (separatorIndex === -1) { + return cookies; + } + const name = decodeURIComponent(pair.slice(0, separatorIndex).trim()); + const value = decodeURIComponent(pair.slice(separatorIndex + 1).trim()); + if (name) { + cookies[name] = value; + } + return cookies; + }, {}); + } + + function serializeCookie(name, value, options) { + const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]; + if (options && options.maxAge !== undefined) { + parts.push(`Max-Age=${Math.max(0, Math.trunc(Number(options.maxAge) / 1000))}`); + } + parts.push('Path=/'); + parts.push('HttpOnly'); + parts.push('SameSite=Lax'); + return parts.join('; '); + } + + function clearSessionCookie(res) { + res.setHeader('Set-Cookie', serializeCookie(sessionCookieName, '', { maxAge: 0 })); + } + + function setSessionCookie(res, token) { + res.setHeader('Set-Cookie', serializeCookie(sessionCookieName, token, { maxAge: sessionMaxAgeMs })); + } + + async function loadCurrentUser(pool, req) { + const cookies = parseCookies(req.headers.cookie || ''); + const token = cookies[sessionCookieName]; + if (!token) { + return null; + } + + const tokenHash = hashSessionToken(token); + const [rows] = await pool.query( + `SELECT s.user_id, u.id, u.name, u.username + FROM auth_sessions s + JOIN users u ON u.id = s.user_id + WHERE s.session_hash = ? + AND s.expires_at > NOW() + LIMIT 1`, + [tokenHash] + ); + if (!rows.length) { + return null; + } + + await pool.query('UPDATE auth_sessions SET last_used_at = CURRENT_TIMESTAMP, modified_by = ? WHERE session_hash = ?', [rows[0].user_id, tokenHash]); + return rows[0]; + } + + async function createUserSession(pool, userId) { + const token = createSessionToken(); + const tokenHash = hashSessionToken(token); + const expiresAt = new Date(Date.now() + sessionMaxAgeMs); + await pool.query( + 'INSERT INTO auth_sessions (session_hash, user_id, expires_at, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', + [tokenHash, userId, expiresAt, userId, userId] + ); + return token; + } + + function requireAuth(req, res, next) { + if (req.currentUser) { + return next(); + } + res.redirect('/login?message=' + encodeURIComponent('Please sign in to continue.')); + } + + return { + parseCookies: parseCookies, + serializeCookie: serializeCookie, + clearSessionCookie: clearSessionCookie, + setSessionCookie: setSessionCookie, + loadCurrentUser: loadCurrentUser, + createUserSession: createUserSession, + requireAuth: requireAuth + }; +} + +module.exports = { createSessionService }; \ No newline at end of file diff --git a/src/web/upload-sync.js b/src/web/upload-sync.js new file mode 100644 index 0000000..95f5588 --- /dev/null +++ b/src/web/upload-sync.js @@ -0,0 +1,561 @@ +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +const multer = require('multer'); + +function normalizeUploadRoot(uploadDir) { + return path.resolve(String(uploadDir || '').trim()); +} + +function createUploadSyncService(options) { + const common = options && options.common; + const playerInternalBaseUrl = String(options && options.playerInternalBaseUrl || '').replace(/\/$/, ''); + const playerSnapshotCache = options && options.playerSnapshotCache; + const notifyPlayerScreens = options && options.notifyPlayerScreens; + + let playerUploadSyncMode = null; + let playerUploadSyncModePromise = null; + const pendingPlayerUploadSyncs = new Map(); + let pendingPlayerUploadSyncFlushTimer = null; + let pendingPlayerUploadSyncFlushInFlight = null; + const pendingPlaylistUploadSyncs = new Map(); + let pendingPlaylistUploadSyncFlushTimer = null; + let pendingPlaylistUploadSyncFlushInFlight = null; + + if (!common || !playerSnapshotCache || typeof notifyPlayerScreens !== 'function') { + throw new Error('createUploadSyncService requires the upload dependencies.'); + } + + function createUploadMiddleware(uploadDir) { + const storage = multer.diskStorage({ + destination: function (_req, _file, cb) { + cb(null, uploadDir); + }, + filename: function (_req, file, cb) { + const safeExt = path.extname(file.originalname || '').toLowerCase(); + const stamp = `${Date.now()}-${crypto.randomUUID()}`; + cb(null, `${stamp}${safeExt}`); + } + }); + return multer({ storage }); + } + + function normalizeUploadReference(uploadPath) { + const value = String(uploadPath || '').trim(); + if (!value || !value.startsWith('/uploads/')) { + return null; + } + return value; + } + + function collectUploadReferencesFromValue(value, refs) { + if (!value) { + return refs; + } + const stack = [value]; + while (stack.length) { + const current = stack.pop(); + if (Array.isArray(current)) { + current.forEach(function (item) { + stack.push(item); + }); + continue; + } + if (current && typeof current === 'object') { + Object.keys(current).forEach(function (key) { + stack.push(current[key]); + }); + continue; + } + if (typeof current === 'string') { + const reference = normalizeUploadReference(current); + if (reference) { + refs.add(reference); + } + } + } + return refs; + } + + function collectUploadReferencesFromSlide(slide) { + const refs = new Set(); + if (!slide) { + return refs; + } + collectUploadReferencesFromValue(slide.media_path, refs); + collectUploadReferencesFromValue(common.parseJsonSafe(slide.content_json), refs); + return refs; + } + + function collectUploadReferencesFromTemplate(template) { + const refs = new Set(); + if (!template) { + return refs; + } + collectUploadReferencesFromValue(template.background_image_path, refs); + return refs; + } + + function collectUploadReferencesFromPayload(payload) { + const refs = new Set(); + if (!payload) { + return refs; + } + collectUploadReferencesFromValue(payload.mediaPath, refs); + collectUploadReferencesFromValue(common.parseJsonSafe(payload.contentJson), refs); + collectUploadReferencesFromValue(payload.backgroundImagePath, refs); + return refs; + } + + async function countUploadReferences(pool, uploadPath) { + const [slideRows] = await pool.query( + `SELECT COUNT(*) AS ref_count + FROM slides + WHERE media_path = ? + OR JSON_SEARCH(COALESCE(content_json, JSON_OBJECT()), 'one', ?) IS NOT NULL`, + [uploadPath, uploadPath] + ); + const [templateRows] = await pool.query( + 'SELECT COUNT(*) AS ref_count FROM slide_templates WHERE background_image_path = ?', + [uploadPath] + ); + return Number(slideRows[0].ref_count || 0) + Number(templateRows[0].ref_count || 0); + } + + async function removeUnusedUploadFiles(pool, uploadDir, uploadPaths) { + const uniquePaths = Array.from(new Set((uploadPaths || []).map(normalizeUploadReference).filter(Boolean))); + for (let i = 0; i < uniquePaths.length; i += 1) { + const uploadPath = uniquePaths[i]; + const referenceCount = await countUploadReferences(pool, uploadPath); + if (referenceCount > 0) { + continue; + } + + const filePath = path.join(uploadDir, path.basename(uploadPath)); + try { + await fs.promises.unlink(filePath); + } catch (error) { + if (error && error.code !== 'ENOENT') { + console.warn('Unable to remove unused upload file:', filePath, error); + } + } + queuePlayerUploadSync({ + type: 'delete', + uploadPath: uploadPath, + uploadDir: uploadDir + }); + } + } + + async function getPlayerUploadSyncMode(localUploadDir) { + if (playerUploadSyncMode) { + return playerUploadSyncMode; + } + if (playerUploadSyncModePromise) { + return playerUploadSyncModePromise; + } + + playerUploadSyncModePromise = (async function () { + try { + const response = await fetch(`${playerInternalBaseUrl}/api/uploads/config`, { + headers: { + Accept: 'application/json' + } + }); + if (!response.ok) { + return null; + } + const data = await response.json(); + const playerUploadDir = data && data.uploadDir ? normalizeUploadRoot(data.uploadDir) : null; + if (!playerUploadDir) { + return null; + } + return playerUploadDir === normalizeUploadRoot(localUploadDir) ? 'shared' : 'different'; + } catch (_error) { + return null; + } + })().then(function (mode) { + if (mode) { + playerUploadSyncMode = mode; + } + playerUploadSyncModePromise = null; + return mode; + }, function () { + playerUploadSyncModePromise = null; + return null; + }); + + return playerUploadSyncModePromise; + } + + async function shouldMirrorUploads(localUploadDir) { + return Boolean(localUploadDir); + } + + function queuePlayerUploadSync(operation) { + if (!operation || !operation.uploadPath) { + return; + } + + pendingPlayerUploadSyncs.set(normalizeUploadReference(operation.uploadPath), { + type: operation.type === 'delete' ? 'delete' : 'put', + uploadPath: normalizeUploadReference(operation.uploadPath), + uploadDir: operation.uploadDir || null + }); + + schedulePendingPlayerUploadSyncFlush(); + } + + function schedulePendingPlayerUploadSyncFlush() { + if (pendingPlayerUploadSyncFlushTimer) { + return; + } + + pendingPlayerUploadSyncFlushTimer = setTimeout(function () { + pendingPlayerUploadSyncFlushTimer = null; + flushPendingPlayerUploadSyncs().catch(function (error) { + console.warn('Unable to flush pending upload syncs:', error); + }); + }, 5000); + } + + async function pushUploadFileToPlayer(uploadPath, localUploadDir) { + if (!uploadPath || !(await shouldMirrorUploads(localUploadDir))) { + return false; + } + + const filename = path.basename(uploadPath); + const sourcePath = path.join(localUploadDir, filename); + let fileBuffer = null; + try { + fileBuffer = await fs.promises.readFile(sourcePath); + } catch (error) { + if (!error || error.code !== 'ENOENT') { + console.warn('Unable to read upload for player sync:', sourcePath, error); + } + return; + } + + try { + const response = await fetch(`${playerInternalBaseUrl}/api/uploads/${encodeURIComponent(filename)}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/octet-stream' + }, + body: fileBuffer + }); + if (!response.ok) { + console.warn('Unable to sync upload to player:', filename, response.status, response.statusText); + return false; + } + return true; + } catch (error) { + console.warn('Unable to sync upload to player:', filename, error); + return false; + } + } + + async function removeUploadFileFromPlayer(uploadPath, localUploadDir) { + if (!uploadPath || !(await shouldMirrorUploads(localUploadDir))) { + return false; + } + + const filename = path.basename(uploadPath); + try { + const response = await fetch(`${playerInternalBaseUrl}/api/uploads/${encodeURIComponent(filename)}`, { + method: 'DELETE', + headers: { + Accept: 'application/json' + } + }); + if (!response.ok && response.status !== 404) { + console.warn('Unable to remove upload from player:', filename, response.status, response.statusText); + return false; + } + return true; + } catch (error) { + console.warn('Unable to remove upload from player:', filename, error); + return false; + } + } + + async function syncUploadRefsToPlayer(uploadRefs, localUploadDir) { + if (!(await shouldMirrorUploads(localUploadDir))) { + return; + } + + const uniqueRefs = Array.from(new Set((uploadRefs || []).map(normalizeUploadReference).filter(Boolean))); + for (let i = 0; i < uniqueRefs.length; i += 1) { + const success = await pushUploadFileToPlayer(uniqueRefs[i], localUploadDir); + if (!success) { + queuePlayerUploadSync({ + type: 'put', + uploadPath: uniqueRefs[i], + uploadDir: localUploadDir + }); + } + } + } + + async function syncExistingUploadsToPlayer(pool, localUploadDir) { + if (!(await shouldMirrorUploads(localUploadDir))) { + return; + } + + const data = await common.fetchAdminData(pool); + const uploadRefs = new Set(); + (data.slides || []).forEach(function (slide) { + collectUploadReferencesFromSlide(slide).forEach(function (reference) { + uploadRefs.add(reference); + }); + }); + (data.templates || []).forEach(function (template) { + collectUploadReferencesFromTemplate(template).forEach(function (reference) { + uploadRefs.add(reference); + }); + }); + Array.from(uploadRefs).forEach(function (uploadPath) { + queuePlayerUploadSync({ + type: 'put', + uploadPath: uploadPath, + uploadDir: localUploadDir + }); + }); + await flushPendingPlayerUploadSyncs(); + } + + function getVisibleCurrentSlideIds() { + const visibleSlideIds = new Set(); + playerSnapshotCache.forEach(function (snapshot) { + const connections = snapshot && Array.isArray(snapshot.connections) ? snapshot.connections : []; + connections.forEach(function (connection) { + const currentSlide = connection && connection.currentSlide && typeof connection.currentSlide === 'object' + ? connection.currentSlide + : null; + const slideId = currentSlide && currentSlide.id !== undefined && currentSlide.id !== null + ? String(currentSlide.id).trim() + : ''; + if (slideId) { + visibleSlideIds.add(slideId); + } + }); + }); + return visibleSlideIds; + } + + function isScreenRefreshBlocked(screenSlug, blockedSlideIds, screenSlideCounts) { + const slideIds = Array.isArray(blockedSlideIds) + ? blockedSlideIds.map(function (value) { + return String(value || '').trim(); + }).filter(Boolean) + : []; + if (!slideIds.length) { + return false; + } + const normalizedScreenSlug = String(screenSlug || '').trim(); + const slideCount = screenSlideCounts && Object.prototype.hasOwnProperty.call(screenSlideCounts, normalizedScreenSlug) + ? Number(screenSlideCounts[normalizedScreenSlug]) + : null; + if (Number.isFinite(slideCount) && slideCount <= 1) { + return false; + } + const snapshot = playerSnapshotCache.get(String(screenSlug || '').trim()); + const connections = snapshot && Array.isArray(snapshot.connections) ? snapshot.connections : []; + return connections.some(function (connection) { + const currentSlide = connection && connection.currentSlide && typeof connection.currentSlide === 'object' + ? connection.currentSlide + : null; + const currentSlideId = currentSlide && currentSlide.id !== undefined && currentSlide.id !== null + ? String(currentSlide.id).trim() + : ''; + return currentSlideId && slideIds.includes(currentSlideId); + }); + } + + function splitRefreshScreenSlugsByVisibility(screenSlugs, blockedSlideIds, screenSlideCounts) { + const ready = []; + const blocked = []; + Array.from(new Set(Array.isArray(screenSlugs) ? screenSlugs : [])).forEach(function (screenSlug) { + const normalizedScreenSlug = String(screenSlug || '').trim(); + if (!normalizedScreenSlug) { + return; + } + if (isScreenRefreshBlocked(normalizedScreenSlug, blockedSlideIds, screenSlideCounts)) { + blocked.push(normalizedScreenSlug); + } else { + ready.push(normalizedScreenSlug); + } + }); + return { ready: ready, blocked: blocked }; + } + + function normalizePlaylistUploadSyncOperation(options) { + return { + key: String(options && options.key ? options.key : '').trim(), + pool: options && options.pool ? options.pool : null, + localUploadDir: options && options.localUploadDir ? options.localUploadDir : null, + previousUploadRefs: Array.from(new Set(options && options.previousUploadRefs ? options.previousUploadRefs : [])), + nextUploadRefs: Array.from(new Set(options && options.nextUploadRefs ? options.nextUploadRefs : [])), + blockedSlideIds: Array.from(new Set(options && options.blockedSlideIds ? options.blockedSlideIds : [])).map(function (value) { + return String(value || '').trim(); + }).filter(Boolean), + refreshScreenSlugs: Array.from(new Set(options && options.refreshScreenSlugs ? options.refreshScreenSlugs : [])).map(function (value) { + return String(value || '').trim(); + }).filter(Boolean) + , + screenSlideCounts: options && options.screenSlideCounts && typeof options.screenSlideCounts === 'object' + ? options.screenSlideCounts + : {} + }; + } + + function queuePlaylistUploadSync(operation) { + if (!operation || !operation.key) { + return; + } + pendingPlaylistUploadSyncs.set(operation.key, normalizePlaylistUploadSyncOperation(operation)); + schedulePendingPlaylistUploadSyncFlush(); + } + + function schedulePendingPlaylistUploadSyncFlush() { + if (pendingPlaylistUploadSyncFlushTimer) { + return; + } + + pendingPlaylistUploadSyncFlushTimer = setTimeout(function () { + pendingPlaylistUploadSyncFlushTimer = null; + flushPendingPlaylistUploadSyncs().catch(function (error) { + console.warn('Unable to flush pending playlist upload syncs:', error); + }); + }, 5000); + } + + async function syncPlaylistUploadsOnChange(options) { + const operation = normalizePlaylistUploadSyncOperation(options); + if (!operation.key) { + return; + } + + if (operation.previousUploadRefs.length) { + const nextUploadRefSet = new Set(operation.nextUploadRefs); + await removeUnusedUploadFiles(operation.pool, operation.localUploadDir, operation.previousUploadRefs.filter(function (reference) { + return !nextUploadRefSet.has(reference); + })); + } + + if (operation.nextUploadRefs.length) { + await syncUploadRefsToPlayer(operation.nextUploadRefs, operation.localUploadDir); + } + + if (operation.refreshScreenSlugs.length) { + const refreshTargets = splitRefreshScreenSlugsByVisibility(operation.refreshScreenSlugs, operation.blockedSlideIds, operation.screenSlideCounts); + if (refreshTargets.ready.length) { + await notifyPlayerScreens(refreshTargets.ready, 'refresh'); + } + refreshTargets.blocked.forEach(function (screenSlug) { + queuePlaylistUploadSync({ + key: operation.key + ':refresh:' + screenSlug, + blockedSlideIds: operation.blockedSlideIds, + refreshScreenSlugs: [screenSlug] + }); + }); + } + } + + async function flushPendingPlaylistUploadSyncs() { + if (pendingPlaylistUploadSyncFlushInFlight) { + return pendingPlaylistUploadSyncFlushInFlight; + } + + if (!pendingPlaylistUploadSyncs.size) { + return null; + } + + pendingPlaylistUploadSyncFlushInFlight = (async function () { + const pendingEntries = Array.from(pendingPlaylistUploadSyncs.values()); + for (let i = 0; i < pendingEntries.length; i += 1) { + const operation = pendingEntries[i]; + const refreshTargets = splitRefreshScreenSlugsByVisibility(operation.refreshScreenSlugs, operation.blockedSlideIds, operation.screenSlideCounts); + if (!refreshTargets.ready.length) { + continue; + } + + if (refreshTargets.ready.length) { + await notifyPlayerScreens(refreshTargets.ready, 'refresh'); + } + + pendingPlaylistUploadSyncs.delete(operation.key); + } + })().finally(function () { + pendingPlaylistUploadSyncFlushInFlight = null; + if (pendingPlaylistUploadSyncs.size) { + schedulePendingPlaylistUploadSyncFlush(); + } + }); + + return pendingPlaylistUploadSyncFlushInFlight; + } + + async function flushPendingPlayerUploadSyncs() { + if (pendingPlayerUploadSyncFlushInFlight) { + return pendingPlayerUploadSyncFlushInFlight; + } + + if (!pendingPlayerUploadSyncs.size) { + return null; + } + + pendingPlayerUploadSyncFlushInFlight = (async function () { + const pendingEntries = Array.from(pendingPlayerUploadSyncs.values()); + for (let i = 0; i < pendingEntries.length; i += 1) { + const operation = pendingEntries[i]; + let success = false; + if (operation.type === 'delete') { + success = await removeUploadFileFromPlayer(operation.uploadPath, operation.uploadDir); + } else { + success = await pushUploadFileToPlayer(operation.uploadPath, operation.uploadDir); + } + if (success) { + pendingPlayerUploadSyncs.delete(operation.uploadPath); + } + } + })().finally(function () { + pendingPlayerUploadSyncFlushInFlight = null; + if (pendingPlayerUploadSyncs.size) { + schedulePendingPlayerUploadSyncFlush(); + } + }); + + return pendingPlayerUploadSyncFlushInFlight; + } + + return { + createUploadMiddleware: createUploadMiddleware, + normalizeUploadReference: normalizeUploadReference, + collectUploadReferencesFromValue: collectUploadReferencesFromValue, + collectUploadReferencesFromSlide: collectUploadReferencesFromSlide, + collectUploadReferencesFromTemplate: collectUploadReferencesFromTemplate, + collectUploadReferencesFromPayload: collectUploadReferencesFromPayload, + countUploadReferences: countUploadReferences, + removeUnusedUploadFiles: removeUnusedUploadFiles, + getPlayerUploadSyncMode: getPlayerUploadSyncMode, + shouldMirrorUploads: shouldMirrorUploads, + queuePlayerUploadSync: queuePlayerUploadSync, + schedulePendingPlayerUploadSyncFlush: schedulePendingPlayerUploadSyncFlush, + pushUploadFileToPlayer: pushUploadFileToPlayer, + removeUploadFileFromPlayer: removeUploadFileFromPlayer, + syncUploadRefsToPlayer: syncUploadRefsToPlayer, + syncExistingUploadsToPlayer: syncExistingUploadsToPlayer, + getVisibleCurrentSlideIds: getVisibleCurrentSlideIds, + isScreenRefreshBlocked: isScreenRefreshBlocked, + splitRefreshScreenSlugsByVisibility: splitRefreshScreenSlugsByVisibility, + normalizePlaylistUploadSyncOperation: normalizePlaylistUploadSyncOperation, + queuePlaylistUploadSync: queuePlaylistUploadSync, + schedulePendingPlaylistUploadSyncFlush: schedulePendingPlaylistUploadSyncFlush, + syncPlaylistUploadsOnChange: syncPlaylistUploadsOnChange, + flushPendingPlaylistUploadSyncs: flushPendingPlaylistUploadSyncs, + flushPendingPlayerUploadSyncs: flushPendingPlayerUploadSyncs + }; +} + +module.exports = { createUploadSyncService }; \ No newline at end of file diff --git a/src/web/view.js b/src/web/view.js index 63332bb..41f83b4 100644 --- a/src/web/view.js +++ b/src/web/view.js @@ -39,6 +39,42 @@ Handlebars.registerHelper('userInitial', function (name, username) { return value.charAt(0).toUpperCase(); }); +Handlebars.registerHelper('saveActionButtons', function (options) { + const hash = options && options.hash ? options.hash : {}; + const formId = String(hash.formId || '').trim(); + const saveLabel = String(hash.saveLabel || 'Save'); + const saveButtonClass = String(hash.saveButtonClass || 'btn btn-success'); + const saveActionName = String(hash.saveActionName || 'save_action'); + const saveActionValue = String(hash.saveActionValue || 'save'); + const closeLabel = String(hash.saveAndCloseLabel || 'Save and Close'); + const closeValue = String(hash.saveAndCloseValue || 'close'); + const newLabel = String(hash.saveAndNewLabel || 'Save and New'); + const newValue = String(hash.saveAndNewValue || 'new'); + const showSaveAndClose = hash.showSaveAndClose === undefined ? true : String(hash.showSaveAndClose).toLowerCase() !== 'false'; + const showSaveAndNew = hash.showSaveAndNew === undefined ? true : String(hash.showSaveAndNew).toLowerCase() !== 'false'; + const ariaLabel = String(hash.ariaLabel || 'Save actions'); + + if (!formId) { + return ''; + } + + const escape = Handlebars.escapeExpression; + const formAttr = ` form="${escape(formId)}"`; + + return new Handlebars.SafeString([ + '
    ', + ``, + `', + '', + '
    ', + ].join('')); +}); + function loadTemplate(relativePath) { const filePath = path.join(VIEWS_ROOT, relativePath); const stat = fs.statSync(filePath); diff --git a/src/web/views/account/password.hbs b/src/web/views/account/password.hbs index 024271e..da4fafe 100644 --- a/src/web/views/account/password.hbs +++ b/src/web/views/account/password.hbs @@ -5,35 +5,57 @@
    - -
    -
    {{playlists.length}}Playlists
    -
    {{slides.length}}Slides
    -
    {{screens.length}}Screens
    -
    {{connectedClientsCount}}Clients
    -
    +
    +
    +
    + Live overview +

    Keep the control surface focused on live state and actions.

    +

    Use the cards below for the current totals, then jump to the screens table when you need a deeper look at playback and connection state.

    +
    +
    +
    + {{playlists.length}} + playlists +
    +
    + {{screens.length}} + screens +
    +
    + {{connectedClientsCount}} + clients +
    +
    +
    +
    -
    -

    Quick actions

    -
    -
    - - -
    -
    - - - -
    +
    +
    +
    +
    +
    +

    Quick actions

    +

    Send global commands without leaving the overview.

    +
    +
    +
    +
    +
    + + + Restart every connected player page. +
    +
    + + + + Blank active players immediately. +
    +
    +
    +
    -
    -

    Current screens

    - - - - {{#if screens.length}} - {{#each screens}} - - - - - - - {{/each}} - {{else}} - - {{/if}} - -
    NamePlayer URLPlaylistConnected clients
    {{name}}{{playerUrl slug}}{{playlist_name}} - {{#if player_connection_count}} -
    {{player_connection_count}} connected
    - {{else}} - No clients connected. - {{/if}} -
    No screens yet.
    +
    +
    +
    +
    +
    +

    Current screens

    +

    Player URL, playlist assignment, and live connection count.

    +
    +
    +
    + + + + {{#if screens.length}} + {{#each screens}} + + + + + + + {{/each}} + {{else}} + + {{/if}} + +
    NamePlayer URLPlaylistConnected clients
    {{name}}{{playerUrl slug}}{{playlist_name}} + {{#if player_connection_count}} +
    {{player_connection_count}} connected
    + {{else}} + No clients connected. + {{/if}} +
    No screens yet.
    +
    +
    +
    diff --git a/src/web/views/frame-layout.hbs b/src/web/views/frame-layout.hbs index 7a471b3..23fe02b 100644 --- a/src/web/views/frame-layout.hbs +++ b/src/web/views/frame-layout.hbs @@ -6,39 +6,85 @@ {{title}} - Pulse - + + + {{#if stylesheets.length}} {{#each stylesheets}} {{/each}} {{/if}} - -
    -
    - {{#unless hideThemeToggle}} - - {{/unless}} - {{#unless hideFrameHeader}} -
    -
    - Slide workspace -

    {{title}}

    + + {{#if framePopupCard}} + {{{body}}} + {{else}} +
    + + {{#unless hideFrameHeader}} + + {{/unless}} +
    +
    +
    + {{{body}}} +
    -
    - {{/unless}} -
    -
    - {{{body}}} -
    -
    -
    -
    - + +
    + {{/if}} + + + {{#if scripts.length}} {{#each scripts}} diff --git a/src/web/views/layout.hbs b/src/web/views/layout.hbs index 66c97b0..c608a40 100644 --- a/src/web/views/layout.hbs +++ b/src/web/views/layout.hbs @@ -6,103 +6,206 @@ {{title}} - Pulse - + + + {{#if stylesheets.length}} {{#each stylesheets}} {{/each}} {{/if}} - + {{#if authShell}} -
    - {{{body}}} +
    +
    + {{else}} - {{#if message}} -
    -
    {{message}}
    - -
    - {{/if}} -
    -
    - + +
    +
    + + - - {{/if}} {{#if scripts.length}} {{#each scripts}} {{#if (isExternalUrl this)}} @@ -112,5 +215,7 @@ {{/if}} {{/each}} {{/if}} + + {{/if}} diff --git a/src/web/views/login.hbs b/src/web/views/login.hbs index b95c704..196d664 100644 --- a/src/web/views/login.hbs +++ b/src/web/views/login.hbs @@ -1,28 +1,28 @@ -
    -
    -
    -
    PS
    -
    -

    Sign in

    -

    Pulse Signage

    -
    -
    + + +
    +
    +

    Sign in

    +
    +
    \ No newline at end of file diff --git a/src/web/views/playlists/add.hbs b/src/web/views/playlists/add.hbs index faaf970..d29a707 100644 --- a/src/web/views/playlists/add.hbs +++ b/src/web/views/playlists/add.hbs @@ -3,14 +3,24 @@

    Create playlist

    Name the playlist and start adding slides.

    - Back to playlists
    -
    -
    - - +
    +
    +

    Playlist details

    +
    + +
    +
    + + +
    +
    +
    diff --git a/src/web/views/playlists/edit.hbs b/src/web/views/playlists/edit.hbs index 1c231e1..fdb99e1 100644 --- a/src/web/views/playlists/edit.hbs +++ b/src/web/views/playlists/edit.hbs @@ -1,119 +1,146 @@ -
    -
    -
    - -
    -
    - Fade: - +
    +
    +
    +
    +

    Playlist details

    +
    +
    + +
    +
    + + +
    +
    + + +
    +
    +

    Add slide to playlist

    + {{#if hasSlides}} + {{#if hasSelectableSlides}} +
    +
    +
    + +
    +
    + +
    +
    +
    + + {{else}} +
    + {{#if playlistCanvasMismatch}} + This playlist contains slides with different canvas sizes. Remove the mismatched items before adding more. + {{else if playlistCanvasSignature}} + No slides match this playlist canvas size. + {{else}} + No slides are currently available for this playlist. + {{/if}} +
    + {{/if}} + {{else}} +
    Create slides first.
    + {{/if}} +
    +
    +
    +
    - -
    -

    Playlist items

    - - - - {{#if playlistSlides.length}} - {{#each playlistSlides}} - - - - - - - - {{/each}} - {{else}} - - {{/if}} - -
    OrderSlideScheduleDurationActions
    -
    - - {{displayOrder}} -
    -
    - {{title}} - - -
    {{scheduleSummary}}
    - - - - - - -
    - - -
    - - -
    -
    No slides assigned yet.
    -
    - - -
    -

    Add slide to playlist

    - {{#if hasSlides}} - {{#if hasSelectableSlides}} -
    -
    - -
    - -
    - - {{else}} -
    - {{#if playlistCanvasMismatch}} - This playlist contains slides with different canvas sizes. Remove the mismatched items before adding more. - {{else if playlistCanvasSignature}} - No slides match this playlist canvas size. - {{else}} - No slides are currently available for this playlist. - {{/if}} +
    +
    +
    +

    Options

    - {{/if}} - {{else}} -
    Create slides first.
    - {{/if}} +
    +
    + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +

    Playlist items

    +
    +
    + + + + {{#if playlistSlides.length}} + {{#each playlistSlides}} + + + + + + + + {{/each}} + {{else}} + + {{/if}} + +
    OrderSlideScheduleDurationActions
    +
    + + {{displayOrder}} +
    +
    + {{title}} + + +
    {{scheduleSummary}}
    + + + + + + +
    + + +
    + + +
    +
    No slides assigned yet.
    +
    +
    +
    - - -
    -
    - Slide schedule -
    Configure availability for this playlist item.
    -
    - -
    - -
    diff --git a/src/web/views/playlists/list.hbs b/src/web/views/playlists/list.hbs index 27b180b..1aef53b 100644 --- a/src/web/views/playlists/list.hbs +++ b/src/web/views/playlists/list.hbs @@ -3,12 +3,17 @@

    Playlists

    Organize slide rotations and manage scheduled playback.

    - Create playlist
    -
    -

    Existing playlists

    - +
    +
    +

    Existing playlists

    + +
    +
    +
    {{#if playlists.length}} @@ -18,9 +23,9 @@ @@ -31,4 +36,5 @@ {{/if}}
    NameSlidesActions
    {{slideCount}} slide{{#unless slideCountIsOne}}s{{/unless}}
    - Edit + Edit
    - +
    +
    diff --git a/src/web/views/playlists/slide-config.hbs b/src/web/views/playlists/slide-config.hbs index 6d11d36..3a9932e 100644 --- a/src/web/views/playlists/slide-config.hbs +++ b/src/web/views/playlists/slide-config.hbs @@ -1,48 +1,68 @@ -
    - - - - -
    -

    Date range

    -
    - - -
    +
    +
    +

    Slide schedule

    + +
    + + -
    -

    Time range

    -
    - - -
    -
    - {{#each dayOptions}} - - {{/each}} -
    -
    +
    + + +
    -
    - -
    - +
    +
    +

    Date range

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + +
    +
    +

    Time range

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + {{#each dayOptions}} + + + {{/each}} +
    +
    +
    +
    + + +
    diff --git a/src/web/views/screens/add.hbs b/src/web/views/screens/add.hbs index f673b94..1dc7034 100644 --- a/src/web/views/screens/add.hbs +++ b/src/web/views/screens/add.hbs @@ -3,25 +3,39 @@

    Add screen

    Register a player endpoint and connect it to a playlist.

    - Back to screens
    -
    -
    - - - - +
    +
    +

    Screen details

    +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    diff --git a/src/web/views/screens/edit.hbs b/src/web/views/screens/edit.hbs index b5d0b30..052a346 100644 --- a/src/web/views/screens/edit.hbs +++ b/src/web/views/screens/edit.hbs @@ -3,38 +3,55 @@

    Edit screen

    Update the display name and assigned playlist.

    - Back to screens
    -
    -

    Edit screen

    -
    - - - -
    - -
    - -
    - -
    +
    +
    +
    +
    +

    Screen details

    +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + +
    +
    -
    - -
    -

    Player URL

    -

    {{playerUrl screen.slug}}

    -
    +
    +
    +
    +

    Player URL

    +
    + +
    +
    +
    \ No newline at end of file diff --git a/src/web/views/screens/list.hbs b/src/web/views/screens/list.hbs index 1135f28..e369a84 100644 --- a/src/web/views/screens/list.hbs +++ b/src/web/views/screens/list.hbs @@ -3,12 +3,17 @@

    Screens

    Register display endpoints and keep playlist assignments in sync.

    - Add screen
    -
    -

    Existing screens

    - +
    +
    +

    Existing screens

    + +
    +
    +
    {{#if screens.length}} @@ -26,9 +31,9 @@ @@ -39,4 +44,5 @@ {{/if}}
    NamePlayer URLPlaylistConnected clientsActions
    - Edit + Edit
    - +
    +
    diff --git a/src/web/views/slides/form.hbs b/src/web/views/slides/form.hbs index 9703995..973f7a3 100644 --- a/src/web/views/slides/form.hbs +++ b/src/web/views/slides/form.hbs @@ -1,46 +1,75 @@ -
    -
    -
    -
    - - +
    + +
    +
    +

    Slide details

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    -
    -
    -

    Preview

    -
    Select a template to preview the slide.
    -
    -
    - -
    - -
    Select a template to preview the slide.
    -
    + +
    +
    +
    +
    + {{{saveActionButtons formId="slide-form" saveLabel=saveLabel saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}} + Cancel + {{#if isEdit}} + + {{/if}} +
    + +
    - +{{#if isEdit}} +
    +{{/if}} + - + diff --git a/src/web/views/slides/list.hbs b/src/web/views/slides/list.hbs index ed4ff2f..ef4af1c 100644 --- a/src/web/views/slides/list.hbs +++ b/src/web/views/slides/list.hbs @@ -3,12 +3,17 @@

    Slides

    Manage individual slide content and template assignments.

    - Create slide
    -
    -

    Existing slides

    - +
    +
    +

    Existing slides

    + +
    +
    +
    {{#if slides.length}} @@ -18,9 +23,9 @@ @@ -31,4 +36,5 @@ {{/if}}
    TitleTemplateActions
    {{template_name}}
    - Edit + Edit
    - +
    +
    diff --git a/src/web/views/templates/add.hbs b/src/web/views/templates/add.hbs index ac7d319..0fb03ee 100644 --- a/src/web/views/templates/add.hbs +++ b/src/web/views/templates/add.hbs @@ -3,36 +3,9 @@

    Create template

    Define a canvas, upload a background, and place content regions.

    - Back to templates
    -
    -
    - - - -
    -
    - @@ -41,32 +14,141 @@
    -
    -
    -
    - -
    No background image selected
    -
    +
    +
    +

    Designer

    +
    +
    +
    + +
    No background image selected
    +
    +
    +
    - -
    -
    - - - - +
    +
    +
    + {{{saveActionButtons formId="template-form" saveLabel="Save" saveButtonClass="btn btn-success template-save-button" showSaveAndClose=false showSaveAndNew=false}}} + Cancel +
    +
    +
    +
    +
    +
    +

    Region information

    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +

    Template details

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +

    Options

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    -

    Region information

    - -
    + + + + diff --git a/src/web/views/templates/edit.hbs b/src/web/views/templates/edit.hbs index 704633a..17da3a8 100644 --- a/src/web/views/templates/edit.hbs +++ b/src/web/views/templates/edit.hbs @@ -1,42 +1,11 @@ -
    -
    -
    - - - -
    -
    - + @@ -45,32 +14,148 @@
    -
    -
    -
    - -
    No background image selected
    -
    +
    +
    +

    Designer

    +
    +
    +
    + +
    No background image selected
    +
    +
    +
    - -
    -
    - - - - +
    +
    +
    + {{{saveActionButtons formId="template-form" saveLabel="Save" saveButtonClass="btn btn-success template-save-button" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}} + Cancel + +
    +
    +
    +
    +
    +
    +

    Region information

    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +

    Template details

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +

    Options

    +
    +
    +
    +
    + +
    + + +
    + +
    +
    + + +
    +
    -

    Region information

    - -
    +
    + + + + + diff --git a/src/web/views/templates/list.hbs b/src/web/views/templates/list.hbs index 4edff47..6fab76a 100644 --- a/src/web/views/templates/list.hbs +++ b/src/web/views/templates/list.hbs @@ -3,12 +3,17 @@

    Slide templates

    Design reusable canvas layouts and region definitions.

    - Create Template
    -
    -

    Existing templates

    - +
    +
    +

    Existing templates

    + +
    +
    +
    {{#if templates.length}} @@ -19,9 +24,9 @@ @@ -32,4 +37,5 @@ {{/if}}
    NameCanvasRegionsActions
    {{regionCount}}
    - Edit + Edit
    - +
    +
    diff --git a/src/web/views/users/add.hbs b/src/web/views/users/add.hbs index 31865f3..f43aa0b 100644 --- a/src/web/views/users/add.hbs +++ b/src/web/views/users/add.hbs @@ -5,39 +5,36 @@
    -
    -
    -
    -

    Account details

    -
    - - +
    +
    +

    User details

    +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    -
    - -
    -

    Set password

    -
    - - +
    +
    - -
    - - Back to users
    \ No newline at end of file diff --git a/src/web/views/users/edit.hbs b/src/web/views/users/edit.hbs index b597126..243907d 100644 --- a/src/web/views/users/edit.hbs +++ b/src/web/views/users/edit.hbs @@ -1,49 +1,67 @@ -
    -
    -
    - -
    - {{user.username}} - {{#if user.isCurrentUser}} -
    Current signed-in user
    - {{/if}} +
    + +
    +
    +
    +
    +
    +

    Profile

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    + +
    +
    +
    +

    Reset password

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    - Back to users
    +
    -
    -
    -

    Edit user

    - - - -
    - -
    -

    Reset password

    - - - -
    -
    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/src/web/views/users/list.hbs b/src/web/views/users/list.hbs index bbe316f..252bb04 100644 --- a/src/web/views/users/list.hbs +++ b/src/web/views/users/list.hbs @@ -3,14 +3,17 @@

    Users

    Create accounts, rename users, reset passwords, and remove unused logins.

    -
    - Add user -
    -
    -

    Existing users

    - +
    +
    +

    Existing users

    +
    + Add user +
    +
    +
    +
    @@ -24,7 +27,6 @@
    User
    -
    {{username}} {{#if isCurrentUser}} @@ -43,9 +45,9 @@
    {{#unless isCurrentUser}} - Edit + Edit
    - +
    {{else}} Protected @@ -59,4 +61,5 @@ {{/if}}
    +
    \ No newline at end of file