From 9464760b6c79b2d82fd14ee3efdd20161c9d7b3f Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Mon, 19 Aug 2024 20:27:24 -0400 Subject: [PATCH] Added keyboard shortcuts. --- htdocs/css/keyboard.min.css | 1 + htdocs/css/shortcuts.css | 79 ++++++++ htdocs/index.html | 2 + htdocs/lib/Shortcuts.js | 389 ++++++++++++++++++++++++++++++++++++ htdocs/lib/UI.js | 16 +- htdocs/openwebrx.js | 3 + owrx/controllers/assets.py | 1 + 7 files changed, 484 insertions(+), 7 deletions(-) create mode 100644 htdocs/css/keyboard.min.css create mode 100644 htdocs/css/shortcuts.css create mode 100644 htdocs/lib/Shortcuts.js diff --git a/htdocs/css/keyboard.min.css b/htdocs/css/keyboard.min.css new file mode 100644 index 00000000..d3c6ecc7 --- /dev/null +++ b/htdocs/css/keyboard.min.css @@ -0,0 +1 @@ +/*! keyboard-css v1.2.4 | (c) 2020 | MIT License | https://github.com/shhdharmen/keyboard-css.git */.kbc-button{font-size:inherit;line-height:inherit;margin:.25rem .25rem .4375rem;padding:.1rem .4rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,0 5px #d9d9d9,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#fff;color:#343a40;-webkit-backface-visibility:hidden;backface-visibility:hidden;border:1px solid #e6e6e6;border-radius:.25rem;display:inline-block;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:400;text-align:left;transform:translateZ(5px);transform-style:preserve-3d;transition:all .25s cubic-bezier(.2,1,.2,1)}.kbc-button:after{border-radius:.5rem;border-width:.125rem;bottom:-9px;left:-.3125rem;right:-.3125rem;top:-3px;transform:translateZ(-3px);border-color:#ccc}.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,0 5px #4da3ff,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}.kbc-button-primary:after{border-color:#66b0ff}.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,0 5px #939ba2,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}.kbc-button-secondary:after{border-color:#a1a8ae}.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,0 5px #48d368,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}.kbc-button-success:after{border-color:#5dd879}.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,0 5px #36cee6,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}.kbc-button-info:after{border-color:#4cd3e9}.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,0 5px #ba8b00,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}.kbc-button-warning:after{border-color:#a07800}.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,0 5px #e77681,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}.kbc-button-danger:after{border-color:#eb8c95}.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,0 5px #cbd3da,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}.kbc-button-light:after{border-color:#bdc6d0}.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,0 5px #56606a,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}.kbc-button-dark:after{border-color:#626d78}.kbc-button-xxs{font-size:.7rem;line-height:1.5;margin:.25rem .25rem .375rem;padding:.1rem .3rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}.kbc-button-xxs:after{border-radius:.375rem;border-width:.0625rem;bottom:-6px;left:-.25rem;right:-.25rem;top:-2px;transform:translateZ(-2px);border-color:#ccc}.kbc-button-xxs.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}.kbc-button-xxs.kbc-button-primary:after{border-color:#66b0ff}.kbc-button-xxs.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}.kbc-button-xxs.kbc-button-secondary:after{border-color:#a1a8ae}.kbc-button-xxs.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}.kbc-button-xxs.kbc-button-success:after{border-color:#5dd879}.kbc-button-xxs.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}.kbc-button-xxs.kbc-button-info:after{border-color:#4cd3e9}.kbc-button-xxs.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}.kbc-button-xxs.kbc-button-warning:after{border-color:#a07800}.kbc-button-xxs.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}.kbc-button-xxs.kbc-button-danger:after{border-color:#eb8c95}.kbc-button-xxs.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}.kbc-button-xxs.kbc-button-light:after{border-color:#bdc6d0}.kbc-button-xxs.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}.kbc-button-xxs.kbc-button-dark:after{border-color:#626d78}.kbc-button-xs{font-size:.725rem;line-height:1.5;margin:.25rem .25rem .375rem;padding:.175rem .5rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}.kbc-button-xs:after{border-radius:.375rem;border-width:.0625rem;bottom:-6px;left:-.25rem;right:-.25rem;top:-2px;transform:translateZ(-2px);border-color:#ccc}.kbc-button-xs.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}.kbc-button-xs.kbc-button-primary:after{border-color:#66b0ff}.kbc-button-xs.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}.kbc-button-xs.kbc-button-secondary:after{border-color:#a1a8ae}.kbc-button-xs.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}.kbc-button-xs.kbc-button-success:after{border-color:#5dd879}.kbc-button-xs.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}.kbc-button-xs.kbc-button-info:after{border-color:#4cd3e9}.kbc-button-xs.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}.kbc-button-xs.kbc-button-warning:after{border-color:#a07800}.kbc-button-xs.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}.kbc-button-xs.kbc-button-danger:after{border-color:#eb8c95}.kbc-button-xs.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}.kbc-button-xs.kbc-button-light:after{border-color:#bdc6d0}.kbc-button-xs.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}.kbc-button-xs.kbc-button-dark:after{border-color:#626d78}.kbc-button-sm{font-size:.875rem;line-height:1.5;margin:.25rem .25rem .4375rem;padding:.25rem .5rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}.kbc-button-sm:after{border-radius:.375rem;border-width:.09375rem;bottom:-7px;left:-.25rem;right:-.25rem;top:-1px;transform:translateZ(-3px);border-color:#ccc}.kbc-button-sm.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}.kbc-button-sm.kbc-button-primary:after{border-color:#66b0ff}.kbc-button-sm.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}.kbc-button-sm.kbc-button-secondary:after{border-color:#a1a8ae}.kbc-button-sm.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}.kbc-button-sm.kbc-button-success:after{border-color:#5dd879}.kbc-button-sm.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}.kbc-button-sm.kbc-button-info:after{border-color:#4cd3e9}.kbc-button-sm.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}.kbc-button-sm.kbc-button-warning:after{border-color:#a07800}.kbc-button-sm.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}.kbc-button-sm.kbc-button-danger:after{border-color:#eb8c95}.kbc-button-sm.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}.kbc-button-sm.kbc-button-light:after{border-color:#bdc6d0}.kbc-button-sm.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}.kbc-button-sm.kbc-button-dark:after{border-color:#626d78}.kbc-button-lg{font-size:1.25rem;line-height:1.5;margin:.25rem .25rem .75rem;padding:.5rem 1rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,0 5px #d9d9d9,0 6px #d9d9d9,0 7px #d9d9d9,0 8px #d9d9d9,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}.kbc-button-lg:after{border-radius:.5rem;border-width:.125rem;bottom:-13px;left:-.375rem;right:-.375rem;top:3px;transform:translateZ(-8px);border-color:#ccc}.kbc-button-lg.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,0 5px #4da3ff,0 6px #4da3ff,0 7px #4da3ff,0 8px #4da3ff,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}.kbc-button-lg.kbc-button-primary:after{border-color:#66b0ff}.kbc-button-lg.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,0 5px #939ba2,0 6px #939ba2,0 7px #939ba2,0 8px #939ba2,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}.kbc-button-lg.kbc-button-secondary:after{border-color:#a1a8ae}.kbc-button-lg.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,0 5px #48d368,0 6px #48d368,0 7px #48d368,0 8px #48d368,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}.kbc-button-lg.kbc-button-success:after{border-color:#5dd879}.kbc-button-lg.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,0 5px #36cee6,0 6px #36cee6,0 7px #36cee6,0 8px #36cee6,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}.kbc-button-lg.kbc-button-info:after{border-color:#4cd3e9}.kbc-button-lg.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,0 5px #ba8b00,0 6px #ba8b00,0 7px #ba8b00,0 8px #ba8b00,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}.kbc-button-lg.kbc-button-warning:after{border-color:#a07800}.kbc-button-lg.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,0 5px #e77681,0 6px #e77681,0 7px #e77681,0 8px #e77681,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}.kbc-button-lg.kbc-button-danger:after{border-color:#eb8c95}.kbc-button-lg.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,0 5px #cbd3da,0 6px #cbd3da,0 7px #cbd3da,0 8px #cbd3da,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}.kbc-button-lg.kbc-button-light:after{border-color:#bdc6d0}.kbc-button-lg.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,0 5px #56606a,0 6px #56606a,0 7px #56606a,0 8px #56606a,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}.kbc-button-lg.kbc-button-dark:after{border-color:#626d78}.kbc-button.no-container:after{border-color:transparent}.kbc-button:after{border-style:solid;box-sizing:content-box;content:"";display:block;position:absolute;transform-style:preserve-3d;transition:all .25s cubic-bezier(.2,1,.2,1)}a.kbc-button,a.kbc-button:focus,a.kbc-button:hover{text-decoration:none}a.kbc-button,button.kbc-button{font-size:1rem;line-height:1.5;margin:.375rem .375rem .6875rem;padding:.375rem .75rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,0 5px #d9d9d9,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40;cursor:pointer;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}a.kbc-button.focus,a.kbc-button.hover,a.kbc-button:focus,a.kbc-button:hover,button.kbc-button.focus,button.kbc-button.hover,button.kbc-button:focus,button.kbc-button:hover{transform:translate3d(0,1px,5px)}a.kbc-button.focus:after,a.kbc-button.hover:after,a.kbc-button:focus:after,a.kbc-button:hover:after,button.kbc-button.focus:after,button.kbc-button.hover:after,button.kbc-button:focus:after,button.kbc-button:hover:after{transform:translate3d(0,-1px,-5px)}a.kbc-button.active,a.kbc-button:active,button.kbc-button.active,button.kbc-button:active{border-color:transparent;box-shadow:none;transform:translate3d(0,5px,0)}a.kbc-button.active:after,a.kbc-button:active:after,button.kbc-button.active:after,button.kbc-button:active:after{transform:translate3d(0,-5px,0)}a.kbc-button:after,button.kbc-button:after{border-radius:.5rem;border-width:.125rem;bottom:-10px;left:-.3125rem;right:-.3125rem;top:0;transform:translateZ(-5px)}a.kbc-button.focus,a.kbc-button.hover,a.kbc-button:focus,a.kbc-button:hover,button.kbc-button.focus,button.kbc-button.hover,button.kbc-button:focus,button.kbc-button:hover{box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#e6e6e6;color:#343a40}a.kbc-button.active,a.kbc-button:active,button.kbc-button.active,button.kbc-button:active{background-color:#e6e6e6;box-shadow:0 0 1px 1px #b3b3b3;color:#343a40}a.kbc-button:after,button.kbc-button:after{border-color:#ccc}a.kbc-button-primary,button.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,0 5px #4da3ff,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}a.kbc-button-primary.focus,a.kbc-button-primary.hover,a.kbc-button-primary:focus,a.kbc-button-primary:hover,button.kbc-button-primary.focus,button.kbc-button-primary.hover,button.kbc-button-primary:focus,button.kbc-button-primary:hover{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#3395ff;color:#f8f9fa}a.kbc-button-primary.active,a.kbc-button-primary:active,button.kbc-button-primary.active,button.kbc-button-primary:active{background-color:#3395ff;box-shadow:0 0 1px 1px #99caff;color:#f8f9fa}a.kbc-button-primary:after,button.kbc-button-primary:after{border-color:#66b0ff}a.kbc-button-secondary,button.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,0 5px #939ba2,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}a.kbc-button-secondary.focus,a.kbc-button-secondary.hover,a.kbc-button-secondary:focus,a.kbc-button-secondary:hover,button.kbc-button-secondary.focus,button.kbc-button-secondary.hover,button.kbc-button-secondary:focus,button.kbc-button-secondary:hover{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#868e96;color:#f8f9fa}a.kbc-button-secondary.active,a.kbc-button-secondary:active,button.kbc-button-secondary.active,button.kbc-button-secondary:active{background-color:#868e96;box-shadow:0 0 1px 1px #bcc1c6;color:#f8f9fa}a.kbc-button-secondary:after,button.kbc-button-secondary:after{border-color:#a1a8ae}a.kbc-button-success,button.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,0 5px #48d368,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}a.kbc-button-success.focus,a.kbc-button-success.hover,a.kbc-button-success:focus,a.kbc-button-success:hover,button.kbc-button-success.focus,button.kbc-button-success.hover,button.kbc-button-success:focus,button.kbc-button-success:hover{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#34ce57;color:#f8f9fa}a.kbc-button-success.active,a.kbc-button-success:active,button.kbc-button-success.active,button.kbc-button-success:active{background-color:#34ce57;box-shadow:0 0 1px 1px #86e29b;color:#f8f9fa}a.kbc-button-success:after,button.kbc-button-success:after{border-color:#5dd879}a.kbc-button-info,button.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,0 5px #36cee6,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}a.kbc-button-info.focus,a.kbc-button-info.hover,a.kbc-button-info:focus,a.kbc-button-info:hover,button.kbc-button-info.focus,button.kbc-button-info.hover,button.kbc-button-info:focus,button.kbc-button-info:hover{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#1fc8e3;color:#343a40}a.kbc-button-info.active,a.kbc-button-info:active,button.kbc-button-info.active,button.kbc-button-info:active{background-color:#1fc8e3;box-shadow:0 0 1px 1px #7adeee;color:#343a40}a.kbc-button-info:after,button.kbc-button-info:after{border-color:#4cd3e9}a.kbc-button-warning,button.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,0 5px #ba8b00,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}a.kbc-button-warning.focus,a.kbc-button-warning.hover,a.kbc-button-warning:focus,a.kbc-button-warning:hover,button.kbc-button-warning.focus,button.kbc-button-warning.hover,button.kbc-button-warning:focus,button.kbc-button-warning:hover{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#d39e00;color:#343a40}a.kbc-button-warning.active,a.kbc-button-warning:active,button.kbc-button-warning.active,button.kbc-button-warning:active{background-color:#d39e00;box-shadow:0 0 1px 1px #6d5200;color:#343a40}a.kbc-button-warning:after,button.kbc-button-warning:after{border-color:#a07800}a.kbc-button-danger,button.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,0 5px #e77681,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}a.kbc-button-danger.focus,a.kbc-button-danger.hover,a.kbc-button-danger:focus,a.kbc-button-danger:hover,button.kbc-button-danger.focus,button.kbc-button-danger.hover,button.kbc-button-danger:focus,button.kbc-button-danger:hover{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#e4606d;color:#f8f9fa}a.kbc-button-danger.active,a.kbc-button-danger:active,button.kbc-button-danger.active,button.kbc-button-danger:active{background-color:#e4606d;box-shadow:0 0 1px 1px #f3b7bd;color:#f8f9fa}a.kbc-button-danger:after,button.kbc-button-danger:after{border-color:#eb8c95}a.kbc-button-light,button.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,0 5px #cbd3da,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}a.kbc-button-light.focus,a.kbc-button-light.hover,a.kbc-button-light:focus,a.kbc-button-light:hover,button.kbc-button-light.focus,button.kbc-button-light.hover,button.kbc-button-light:focus,button.kbc-button-light:hover{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#dae0e5;color:#343a40}a.kbc-button-light.active,a.kbc-button-light:active,button.kbc-button-light.active,button.kbc-button-light:active{background-color:#dae0e5;box-shadow:0 0 1px 1px #9fadba;color:#343a40}a.kbc-button-light:after,button.kbc-button-light:after{border-color:#bdc6d0}a.kbc-button-dark,button.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,0 5px #56606a,2px 2.5px 4px #adb5bd,0 -1px 2.5px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}a.kbc-button-dark.focus,a.kbc-button-dark.hover,a.kbc-button-dark:focus,a.kbc-button-dark:hover,button.kbc-button-dark.focus,button.kbc-button-dark.hover,button.kbc-button-dark:focus,button.kbc-button-dark:hover{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,2px 2px 4px #adb5bd,0 -1px 2px #adb5bd;background-color:#4b545c;color:#f8f9fa}a.kbc-button-dark.active,a.kbc-button-dark:active,button.kbc-button-dark.active,button.kbc-button-dark:active{background-color:#4b545c;box-shadow:0 0 1px 1px #7a8793;color:#f8f9fa}a.kbc-button-dark:after,button.kbc-button-dark:after{border-color:#626d78}a.kbc-button-xxs,button.kbc-button-xxs{font-size:.7rem;line-height:1.5;margin:.3125rem .3125rem .4375rem;padding:.1rem .3rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}a.kbc-button-xxs.focus,a.kbc-button-xxs.hover,a.kbc-button-xxs:focus,a.kbc-button-xxs:hover,button.kbc-button-xxs.focus,button.kbc-button-xxs.hover,button.kbc-button-xxs:focus,button.kbc-button-xxs:hover{transform:translate3d(0,1px,2px)}a.kbc-button-xxs.focus:after,a.kbc-button-xxs.hover:after,a.kbc-button-xxs:focus:after,a.kbc-button-xxs:hover:after,button.kbc-button-xxs.focus:after,button.kbc-button-xxs.hover:after,button.kbc-button-xxs:focus:after,button.kbc-button-xxs:hover:after{transform:translate3d(0,-1px,-2px)}a.kbc-button-xxs.active,a.kbc-button-xxs:active,button.kbc-button-xxs.active,button.kbc-button-xxs:active{border-color:transparent;box-shadow:none;transform:translate3d(0,2px,0)}a.kbc-button-xxs.active:after,a.kbc-button-xxs:active:after,button.kbc-button-xxs.active:after,button.kbc-button-xxs:active:after{transform:translate3d(0,-2px,0)}a.kbc-button-xxs:after,button.kbc-button-xxs:after{border-radius:.375rem;border-width:.0625rem;bottom:-6px;left:-.25rem;right:-.25rem;top:-2px;transform:translateZ(-2px)}a.kbc-button-xxs.focus,a.kbc-button-xxs.hover,a.kbc-button-xxs:focus,a.kbc-button-xxs:hover,button.kbc-button-xxs.focus,button.kbc-button-xxs.hover,button.kbc-button-xxs:focus,button.kbc-button-xxs:hover{box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#e6e6e6;color:#343a40}a.kbc-button-xxs.active,a.kbc-button-xxs:active,button.kbc-button-xxs.active,button.kbc-button-xxs:active{background-color:#e6e6e6;box-shadow:0 0 1px 1px #b3b3b3;color:#343a40}a.kbc-button-xxs:after,button.kbc-button-xxs:after{border-color:#ccc}a.kbc-button-xxs.kbc-button-primary,button.kbc-button-xxs.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}a.kbc-button-xxs.kbc-button-primary.focus,a.kbc-button-xxs.kbc-button-primary.hover,a.kbc-button-xxs.kbc-button-primary:focus,a.kbc-button-xxs.kbc-button-primary:hover,button.kbc-button-xxs.kbc-button-primary.focus,button.kbc-button-xxs.kbc-button-primary.hover,button.kbc-button-xxs.kbc-button-primary:focus,button.kbc-button-xxs.kbc-button-primary:hover{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#3395ff;color:#f8f9fa}a.kbc-button-xxs.kbc-button-primary.active,a.kbc-button-xxs.kbc-button-primary:active,button.kbc-button-xxs.kbc-button-primary.active,button.kbc-button-xxs.kbc-button-primary:active{background-color:#3395ff;box-shadow:0 0 1px 1px #99caff;color:#f8f9fa}a.kbc-button-xxs.kbc-button-primary:after,button.kbc-button-xxs.kbc-button-primary:after{border-color:#66b0ff}a.kbc-button-xxs.kbc-button-secondary,button.kbc-button-xxs.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}a.kbc-button-xxs.kbc-button-secondary.focus,a.kbc-button-xxs.kbc-button-secondary.hover,a.kbc-button-xxs.kbc-button-secondary:focus,a.kbc-button-xxs.kbc-button-secondary:hover,button.kbc-button-xxs.kbc-button-secondary.focus,button.kbc-button-xxs.kbc-button-secondary.hover,button.kbc-button-xxs.kbc-button-secondary:focus,button.kbc-button-xxs.kbc-button-secondary:hover{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#868e96;color:#f8f9fa}a.kbc-button-xxs.kbc-button-secondary.active,a.kbc-button-xxs.kbc-button-secondary:active,button.kbc-button-xxs.kbc-button-secondary.active,button.kbc-button-xxs.kbc-button-secondary:active{background-color:#868e96;box-shadow:0 0 1px 1px #bcc1c6;color:#f8f9fa}a.kbc-button-xxs.kbc-button-secondary:after,button.kbc-button-xxs.kbc-button-secondary:after{border-color:#a1a8ae}a.kbc-button-xxs.kbc-button-success,button.kbc-button-xxs.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}a.kbc-button-xxs.kbc-button-success.focus,a.kbc-button-xxs.kbc-button-success.hover,a.kbc-button-xxs.kbc-button-success:focus,a.kbc-button-xxs.kbc-button-success:hover,button.kbc-button-xxs.kbc-button-success.focus,button.kbc-button-xxs.kbc-button-success.hover,button.kbc-button-xxs.kbc-button-success:focus,button.kbc-button-xxs.kbc-button-success:hover{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#34ce57;color:#f8f9fa}a.kbc-button-xxs.kbc-button-success.active,a.kbc-button-xxs.kbc-button-success:active,button.kbc-button-xxs.kbc-button-success.active,button.kbc-button-xxs.kbc-button-success:active{background-color:#34ce57;box-shadow:0 0 1px 1px #86e29b;color:#f8f9fa}a.kbc-button-xxs.kbc-button-success:after,button.kbc-button-xxs.kbc-button-success:after{border-color:#5dd879}a.kbc-button-xxs.kbc-button-info,button.kbc-button-xxs.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}a.kbc-button-xxs.kbc-button-info.focus,a.kbc-button-xxs.kbc-button-info.hover,a.kbc-button-xxs.kbc-button-info:focus,a.kbc-button-xxs.kbc-button-info:hover,button.kbc-button-xxs.kbc-button-info.focus,button.kbc-button-xxs.kbc-button-info.hover,button.kbc-button-xxs.kbc-button-info:focus,button.kbc-button-xxs.kbc-button-info:hover{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#1fc8e3;color:#343a40}a.kbc-button-xxs.kbc-button-info.active,a.kbc-button-xxs.kbc-button-info:active,button.kbc-button-xxs.kbc-button-info.active,button.kbc-button-xxs.kbc-button-info:active{background-color:#1fc8e3;box-shadow:0 0 1px 1px #7adeee;color:#343a40}a.kbc-button-xxs.kbc-button-info:after,button.kbc-button-xxs.kbc-button-info:after{border-color:#4cd3e9}a.kbc-button-xxs.kbc-button-warning,button.kbc-button-xxs.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}a.kbc-button-xxs.kbc-button-warning.focus,a.kbc-button-xxs.kbc-button-warning.hover,a.kbc-button-xxs.kbc-button-warning:focus,a.kbc-button-xxs.kbc-button-warning:hover,button.kbc-button-xxs.kbc-button-warning.focus,button.kbc-button-xxs.kbc-button-warning.hover,button.kbc-button-xxs.kbc-button-warning:focus,button.kbc-button-xxs.kbc-button-warning:hover{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#d39e00;color:#343a40}a.kbc-button-xxs.kbc-button-warning.active,a.kbc-button-xxs.kbc-button-warning:active,button.kbc-button-xxs.kbc-button-warning.active,button.kbc-button-xxs.kbc-button-warning:active{background-color:#d39e00;box-shadow:0 0 1px 1px #6d5200;color:#343a40}a.kbc-button-xxs.kbc-button-warning:after,button.kbc-button-xxs.kbc-button-warning:after{border-color:#a07800}a.kbc-button-xxs.kbc-button-danger,button.kbc-button-xxs.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}a.kbc-button-xxs.kbc-button-danger.focus,a.kbc-button-xxs.kbc-button-danger.hover,a.kbc-button-xxs.kbc-button-danger:focus,a.kbc-button-xxs.kbc-button-danger:hover,button.kbc-button-xxs.kbc-button-danger.focus,button.kbc-button-xxs.kbc-button-danger.hover,button.kbc-button-xxs.kbc-button-danger:focus,button.kbc-button-xxs.kbc-button-danger:hover{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#e4606d;color:#f8f9fa}a.kbc-button-xxs.kbc-button-danger.active,a.kbc-button-xxs.kbc-button-danger:active,button.kbc-button-xxs.kbc-button-danger.active,button.kbc-button-xxs.kbc-button-danger:active{background-color:#e4606d;box-shadow:0 0 1px 1px #f3b7bd;color:#f8f9fa}a.kbc-button-xxs.kbc-button-danger:after,button.kbc-button-xxs.kbc-button-danger:after{border-color:#eb8c95}a.kbc-button-xxs.kbc-button-light,button.kbc-button-xxs.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}a.kbc-button-xxs.kbc-button-light.focus,a.kbc-button-xxs.kbc-button-light.hover,a.kbc-button-xxs.kbc-button-light:focus,a.kbc-button-xxs.kbc-button-light:hover,button.kbc-button-xxs.kbc-button-light.focus,button.kbc-button-xxs.kbc-button-light.hover,button.kbc-button-xxs.kbc-button-light:focus,button.kbc-button-xxs.kbc-button-light:hover{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#dae0e5;color:#343a40}a.kbc-button-xxs.kbc-button-light.active,a.kbc-button-xxs.kbc-button-light:active,button.kbc-button-xxs.kbc-button-light.active,button.kbc-button-xxs.kbc-button-light:active{background-color:#dae0e5;box-shadow:0 0 1px 1px #9fadba;color:#343a40}a.kbc-button-xxs.kbc-button-light:after,button.kbc-button-xxs.kbc-button-light:after{border-color:#bdc6d0}a.kbc-button-xxs.kbc-button-dark,button.kbc-button-xxs.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}a.kbc-button-xxs.kbc-button-dark.focus,a.kbc-button-xxs.kbc-button-dark.hover,a.kbc-button-xxs.kbc-button-dark:focus,a.kbc-button-xxs.kbc-button-dark:hover,button.kbc-button-xxs.kbc-button-dark.focus,button.kbc-button-xxs.kbc-button-dark.hover,button.kbc-button-xxs.kbc-button-dark:focus,button.kbc-button-xxs.kbc-button-dark:hover{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#4b545c;color:#f8f9fa}a.kbc-button-xxs.kbc-button-dark.active,a.kbc-button-xxs.kbc-button-dark:active,button.kbc-button-xxs.kbc-button-dark.active,button.kbc-button-xxs.kbc-button-dark:active{background-color:#4b545c;box-shadow:0 0 1px 1px #7a8793;color:#f8f9fa}a.kbc-button-xxs.kbc-button-dark:after,button.kbc-button-xxs.kbc-button-dark:after{border-color:#626d78}a.kbc-button-xs,button.kbc-button-xs{font-size:.725rem;line-height:1.5;margin:.3125rem .3125rem .4375rem;padding:.175rem .5rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}a.kbc-button-xs.focus,a.kbc-button-xs.hover,a.kbc-button-xs:focus,a.kbc-button-xs:hover,button.kbc-button-xs.focus,button.kbc-button-xs.hover,button.kbc-button-xs:focus,button.kbc-button-xs:hover{transform:translate3d(0,1px,2px)}a.kbc-button-xs.focus:after,a.kbc-button-xs.hover:after,a.kbc-button-xs:focus:after,a.kbc-button-xs:hover:after,button.kbc-button-xs.focus:after,button.kbc-button-xs.hover:after,button.kbc-button-xs:focus:after,button.kbc-button-xs:hover:after{transform:translate3d(0,-1px,-2px)}a.kbc-button-xs.active,a.kbc-button-xs:active,button.kbc-button-xs.active,button.kbc-button-xs:active{border-color:transparent;box-shadow:none;transform:translate3d(0,2px,0)}a.kbc-button-xs.active:after,a.kbc-button-xs:active:after,button.kbc-button-xs.active:after,button.kbc-button-xs:active:after{transform:translate3d(0,-2px,0)}a.kbc-button-xs:after,button.kbc-button-xs:after{border-radius:.375rem;border-width:.0625rem;bottom:-6px;left:-.25rem;right:-.25rem;top:-2px;transform:translateZ(-2px)}a.kbc-button-xs.focus,a.kbc-button-xs.hover,a.kbc-button-xs:focus,a.kbc-button-xs:hover,button.kbc-button-xs.focus,button.kbc-button-xs.hover,button.kbc-button-xs:focus,button.kbc-button-xs:hover{box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#e6e6e6;color:#343a40}a.kbc-button-xs.active,a.kbc-button-xs:active,button.kbc-button-xs.active,button.kbc-button-xs:active{background-color:#e6e6e6;box-shadow:0 0 1px 1px #b3b3b3;color:#343a40}a.kbc-button-xs:after,button.kbc-button-xs:after{border-color:#ccc}a.kbc-button-xs.kbc-button-primary,button.kbc-button-xs.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}a.kbc-button-xs.kbc-button-primary.focus,a.kbc-button-xs.kbc-button-primary.hover,a.kbc-button-xs.kbc-button-primary:focus,a.kbc-button-xs.kbc-button-primary:hover,button.kbc-button-xs.kbc-button-primary.focus,button.kbc-button-xs.kbc-button-primary.hover,button.kbc-button-xs.kbc-button-primary:focus,button.kbc-button-xs.kbc-button-primary:hover{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#3395ff;color:#f8f9fa}a.kbc-button-xs.kbc-button-primary.active,a.kbc-button-xs.kbc-button-primary:active,button.kbc-button-xs.kbc-button-primary.active,button.kbc-button-xs.kbc-button-primary:active{background-color:#3395ff;box-shadow:0 0 1px 1px #99caff;color:#f8f9fa}a.kbc-button-xs.kbc-button-primary:after,button.kbc-button-xs.kbc-button-primary:after{border-color:#66b0ff}a.kbc-button-xs.kbc-button-secondary,button.kbc-button-xs.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}a.kbc-button-xs.kbc-button-secondary.focus,a.kbc-button-xs.kbc-button-secondary.hover,a.kbc-button-xs.kbc-button-secondary:focus,a.kbc-button-xs.kbc-button-secondary:hover,button.kbc-button-xs.kbc-button-secondary.focus,button.kbc-button-xs.kbc-button-secondary.hover,button.kbc-button-xs.kbc-button-secondary:focus,button.kbc-button-xs.kbc-button-secondary:hover{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#868e96;color:#f8f9fa}a.kbc-button-xs.kbc-button-secondary.active,a.kbc-button-xs.kbc-button-secondary:active,button.kbc-button-xs.kbc-button-secondary.active,button.kbc-button-xs.kbc-button-secondary:active{background-color:#868e96;box-shadow:0 0 1px 1px #bcc1c6;color:#f8f9fa}a.kbc-button-xs.kbc-button-secondary:after,button.kbc-button-xs.kbc-button-secondary:after{border-color:#a1a8ae}a.kbc-button-xs.kbc-button-success,button.kbc-button-xs.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}a.kbc-button-xs.kbc-button-success.focus,a.kbc-button-xs.kbc-button-success.hover,a.kbc-button-xs.kbc-button-success:focus,a.kbc-button-xs.kbc-button-success:hover,button.kbc-button-xs.kbc-button-success.focus,button.kbc-button-xs.kbc-button-success.hover,button.kbc-button-xs.kbc-button-success:focus,button.kbc-button-xs.kbc-button-success:hover{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#34ce57;color:#f8f9fa}a.kbc-button-xs.kbc-button-success.active,a.kbc-button-xs.kbc-button-success:active,button.kbc-button-xs.kbc-button-success.active,button.kbc-button-xs.kbc-button-success:active{background-color:#34ce57;box-shadow:0 0 1px 1px #86e29b;color:#f8f9fa}a.kbc-button-xs.kbc-button-success:after,button.kbc-button-xs.kbc-button-success:after{border-color:#5dd879}a.kbc-button-xs.kbc-button-info,button.kbc-button-xs.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}a.kbc-button-xs.kbc-button-info.focus,a.kbc-button-xs.kbc-button-info.hover,a.kbc-button-xs.kbc-button-info:focus,a.kbc-button-xs.kbc-button-info:hover,button.kbc-button-xs.kbc-button-info.focus,button.kbc-button-xs.kbc-button-info.hover,button.kbc-button-xs.kbc-button-info:focus,button.kbc-button-xs.kbc-button-info:hover{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#1fc8e3;color:#343a40}a.kbc-button-xs.kbc-button-info.active,a.kbc-button-xs.kbc-button-info:active,button.kbc-button-xs.kbc-button-info.active,button.kbc-button-xs.kbc-button-info:active{background-color:#1fc8e3;box-shadow:0 0 1px 1px #7adeee;color:#343a40}a.kbc-button-xs.kbc-button-info:after,button.kbc-button-xs.kbc-button-info:after{border-color:#4cd3e9}a.kbc-button-xs.kbc-button-warning,button.kbc-button-xs.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}a.kbc-button-xs.kbc-button-warning.focus,a.kbc-button-xs.kbc-button-warning.hover,a.kbc-button-xs.kbc-button-warning:focus,a.kbc-button-xs.kbc-button-warning:hover,button.kbc-button-xs.kbc-button-warning.focus,button.kbc-button-xs.kbc-button-warning.hover,button.kbc-button-xs.kbc-button-warning:focus,button.kbc-button-xs.kbc-button-warning:hover{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#d39e00;color:#343a40}a.kbc-button-xs.kbc-button-warning.active,a.kbc-button-xs.kbc-button-warning:active,button.kbc-button-xs.kbc-button-warning.active,button.kbc-button-xs.kbc-button-warning:active{background-color:#d39e00;box-shadow:0 0 1px 1px #6d5200;color:#343a40}a.kbc-button-xs.kbc-button-warning:after,button.kbc-button-xs.kbc-button-warning:after{border-color:#a07800}a.kbc-button-xs.kbc-button-danger,button.kbc-button-xs.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}a.kbc-button-xs.kbc-button-danger.focus,a.kbc-button-xs.kbc-button-danger.hover,a.kbc-button-xs.kbc-button-danger:focus,a.kbc-button-xs.kbc-button-danger:hover,button.kbc-button-xs.kbc-button-danger.focus,button.kbc-button-xs.kbc-button-danger.hover,button.kbc-button-xs.kbc-button-danger:focus,button.kbc-button-xs.kbc-button-danger:hover{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#e4606d;color:#f8f9fa}a.kbc-button-xs.kbc-button-danger.active,a.kbc-button-xs.kbc-button-danger:active,button.kbc-button-xs.kbc-button-danger.active,button.kbc-button-xs.kbc-button-danger:active{background-color:#e4606d;box-shadow:0 0 1px 1px #f3b7bd;color:#f8f9fa}a.kbc-button-xs.kbc-button-danger:after,button.kbc-button-xs.kbc-button-danger:after{border-color:#eb8c95}a.kbc-button-xs.kbc-button-light,button.kbc-button-xs.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}a.kbc-button-xs.kbc-button-light.focus,a.kbc-button-xs.kbc-button-light.hover,a.kbc-button-xs.kbc-button-light:focus,a.kbc-button-xs.kbc-button-light:hover,button.kbc-button-xs.kbc-button-light.focus,button.kbc-button-xs.kbc-button-light.hover,button.kbc-button-xs.kbc-button-light:focus,button.kbc-button-xs.kbc-button-light:hover{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#dae0e5;color:#343a40}a.kbc-button-xs.kbc-button-light.active,a.kbc-button-xs.kbc-button-light:active,button.kbc-button-xs.kbc-button-light.active,button.kbc-button-xs.kbc-button-light:active{background-color:#dae0e5;box-shadow:0 0 1px 1px #9fadba;color:#343a40}a.kbc-button-xs.kbc-button-light:after,button.kbc-button-xs.kbc-button-light:after{border-color:#bdc6d0}a.kbc-button-xs.kbc-button-dark,button.kbc-button-xs.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}a.kbc-button-xs.kbc-button-dark.focus,a.kbc-button-xs.kbc-button-dark.hover,a.kbc-button-xs.kbc-button-dark:focus,a.kbc-button-xs.kbc-button-dark:hover,button.kbc-button-xs.kbc-button-dark.focus,button.kbc-button-xs.kbc-button-dark.hover,button.kbc-button-xs.kbc-button-dark:focus,button.kbc-button-xs.kbc-button-dark:hover{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,2px .5px 4px #adb5bd,0 -1px .5px #adb5bd;background-color:#4b545c;color:#f8f9fa}a.kbc-button-xs.kbc-button-dark.active,a.kbc-button-xs.kbc-button-dark:active,button.kbc-button-xs.kbc-button-dark.active,button.kbc-button-xs.kbc-button-dark:active{background-color:#4b545c;box-shadow:0 0 1px 1px #7a8793;color:#f8f9fa}a.kbc-button-xs.kbc-button-dark:after,button.kbc-button-xs.kbc-button-dark:after{border-color:#626d78}a.kbc-button-sm,button.kbc-button-sm{font-size:.875rem;line-height:1.5;margin:.34375rem .34375rem .53125rem;padding:.25rem .5rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}a.kbc-button-sm.focus,a.kbc-button-sm.hover,a.kbc-button-sm:focus,a.kbc-button-sm:hover,button.kbc-button-sm.focus,button.kbc-button-sm.hover,button.kbc-button-sm:focus,button.kbc-button-sm:hover{transform:translate3d(0,1px,3px)}a.kbc-button-sm.focus:after,a.kbc-button-sm.hover:after,a.kbc-button-sm:focus:after,a.kbc-button-sm:hover:after,button.kbc-button-sm.focus:after,button.kbc-button-sm.hover:after,button.kbc-button-sm:focus:after,button.kbc-button-sm:hover:after{transform:translate3d(0,-1px,-3px)}a.kbc-button-sm.active,a.kbc-button-sm:active,button.kbc-button-sm.active,button.kbc-button-sm:active{border-color:transparent;box-shadow:none;transform:translate3d(0,3px,0)}a.kbc-button-sm.active:after,a.kbc-button-sm:active:after,button.kbc-button-sm.active:after,button.kbc-button-sm:active:after{transform:translate3d(0,-3px,0)}a.kbc-button-sm:after,button.kbc-button-sm:after{border-radius:.375rem;border-width:.09375rem;bottom:-7px;left:-.25rem;right:-.25rem;top:-1px;transform:translateZ(-3px)}a.kbc-button-sm.focus,a.kbc-button-sm.hover,a.kbc-button-sm:focus,a.kbc-button-sm:hover,button.kbc-button-sm.focus,button.kbc-button-sm.hover,button.kbc-button-sm:focus,button.kbc-button-sm:hover{box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#e6e6e6;color:#343a40}a.kbc-button-sm.active,a.kbc-button-sm:active,button.kbc-button-sm.active,button.kbc-button-sm:active{background-color:#e6e6e6;box-shadow:0 0 1px 1px #b3b3b3;color:#343a40}a.kbc-button-sm:after,button.kbc-button-sm:after{border-color:#ccc}a.kbc-button-sm.kbc-button-primary,button.kbc-button-sm.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}a.kbc-button-sm.kbc-button-primary.focus,a.kbc-button-sm.kbc-button-primary.hover,a.kbc-button-sm.kbc-button-primary:focus,a.kbc-button-sm.kbc-button-primary:hover,button.kbc-button-sm.kbc-button-primary.focus,button.kbc-button-sm.kbc-button-primary.hover,button.kbc-button-sm.kbc-button-primary:focus,button.kbc-button-sm.kbc-button-primary:hover{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#3395ff;color:#f8f9fa}a.kbc-button-sm.kbc-button-primary.active,a.kbc-button-sm.kbc-button-primary:active,button.kbc-button-sm.kbc-button-primary.active,button.kbc-button-sm.kbc-button-primary:active{background-color:#3395ff;box-shadow:0 0 1px 1px #99caff;color:#f8f9fa}a.kbc-button-sm.kbc-button-primary:after,button.kbc-button-sm.kbc-button-primary:after{border-color:#66b0ff}a.kbc-button-sm.kbc-button-secondary,button.kbc-button-sm.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}a.kbc-button-sm.kbc-button-secondary.focus,a.kbc-button-sm.kbc-button-secondary.hover,a.kbc-button-sm.kbc-button-secondary:focus,a.kbc-button-sm.kbc-button-secondary:hover,button.kbc-button-sm.kbc-button-secondary.focus,button.kbc-button-sm.kbc-button-secondary.hover,button.kbc-button-sm.kbc-button-secondary:focus,button.kbc-button-sm.kbc-button-secondary:hover{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#868e96;color:#f8f9fa}a.kbc-button-sm.kbc-button-secondary.active,a.kbc-button-sm.kbc-button-secondary:active,button.kbc-button-sm.kbc-button-secondary.active,button.kbc-button-sm.kbc-button-secondary:active{background-color:#868e96;box-shadow:0 0 1px 1px #bcc1c6;color:#f8f9fa}a.kbc-button-sm.kbc-button-secondary:after,button.kbc-button-sm.kbc-button-secondary:after{border-color:#a1a8ae}a.kbc-button-sm.kbc-button-success,button.kbc-button-sm.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}a.kbc-button-sm.kbc-button-success.focus,a.kbc-button-sm.kbc-button-success.hover,a.kbc-button-sm.kbc-button-success:focus,a.kbc-button-sm.kbc-button-success:hover,button.kbc-button-sm.kbc-button-success.focus,button.kbc-button-sm.kbc-button-success.hover,button.kbc-button-sm.kbc-button-success:focus,button.kbc-button-sm.kbc-button-success:hover{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#34ce57;color:#f8f9fa}a.kbc-button-sm.kbc-button-success.active,a.kbc-button-sm.kbc-button-success:active,button.kbc-button-sm.kbc-button-success.active,button.kbc-button-sm.kbc-button-success:active{background-color:#34ce57;box-shadow:0 0 1px 1px #86e29b;color:#f8f9fa}a.kbc-button-sm.kbc-button-success:after,button.kbc-button-sm.kbc-button-success:after{border-color:#5dd879}a.kbc-button-sm.kbc-button-info,button.kbc-button-sm.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}a.kbc-button-sm.kbc-button-info.focus,a.kbc-button-sm.kbc-button-info.hover,a.kbc-button-sm.kbc-button-info:focus,a.kbc-button-sm.kbc-button-info:hover,button.kbc-button-sm.kbc-button-info.focus,button.kbc-button-sm.kbc-button-info.hover,button.kbc-button-sm.kbc-button-info:focus,button.kbc-button-sm.kbc-button-info:hover{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#1fc8e3;color:#343a40}a.kbc-button-sm.kbc-button-info.active,a.kbc-button-sm.kbc-button-info:active,button.kbc-button-sm.kbc-button-info.active,button.kbc-button-sm.kbc-button-info:active{background-color:#1fc8e3;box-shadow:0 0 1px 1px #7adeee;color:#343a40}a.kbc-button-sm.kbc-button-info:after,button.kbc-button-sm.kbc-button-info:after{border-color:#4cd3e9}a.kbc-button-sm.kbc-button-warning,button.kbc-button-sm.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}a.kbc-button-sm.kbc-button-warning.focus,a.kbc-button-sm.kbc-button-warning.hover,a.kbc-button-sm.kbc-button-warning:focus,a.kbc-button-sm.kbc-button-warning:hover,button.kbc-button-sm.kbc-button-warning.focus,button.kbc-button-sm.kbc-button-warning.hover,button.kbc-button-sm.kbc-button-warning:focus,button.kbc-button-sm.kbc-button-warning:hover{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#d39e00;color:#343a40}a.kbc-button-sm.kbc-button-warning.active,a.kbc-button-sm.kbc-button-warning:active,button.kbc-button-sm.kbc-button-warning.active,button.kbc-button-sm.kbc-button-warning:active{background-color:#d39e00;box-shadow:0 0 1px 1px #6d5200;color:#343a40}a.kbc-button-sm.kbc-button-warning:after,button.kbc-button-sm.kbc-button-warning:after{border-color:#a07800}a.kbc-button-sm.kbc-button-danger,button.kbc-button-sm.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}a.kbc-button-sm.kbc-button-danger.focus,a.kbc-button-sm.kbc-button-danger.hover,a.kbc-button-sm.kbc-button-danger:focus,a.kbc-button-sm.kbc-button-danger:hover,button.kbc-button-sm.kbc-button-danger.focus,button.kbc-button-sm.kbc-button-danger.hover,button.kbc-button-sm.kbc-button-danger:focus,button.kbc-button-sm.kbc-button-danger:hover{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#e4606d;color:#f8f9fa}a.kbc-button-sm.kbc-button-danger.active,a.kbc-button-sm.kbc-button-danger:active,button.kbc-button-sm.kbc-button-danger.active,button.kbc-button-sm.kbc-button-danger:active{background-color:#e4606d;box-shadow:0 0 1px 1px #f3b7bd;color:#f8f9fa}a.kbc-button-sm.kbc-button-danger:after,button.kbc-button-sm.kbc-button-danger:after{border-color:#eb8c95}a.kbc-button-sm.kbc-button-light,button.kbc-button-sm.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}a.kbc-button-sm.kbc-button-light.focus,a.kbc-button-sm.kbc-button-light.hover,a.kbc-button-sm.kbc-button-light:focus,a.kbc-button-sm.kbc-button-light:hover,button.kbc-button-sm.kbc-button-light.focus,button.kbc-button-sm.kbc-button-light.hover,button.kbc-button-sm.kbc-button-light:focus,button.kbc-button-sm.kbc-button-light:hover{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#dae0e5;color:#343a40}a.kbc-button-sm.kbc-button-light.active,a.kbc-button-sm.kbc-button-light:active,button.kbc-button-sm.kbc-button-light.active,button.kbc-button-sm.kbc-button-light:active{background-color:#dae0e5;box-shadow:0 0 1px 1px #9fadba;color:#343a40}a.kbc-button-sm.kbc-button-light:after,button.kbc-button-sm.kbc-button-light:after{border-color:#bdc6d0}a.kbc-button-sm.kbc-button-dark,button.kbc-button-sm.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,2px 1.5px 4px #adb5bd,0 -1px 1.5px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}a.kbc-button-sm.kbc-button-dark.focus,a.kbc-button-sm.kbc-button-dark.hover,a.kbc-button-sm.kbc-button-dark:focus,a.kbc-button-sm.kbc-button-dark:hover,button.kbc-button-sm.kbc-button-dark.focus,button.kbc-button-sm.kbc-button-dark.hover,button.kbc-button-sm.kbc-button-dark:focus,button.kbc-button-sm.kbc-button-dark:hover{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,2px 1px 4px #adb5bd,0 -1px 1px #adb5bd;background-color:#4b545c;color:#f8f9fa}a.kbc-button-sm.kbc-button-dark.active,a.kbc-button-sm.kbc-button-dark:active,button.kbc-button-sm.kbc-button-dark.active,button.kbc-button-sm.kbc-button-dark:active{background-color:#4b545c;box-shadow:0 0 1px 1px #7a8793;color:#f8f9fa}a.kbc-button-sm.kbc-button-dark:after,button.kbc-button-sm.kbc-button-dark:after{border-color:#626d78}a.kbc-button-lg,button.kbc-button-lg{font-size:1.25rem;line-height:1.5;margin:.375rem .375rem .875rem;padding:.5rem 1rem;box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,0 5px #d9d9d9,0 6px #d9d9d9,0 7px #d9d9d9,0 8px #d9d9d9,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#fff;border-color:#e6e6e6;color:#343a40}a.kbc-button-lg.focus,a.kbc-button-lg.hover,a.kbc-button-lg:focus,a.kbc-button-lg:hover,button.kbc-button-lg.focus,button.kbc-button-lg.hover,button.kbc-button-lg:focus,button.kbc-button-lg:hover{transform:translate3d(0,1px,8px)}a.kbc-button-lg.focus:after,a.kbc-button-lg.hover:after,a.kbc-button-lg:focus:after,a.kbc-button-lg:hover:after,button.kbc-button-lg.focus:after,button.kbc-button-lg.hover:after,button.kbc-button-lg:focus:after,button.kbc-button-lg:hover:after{transform:translate3d(0,-1px,-8px)}a.kbc-button-lg.active,a.kbc-button-lg:active,button.kbc-button-lg.active,button.kbc-button-lg:active{border-color:transparent;box-shadow:none;transform:translate3d(0,8px,0)}a.kbc-button-lg.active:after,a.kbc-button-lg:active:after,button.kbc-button-lg.active:after,button.kbc-button-lg:active:after{transform:translate3d(0,-8px,0)}a.kbc-button-lg:after,button.kbc-button-lg:after{border-radius:.5rem;border-width:.125rem;bottom:-13px;left:-.375rem;right:-.375rem;top:3px;transform:translateZ(-8px)}a.kbc-button-lg.focus,a.kbc-button-lg.hover,a.kbc-button-lg:focus,a.kbc-button-lg:hover,button.kbc-button-lg.focus,button.kbc-button-lg.hover,button.kbc-button-lg:focus,button.kbc-button-lg:hover{box-shadow:0 0 #d9d9d9,0 0 #d9d9d9,0 1px #d9d9d9,0 2px #d9d9d9,0 3px #d9d9d9,0 4px #d9d9d9,0 5px #d9d9d9,0 6px #d9d9d9,0 7px #d9d9d9,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#e6e6e6;color:#343a40}a.kbc-button-lg.active,a.kbc-button-lg:active,button.kbc-button-lg.active,button.kbc-button-lg:active{background-color:#e6e6e6;box-shadow:0 0 1px 1px #b3b3b3;color:#343a40}a.kbc-button-lg:after,button.kbc-button-lg:after{border-color:#ccc}a.kbc-button-lg.kbc-button-primary,button.kbc-button-lg.kbc-button-primary{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,0 5px #4da3ff,0 6px #4da3ff,0 7px #4da3ff,0 8px #4da3ff,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#007bff;border-color:#3395ff;color:#f8f9fa}a.kbc-button-lg.kbc-button-primary.focus,a.kbc-button-lg.kbc-button-primary.hover,a.kbc-button-lg.kbc-button-primary:focus,a.kbc-button-lg.kbc-button-primary:hover,button.kbc-button-lg.kbc-button-primary.focus,button.kbc-button-lg.kbc-button-primary.hover,button.kbc-button-lg.kbc-button-primary:focus,button.kbc-button-lg.kbc-button-primary:hover{box-shadow:0 0 #4da3ff,0 0 #4da3ff,0 1px #4da3ff,0 2px #4da3ff,0 3px #4da3ff,0 4px #4da3ff,0 5px #4da3ff,0 6px #4da3ff,0 7px #4da3ff,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#3395ff;color:#f8f9fa}a.kbc-button-lg.kbc-button-primary.active,a.kbc-button-lg.kbc-button-primary:active,button.kbc-button-lg.kbc-button-primary.active,button.kbc-button-lg.kbc-button-primary:active{background-color:#3395ff;box-shadow:0 0 1px 1px #99caff;color:#f8f9fa}a.kbc-button-lg.kbc-button-primary:after,button.kbc-button-lg.kbc-button-primary:after{border-color:#66b0ff}a.kbc-button-lg.kbc-button-secondary,button.kbc-button-lg.kbc-button-secondary{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,0 5px #939ba2,0 6px #939ba2,0 7px #939ba2,0 8px #939ba2,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#6c757d;border-color:#868e96;color:#f8f9fa}a.kbc-button-lg.kbc-button-secondary.focus,a.kbc-button-lg.kbc-button-secondary.hover,a.kbc-button-lg.kbc-button-secondary:focus,a.kbc-button-lg.kbc-button-secondary:hover,button.kbc-button-lg.kbc-button-secondary.focus,button.kbc-button-lg.kbc-button-secondary.hover,button.kbc-button-lg.kbc-button-secondary:focus,button.kbc-button-lg.kbc-button-secondary:hover{box-shadow:0 0 #939ba2,0 0 #939ba2,0 1px #939ba2,0 2px #939ba2,0 3px #939ba2,0 4px #939ba2,0 5px #939ba2,0 6px #939ba2,0 7px #939ba2,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#868e96;color:#f8f9fa}a.kbc-button-lg.kbc-button-secondary.active,a.kbc-button-lg.kbc-button-secondary:active,button.kbc-button-lg.kbc-button-secondary.active,button.kbc-button-lg.kbc-button-secondary:active{background-color:#868e96;box-shadow:0 0 1px 1px #bcc1c6;color:#f8f9fa}a.kbc-button-lg.kbc-button-secondary:after,button.kbc-button-lg.kbc-button-secondary:after{border-color:#a1a8ae}a.kbc-button-lg.kbc-button-success,button.kbc-button-lg.kbc-button-success{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,0 5px #48d368,0 6px #48d368,0 7px #48d368,0 8px #48d368,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#28a745;border-color:#34ce57;color:#f8f9fa}a.kbc-button-lg.kbc-button-success.focus,a.kbc-button-lg.kbc-button-success.hover,a.kbc-button-lg.kbc-button-success:focus,a.kbc-button-lg.kbc-button-success:hover,button.kbc-button-lg.kbc-button-success.focus,button.kbc-button-lg.kbc-button-success.hover,button.kbc-button-lg.kbc-button-success:focus,button.kbc-button-lg.kbc-button-success:hover{box-shadow:0 0 #48d368,0 0 #48d368,0 1px #48d368,0 2px #48d368,0 3px #48d368,0 4px #48d368,0 5px #48d368,0 6px #48d368,0 7px #48d368,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#34ce57;color:#f8f9fa}a.kbc-button-lg.kbc-button-success.active,a.kbc-button-lg.kbc-button-success:active,button.kbc-button-lg.kbc-button-success.active,button.kbc-button-lg.kbc-button-success:active{background-color:#34ce57;box-shadow:0 0 1px 1px #86e29b;color:#f8f9fa}a.kbc-button-lg.kbc-button-success:after,button.kbc-button-lg.kbc-button-success:after{border-color:#5dd879}a.kbc-button-lg.kbc-button-info,button.kbc-button-lg.kbc-button-info{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,0 5px #36cee6,0 6px #36cee6,0 7px #36cee6,0 8px #36cee6,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#17a2b8;border-color:#1fc8e3;color:#f8f9fa}a.kbc-button-lg.kbc-button-info.focus,a.kbc-button-lg.kbc-button-info.hover,a.kbc-button-lg.kbc-button-info:focus,a.kbc-button-lg.kbc-button-info:hover,button.kbc-button-lg.kbc-button-info.focus,button.kbc-button-lg.kbc-button-info.hover,button.kbc-button-lg.kbc-button-info:focus,button.kbc-button-lg.kbc-button-info:hover{box-shadow:0 0 #36cee6,0 0 #36cee6,0 1px #36cee6,0 2px #36cee6,0 3px #36cee6,0 4px #36cee6,0 5px #36cee6,0 6px #36cee6,0 7px #36cee6,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#1fc8e3;color:#343a40}a.kbc-button-lg.kbc-button-info.active,a.kbc-button-lg.kbc-button-info:active,button.kbc-button-lg.kbc-button-info.active,button.kbc-button-lg.kbc-button-info:active{background-color:#1fc8e3;box-shadow:0 0 1px 1px #7adeee;color:#343a40}a.kbc-button-lg.kbc-button-info:after,button.kbc-button-lg.kbc-button-info:after{border-color:#4cd3e9}a.kbc-button-lg.kbc-button-warning,button.kbc-button-lg.kbc-button-warning{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,0 5px #ba8b00,0 6px #ba8b00,0 7px #ba8b00,0 8px #ba8b00,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#ffc107;border-color:#d39e00;color:#343a40}a.kbc-button-lg.kbc-button-warning.focus,a.kbc-button-lg.kbc-button-warning.hover,a.kbc-button-lg.kbc-button-warning:focus,a.kbc-button-lg.kbc-button-warning:hover,button.kbc-button-lg.kbc-button-warning.focus,button.kbc-button-lg.kbc-button-warning.hover,button.kbc-button-lg.kbc-button-warning:focus,button.kbc-button-lg.kbc-button-warning:hover{box-shadow:0 0 #ba8b00,0 0 #ba8b00,0 1px #ba8b00,0 2px #ba8b00,0 3px #ba8b00,0 4px #ba8b00,0 5px #ba8b00,0 6px #ba8b00,0 7px #ba8b00,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#d39e00;color:#343a40}a.kbc-button-lg.kbc-button-warning.active,a.kbc-button-lg.kbc-button-warning:active,button.kbc-button-lg.kbc-button-warning.active,button.kbc-button-lg.kbc-button-warning:active{background-color:#d39e00;box-shadow:0 0 1px 1px #6d5200;color:#343a40}a.kbc-button-lg.kbc-button-warning:after,button.kbc-button-lg.kbc-button-warning:after{border-color:#a07800}a.kbc-button-lg.kbc-button-danger,button.kbc-button-lg.kbc-button-danger{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,0 5px #e77681,0 6px #e77681,0 7px #e77681,0 8px #e77681,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#dc3545;border-color:#e4606d;color:#f8f9fa}a.kbc-button-lg.kbc-button-danger.focus,a.kbc-button-lg.kbc-button-danger.hover,a.kbc-button-lg.kbc-button-danger:focus,a.kbc-button-lg.kbc-button-danger:hover,button.kbc-button-lg.kbc-button-danger.focus,button.kbc-button-lg.kbc-button-danger.hover,button.kbc-button-lg.kbc-button-danger:focus,button.kbc-button-lg.kbc-button-danger:hover{box-shadow:0 0 #e77681,0 0 #e77681,0 1px #e77681,0 2px #e77681,0 3px #e77681,0 4px #e77681,0 5px #e77681,0 6px #e77681,0 7px #e77681,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#e4606d;color:#f8f9fa}a.kbc-button-lg.kbc-button-danger.active,a.kbc-button-lg.kbc-button-danger:active,button.kbc-button-lg.kbc-button-danger.active,button.kbc-button-lg.kbc-button-danger:active{background-color:#e4606d;box-shadow:0 0 1px 1px #f3b7bd;color:#f8f9fa}a.kbc-button-lg.kbc-button-danger:after,button.kbc-button-lg.kbc-button-danger:after{border-color:#eb8c95}a.kbc-button-lg.kbc-button-light,button.kbc-button-lg.kbc-button-light{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,0 5px #cbd3da,0 6px #cbd3da,0 7px #cbd3da,0 8px #cbd3da,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#f8f9fa;border-color:#dae0e5;color:#343a40}a.kbc-button-lg.kbc-button-light.focus,a.kbc-button-lg.kbc-button-light.hover,a.kbc-button-lg.kbc-button-light:focus,a.kbc-button-lg.kbc-button-light:hover,button.kbc-button-lg.kbc-button-light.focus,button.kbc-button-lg.kbc-button-light.hover,button.kbc-button-lg.kbc-button-light:focus,button.kbc-button-lg.kbc-button-light:hover{box-shadow:0 0 #cbd3da,0 0 #cbd3da,0 1px #cbd3da,0 2px #cbd3da,0 3px #cbd3da,0 4px #cbd3da,0 5px #cbd3da,0 6px #cbd3da,0 7px #cbd3da,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#dae0e5;color:#343a40}a.kbc-button-lg.kbc-button-light.active,a.kbc-button-lg.kbc-button-light:active,button.kbc-button-lg.kbc-button-light.active,button.kbc-button-lg.kbc-button-light:active{background-color:#dae0e5;box-shadow:0 0 1px 1px #9fadba;color:#343a40}a.kbc-button-lg.kbc-button-light:after,button.kbc-button-lg.kbc-button-light:after{border-color:#bdc6d0}a.kbc-button-lg.kbc-button-dark,button.kbc-button-lg.kbc-button-dark{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,0 5px #56606a,0 6px #56606a,0 7px #56606a,0 8px #56606a,2px 4px 4px #adb5bd,0 -1px 4px #adb5bd;background-color:#343a40;border-color:#4b545c;color:#f8f9fa}a.kbc-button-lg.kbc-button-dark.focus,a.kbc-button-lg.kbc-button-dark.hover,a.kbc-button-lg.kbc-button-dark:focus,a.kbc-button-lg.kbc-button-dark:hover,button.kbc-button-lg.kbc-button-dark.focus,button.kbc-button-lg.kbc-button-dark.hover,button.kbc-button-lg.kbc-button-dark:focus,button.kbc-button-lg.kbc-button-dark:hover{box-shadow:0 0 #56606a,0 0 #56606a,0 1px #56606a,0 2px #56606a,0 3px #56606a,0 4px #56606a,0 5px #56606a,0 6px #56606a,0 7px #56606a,2px 3.5px 4px #adb5bd,0 -1px 3.5px #adb5bd;background-color:#4b545c;color:#f8f9fa}a.kbc-button-lg.kbc-button-dark.active,a.kbc-button-lg.kbc-button-dark:active,button.kbc-button-lg.kbc-button-dark.active,button.kbc-button-lg.kbc-button-dark:active{background-color:#4b545c;box-shadow:0 0 1px 1px #7a8793;color:#f8f9fa}a.kbc-button-lg.kbc-button-dark:after,button.kbc-button-lg.kbc-button-dark:after{border-color:#626d78}a.kbc-button.disabled,a.kbc-button:disabled,button.kbc-button.disabled,button.kbc-button:disabled{cursor:not-allowed;opacity:.65;pointer-events:none}a.kbc-button.focus,a.kbc-button.hover,a.kbc-button:focus,a.kbc-button:hover,button.kbc-button.focus,button.kbc-button.hover,button.kbc-button:focus,button.kbc-button:hover{outline:none} \ No newline at end of file diff --git a/htdocs/css/shortcuts.css b/htdocs/css/shortcuts.css new file mode 100644 index 00000000..b5772fd7 --- /dev/null +++ b/htdocs/css/shortcuts.css @@ -0,0 +1,79 @@ +/* import keyboard-css for keys in help */ +@import url("keyboard.min.css"); + +#ks-overlay { + position: fixed; + top: 5vh; + left: calc((100vw - 800px) / 2); + max-height: 90vh; + width: 800px; + color: white; + background-color: #000; + opacity: 0.8; + z-index: 10000; + border: 3px solid white; + border-radius: 20px; + display: flex; + align-items: center; + flex-direction: column; + padding: 0.5rem; +} + +.ks-title { + font-weight: bold; + font-size: 1.5rem; + margin-top: 1rem; +} + +.ks-subtitle { + font-size: 0.8rem; + margin-top: 0.25rem; +} + +.ks-separator { + border-top: 1px dotted white; + align-self: stretch; + margin: 1rem; +} + +.ks-content { + padding: 0 0.75rem; + font-size: 1rem; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + overflow-y: auto; +} + +.ks-item { + width: 240px; + padding: 0.25rem; + border: 1px dashed #444; + margin-bottom: 0.25rem; + display: flex; + justify-content: space-between; + flex-wrap: nowrap; + align-items: center; + flex-direction: column; + /* flex-direction: row; */ +} + +.ks-item-txt { + color: silver; +} + +.ks-item-kbd { + text-wrap: nowrap; + color: silver; +} + +a.kbc-button-xs, button.kbc-button-xs { + padding: 0.02rem 0.25rem; +} + +a.kbc-button-sm, button.kbc-button-sm { + padding: 0 0.5rem; + font-size: .85rem; +} diff --git a/htdocs/index.html b/htdocs/index.html index 2453f9bf..1a4f2c31 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -35,6 +35,7 @@ + @@ -42,6 +43,7 @@ +
${header}
diff --git a/htdocs/lib/Shortcuts.js b/htdocs/lib/Shortcuts.js new file mode 100644 index 00000000..59312b66 --- /dev/null +++ b/htdocs/lib/Shortcuts.js @@ -0,0 +1,389 @@ +// +// Handle keyboard shortcuts +// + +function Shortcuts() {} + +Shortcuts.init = function(target) { + var that = this; + target.addEventListener('keydown', function(e) { that.handleKey(e); }); + + this.overlay = jQuery('
'); + this.overlay.hide(); + this.overlay.appendTo(target); + + this.overlay.html(` +
Keyboard Shortcuts
+
Hide this help with '?'.
+
+
+ +
+
tune frequency
+
${this.keycap('ArrowLeft')}|${this.keycap('ArrowRight')}
+
+
+
zoom waterfall
+
${this.keycap('ArrowUp')}|${this.keycap('ArrowDown')}
+
+
+
select modulation
+
(${this.keycap('Control')}+) ${this.keycap('0')}..${this.keycap('9')}
+
+ +
+
change tuning step
+
${this.keycap('[')}|${this.keycap(']')}
+
+
+
change volume
+
${this.keycap('Control')}+${this.keycap('ArrowUp')}|${this.keycap('ArrowDown')}
+
+
+
mute/unumte sound
+
${this.keycap('Space')}
+
+ +
+
auto-set squelch
+
${this.keycap('A')}
+
+
+
change squelch level
+
${this.keycap('Control')}+${this.keycap('ArrowLeft')}|${this.keycap('ArrowRight')}
+
+
+
disable squelch
+
${this.keycap('D')}
+
+ +
+
toggle noise reduction
+
${this.keycap('N')}
+
+
+
adjust bandpass offset
+
${this.keycap('Shift')}+${this.keycap('ArrowLeft')}|${this.keycap('ArrowRight')}
+
+
+
adjust bandpass width
+
${this.keycap('Shift')}+${this.keycap('ArrowUp')}|${this.keycap('ArrowDown')}
+
+ +
+
toggle scanner
+
${this.keycap('S')}
+
+
+
adjust waterfall min level
+
${this.keycap(',')}|${this.keycap('.')}
+
+
+
adjust waterfall max level
+
${this.keycap('<')}|${this.keycap('>')}
+
+ +
+
auto-set colors once
+
${this.keycap('Z')}
+
+
+
auto-set colors
+
${this.keycap('X')}
+
+
+
set default colors
+
${this.keycap('C')}
+
+ +
+
toggle recorder
+
${this.keycap('R')}
+
+
+
toggle spectrum
+
${this.keycap('V')}
+
+
+
toggle bandplan
+
${this.keycap('B')}
+
+ +
+
open map
+
${this.keycap('M')}
+
+
+
open files browser
+
${this.keycap('F')}
+
+
+
open documentation
+
${this.keycap('H')}
+
+
+ `); +}; + +Shortcuts.moveSlider = function(slider, delta) { + var $control = $(slider); + if (!$control.prop('disabled')) { + $control.val(parseInt($control.val()) + delta).change(); + } +}; + +Shortcuts.moveSelector = function(selector, steps) { + var $control = $(selector); + if (!$control.prop('disabled')) { + var max = $(selector + ' option').length; + var n = $control.prop('selectedIndex') + steps; + n = n < 0? n + max : n >= max? n - max : n; + $control.prop('selectedIndex', n).change(); + } +}; + +Shortcuts.handleKey = function(event) { + // Do not handle shortcuts when focused on a text or numeric input + var on_input = !!($('input:focus').length && ($('input:focus')[0].type === 'text' || $('input:focus')[0].type === 'number')); + if (on_input) return; + + // Leave CTRL+ combinations to the browser + if (event.ctrlKey && event.key.match(/^[a-z]$/i)) return; + + switch (event.key) { + case 'ArrowLeft': + if (event.ctrlKey) { + // CTRL+LEFT: Decrease squelch + this.moveSlider('#openwebrx-panel-receiver .openwebrx-squelch-slider', -1); + } else if (event.shiftKey) { + // SHIFT+LEFT: Shift bandpass left + var demodulators = getDemodulators(); + for (var i = 0; i < demodulators.length; i++) { + demodulators[i].moveBandpass( + demodulators[i].low_cut - 50, + demodulators[i].high_cut - 50 + ); + } + } else { + // LEFT: Tune down + tuneBySteps(-1); + } + break; + + case 'ArrowRight': + if (event.ctrlKey) { + // CTRL+RIGHT: Increase squelch + this.moveSlider('#openwebrx-panel-receiver .openwebrx-squelch-slider', 1); + } else if (event.shiftKey) { + // SHIFT+RIGHT: Shift bandpass right + var demodulators = getDemodulators(); + for (var i = 0; i < demodulators.length; i++) { + demodulators[i].moveBandpass( + demodulators[i].low_cut + 50, + demodulators[i].high_cut + 50 + ); + } + } else { + // RIGHT: Tune up + tuneBySteps(1); + } + break; + + case 'ArrowUp': + if (event.ctrlKey) { + // CTRL+UP: Increase volume + this.moveSlider('#openwebrx-panel-volume', 1); + } else if (event.shiftKey) { + // SHIFT+UP: Make bandpass wider + var demodulators = getDemodulators(); + for (var i = 0; i < demodulators.length; i++) { + demodulators[i].moveBandpass( + demodulators[i].low_cut - 50, + demodulators[i].high_cut + 50 + ); + } + } else { + // UP: Zoom in + zoomInOneStep(); + } + break; + + case 'ArrowDown': + if (event.ctrlKey) { + // CTRL+DOWN: Decrease volume + this.moveSlider('#openwebrx-panel-volume', -1); + } else if (event.shiftKey) { + // SHIFT+DOWN: Make bandpass narrower + var demodulators = getDemodulators(); + for (var i = 0; i < demodulators.length; i++) { + demodulators[i].moveBandpass( + demodulators[i].low_cut + 50, + demodulators[i].high_cut - 50 + ); + } + } else { + // DOWN: Zoom out + zoomOutOneStep(); + } + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case '0': + // [CTRL+]0-9: Select modulation + var $modes = $('.openwebrx-demodulator-button'); + var n = parseInt(event.key); + n = n > 0? n - 1 : 9; + if (event.ctrlKey) n += 10; + if (n < $modes.length) $modes[n].click(); + break; + + case '[': case '{': + // [: Decrease tuning step + this.moveSelector('#openwebrx-tuning-step-listbox', -1); + break; + + case ']': case '}': + // ]: Increase tuning step + this.moveSelector('#openwebrx-tuning-step-listbox', 1); + break; + + case 'a': + // A: Set squelch automatically + $('.openwebrx-squelch-auto').click(); + break; + + case 's': + // S: Toggle scanner + toggleScanner(); + break; + + case 'd': + // D: Turn off squelch + var $squelchControl = $('#openwebrx-panel-receiver .openwebrx-squelch-slider'); + if (!$squelchControl.prop('disabled')) { + $squelchControl.val($squelchControl.attr('min')).change(); + } + break; + + case 'z': + // Z: Set waterfall colors automatically + $('#openwebrx-waterfall-colors-auto').click(); + break; + + case 'x': + // X: Continuously auto-set waterfall colors + $('#openwebrx-waterfall-colors-auto').triggerHandler('contextmenu'); + break; + + case 'c': + // C: Set default waterfall colors + $('#openwebrx-waterfall-colors-default').click(); + break; + + case 'v': + // V: Toggle spectrum display + UI.toggleSpectrum(); + break; + + case 'b': + // B: Toggle bandplan display + UI.toggleBandplan(); + break; + + case ' ': + // SPACE: Mute/unmute sound + UI.toggleMute(); + break; + + case 'n': + // N: Toggle noise reduction + UI.toggleNR(); + break; + + case 'r': + // R: Toggle recorder + UI.toggleRecording(); + break; + + case '<': + // SHIFT+<: Decrease waterfall max level + this.moveSlider('#openwebrx-waterfall-color-max', -1); + break; + + case ',': + // <: Decrease waterfall min level + this.moveSlider('#openwebrx-waterfall-color-min', -1); + break; + + case '>': + // SHIFT+>: Increase waterfall max level + this.moveSlider('#openwebrx-waterfall-color-max', 1); + break; + + case '.': + // >: Increase waterfall min level + this.moveSlider('#openwebrx-waterfall-color-min', 1); + break; + + case 'f': + // F: Open file browser + $('a.button[target="openwebrx-files"]')[0].click(); + break; + + case 'h': + // H: Open documentation + $('a.button[target="openwebrx-help"]')[0].click(); + break; + + case 'm': + // M: Open map + $('a.button[target="openwebrx-map"]')[0].click(); + break; + + case '/': case '?': + Shortcuts.overlay.slideToggle(100); + break; + + default: + // Key not handled, pass it on + return; + } + + // Key handled, prevent default operation + event.preventDefault(); +}; + +Shortcuts.keycap = function(key) { + var keymap = { + ',': ', comma', + '.': '. dot', + ';': '; semicolon', + '\'': '\' apostrophe', + 'SHIFT': '⇧ Shift', + 'CONTROL': '⌃ Ctrl', + 'COMMAND': '⌘ Cmd', + 'META': '⌘ Meta', + 'ALT': '⌥ Alt', + 'OPTION': '⌥ Opt', + 'ENTER': '↵ Enter', + 'RETURN': '↵ Enter', + 'DELETE': '⌦ Del', + 'BACKSPACE': '⌫ BS', + 'ESCAPE': '⎋ ESC', + 'ARROWRIGHT': '→', + 'ARROWLEFT': '←', + 'ARROWUP': '↑', + 'ARROWDOWN': '↓', + 'PAGEUP': '⇞ PgUp', + 'PAGEDOWN': '⇟ PgDn', + 'HOME': '↖ Home', + 'END': '↘ End', + 'TAB': '⇥ Tab', + 'SPACE': '␣ Space', + 'INTERVAL': '␣ Space', + }; + + var k = keymap[key.toUpperCase()] || key.toUpperCase(); + + return ``; +}; diff --git a/htdocs/lib/UI.js b/htdocs/lib/UI.js index 1544b184..ea199f61 100644 --- a/htdocs/lib/UI.js +++ b/htdocs/lib/UI.js @@ -72,7 +72,7 @@ UI.loadSettings = function() { // Set audio volume in 0..150 range. UI.setVolume = function(x) { - x = Math.round(parseFloat(x)); + x = Math.min(150, Math.max(0, Math.round(parseFloat(x)))); if (this.volume != x) { this.volume = x; LS.save('volume', x); @@ -155,12 +155,14 @@ UI.toggleRecording = function(on) { var $recButton = $('.openwebrx-record-button'); - if (audioEngine.recording && (toggle || !on)) { - audioEngine.stopRecording(); - $recButton.css('animation-name', ''); - } else if (toggle || on) { - audioEngine.startRecording(); - $recButton.css('animation-name', 'openwebrx-record-animation'); + if ($recButton.is(':visible')) { + if (audioEngine.recording && (toggle || !on)) { + audioEngine.stopRecording(); + $recButton.css('animation-name', ''); + } else if (toggle || on) { + audioEngine.startRecording(); + $recButton.css('animation-name', 'openwebrx-record-animation'); + } } }; diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 0f6856bb..5992492d 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -1403,6 +1403,9 @@ function openwebrx_init() { // Create and run clock clock = new Clock($('#openwebrx-clock-utc')); + + // Initialize keyboard shortcuts + Shortcuts.init(document.body); } function initSliders() { diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py index 7d2e2f97..512a5b8b 100644 --- a/owrx/controllers/assets.py +++ b/owrx/controllers/assets.py @@ -138,6 +138,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): "lib/Modes.js", "lib/MetaPanel.js", "lib/Waterfall.js", + "lib/Shortcuts.js", "lib/Bandplan.js", "lib/Spectrum.js", "lib/Scanner.js",