

/*!
 *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */
/* FONT PATH
 * -------------------------- */
@font-face {
  font-family: 'FontAwesome';
  src: url('../fonts/fontawesome-webfont.eot?v=4.7.0');
  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
  font-weight: normal;
  font-style: normal;
}
.fa {
  display: inline-block;
  font: normal normal normal 14px/1 FontAwesome;
  font-size: inherit;
  text-rendering: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
  font-size: 1.33333333em;
  line-height: 0.75em;
  vertical-align: -15%;
}
.fa-2x {
  font-size: 2em;
}
.fa-3x {
  font-size: 3em;
}
.fa-4x {
  font-size: 4em;
}
.fa-5x {
  font-size: 5em;
}
.fa-fw {
  width: 1.28571429em;
  text-align: center;
}
.fa-ul {
  padding-left: 0;
  margin-left: 2.14285714em;
  list-style-type: none;
}
.fa-ul > li {
  position: relative;
}
.fa-li {
  position: absolute;
  left: -2.14285714em;
  width: 2.14285714em;
  top: 0.14285714em;
  text-align: center;
}
.fa-li.fa-lg {
  left: -1.85714286em;
}
.fa-border {
  padding: .2em .25em .15em;
  border: solid 0.08em #eeeeee;
  border-radius: .1em;
}
.fa-pull-left {
  float: left;
}
.fa-pull-right {
  float: right;
}
.fa.fa-pull-left {
  margin-right: .3em;
}
.fa.fa-pull-right {
  margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
  float: right;
}
.pull-left {
  float: left;
}
.fa.pull-left {
  margin-right: .3em;
}
.fa.pull-right {
  margin-left: .3em;
}
.fa-spin {
  -webkit-animation: fa-spin 2s infinite linear;
  animation: fa-spin 2s infinite linear;
}
.fa-pulse {
  -webkit-animation: fa-spin 1s infinite steps(8);
  animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(359deg);
    transform: rotate(359deg);
  }
}
@keyframes fa-spin {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(359deg);
    transform: rotate(359deg);
  }
}
.fa-rotate-90 {
  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
  -webkit-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}
.fa-rotate-180 {
  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
  -webkit-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  transform: rotate(180deg);
}
.fa-rotate-270 {
  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
  -webkit-transform: rotate(270deg);
  -ms-transform: rotate(270deg);
  transform: rotate(270deg);
}
.fa-flip-horizontal {
  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
  -webkit-transform: scale(-1, 1);
  -ms-transform: scale(-1, 1);
  transform: scale(-1, 1);
}
.fa-flip-vertical {
  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
  -webkit-transform: scale(1, -1);
  -ms-transform: scale(1, -1);
  transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
  filter: none;
}
.fa-stack {
  position: relative;
  display: inline-block;
  width: 2em;
  height: 2em;
  line-height: 2em;
  vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
  position: absolute;
  left: 0;
  width: 100%;
  text-align: center;
}
.fa-stack-1x {
  line-height: inherit;
}
.fa-stack-2x {
  font-size: 2em;
}
.fa-inverse {
  color: #ffffff;
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
   readers do not read off random characters that represent icons */
.fa-glass:before {
  content: "\f000";
}
.fa-music:before {
  content: "\f001";
}
.fa-search:before {
  content: "\f002";
}
.fa-envelope-o:before {
  content: "\f003";
}
.fa-heart:before {
  content: "\f004";
}
.fa-star:before {
  content: "\f005";
}
.fa-star-o:before {
  content: "\f006";
}
.fa-user:before {
  content: "\f007";
}
.fa-film:before {
  content: "\f008";
}
.fa-th-large:before {
  content: "\f009";
}
.fa-th:before {
  content: "\f00a";
}
.fa-th-list:before {
  content: "\f00b";
}
.fa-check:before {
  content: "\f00c";
}
.fa-remove:before,
.fa-close:before,
.fa-times:before {
  content: "\f00d";
}
.fa-search-plus:before {
  content: "\f00e";
}
.fa-search-minus:before {
  content: "\f010";
}
.fa-power-off:before {
  content: "\f011";
}
.fa-signal:before {
  content: "\f012";
}
.fa-gear:before,
.fa-cog:before {
  content: "\f013";
}
.fa-trash-o:before {
  content: "\f014";
}
.fa-home:before {
  content: "\f015";
}
.fa-file-o:before {
  content: "\f016";
}
.fa-clock-o:before {
  content: "\f017";
}
.fa-road:before {
  content: "\f018";
}
.fa-download:before {
  content: "\f019";
}
.fa-arrow-circle-o-down:before {
  content: "\f01a";
}
.fa-arrow-circle-o-up:before {
  content: "\f01b";
}
.fa-inbox:before {
  content: "\f01c";
}
.fa-play-circle-o:before {
  content: "\f01d";
}
.fa-rotate-right:before,
.fa-repeat:before {
  content: "\f01e";
}
.fa-refresh:before {
  content: "\f021";
}
.fa-list-alt:before {
  content: "\f022";
}
.fa-lock:before {
  content: "\f023";
}
.fa-flag:before {
  content: "\f024";
}
.fa-headphones:before {
  content: "\f025";
}
.fa-volume-off:before {
  content: "\f026";
}
.fa-volume-down:before {
  content: "\f027";
}
.fa-volume-up:before {
  content: "\f028";
}
.fa-qrcode:before {
  content: "\f029";
}
.fa-barcode:before {
  content: "\f02a";
}
.fa-tag:before {
  content: "\f02b";
}
.fa-tags:before {
  content: "\f02c";
}
.fa-book:before {
  content: "\f02d";
}
.fa-bookmark:before {
  content: "\f02e";
}
.fa-print:before {
  content: "\f02f";
}
.fa-camera:before {
  content: "\f030";
}
.fa-font:before {
  content: "\f031";
}
.fa-bold:before {
  content: "\f032";
}
.fa-italic:before {
  content: "\f033";
}
.fa-text-height:before {
  content: "\f034";
}
.fa-text-width:before {
  content: "\f035";
}
.fa-align-left:before {
  content: "\f036";
}
.fa-align-center:before {
  content: "\f037";
}
.fa-align-right:before {
  content: "\f038";
}
.fa-align-justify:before {
  content: "\f039";
}
.fa-list:before {
  content: "\f03a";
}
.fa-dedent:before,
.fa-outdent:before {
  content: "\f03b";
}
.fa-indent:before {
  content: "\f03c";
}
.fa-video-camera:before {
  content: "\f03d";
}
.fa-photo:before,
.fa-image:before,
.fa-picture-o:before {
  content: "\f03e";
}
.fa-pencil:before {
  content: "\f040";
}
.fa-map-marker:before {
  content: "\f041";
}
.fa-adjust:before {
  content: "\f042";
}
.fa-tint:before {
  content: "\f043";
}
.fa-edit:before,
.fa-pencil-square-o:before {
  content: "\f044";
}
.fa-share-square-o:before {
  content: "\f045";
}
.fa-check-square-o:before {
  content: "\f046";
}
.fa-arrows:before {
  content: "\f047";
}
.fa-step-backward:before {
  content: "\f048";
}
.fa-fast-backward:before {
  content: "\f049";
}
.fa-backward:before {
  content: "\f04a";
}
.fa-play:before {
  content: "\f04b";
}
.fa-pause:before {
  content: "\f04c";
}
.fa-stop:before {
  content: "\f04d";
}
.fa-forward:before {
  content: "\f04e";
}
.fa-fast-forward:before {
  content: "\f050";
}
.fa-step-forward:before {
  content: "\f051";
}
.fa-eject:before {
  content: "\f052";
}
.fa-chevron-left:before {
  content: "\f053";
}
.fa-chevron-right:before {
  content: "\f054";
}
.fa-plus-circle:before {
  content: "\f055";
}
.fa-minus-circle:before {
  content: "\f056";
}
.fa-times-circle:before {
  content: "\f057";
}
.fa-check-circle:before {
  content: "\f058";
}
.fa-question-circle:before {
  content: "\f059";
}
.fa-info-circle:before {
  content: "\f05a";
}
.fa-crosshairs:before {
  content: "\f05b";
}
.fa-times-circle-o:before {
  content: "\f05c";
}
.fa-check-circle-o:before {
  content: "\f05d";
}
.fa-ban:before {
  content: "\f05e";
}
.fa-arrow-left:before {
  content: "\f060";
}
.fa-arrow-right:before {
  content: "\f061";
}
.fa-arrow-up:before {
  content: "\f062";
}
.fa-arrow-down:before {
  content: "\f063";
}
.fa-mail-forward:before,
.fa-share:before {
  content: "\f064";
}
.fa-expand:before {
  content: "\f065";
}
.fa-compress:before {
  content: "\f066";
}
.fa-plus:before {
  content: "\f067";
}
.fa-minus:before {
  content: "\f068";
}
.fa-asterisk:before {
  content: "\f069";
}
.fa-exclamation-circle:before {
  content: "\f06a";
}
.fa-gift:before {
  content: "\f06b";
}
.fa-leaf:before {
  content: "\f06c";
}
.fa-fire:before {
  content: "\f06d";
}
.fa-eye:before {
  content: "\f06e";
}
.fa-eye-slash:before {
  content: "\f070";
}
.fa-warning:before,
.fa-exclamation-triangle:before {
  content: "\f071";
}
.fa-plane:before {
  content: "\f072";
}
.fa-calendar:before {
  content: "\f073";
}
.fa-random:before {
  content: "\f074";
}
.fa-comment:before {
  content: "\f075";
}
.fa-magnet:before {
  content: "\f076";
}
.fa-chevron-up:before {
  content: "\f077";
}
.fa-chevron-down:before {
  content: "\f078";
}
.fa-retweet:before {
  content: "\f079";
}
.fa-shopping-cart:before {
  content: "\f07a";
}
.fa-folder:before {
  content: "\f07b";
}
.fa-folder-open:before {
  content: "\f07c";
}
.fa-arrows-v:before {
  content: "\f07d";
}
.fa-arrows-h:before {
  content: "\f07e";
}
.fa-bar-chart-o:before,
.fa-bar-chart:before {
  content: "\f080";
}
.fa-twitter-square:before {
  content: "\f081";
}
.fa-facebook-square:before {
  content: "\f082";
}
.fa-camera-retro:before {
  content: "\f083";
}
.fa-key:before {
  content: "\f084";
}
.fa-gears:before,
.fa-cogs:before {
  content: "\f085";
}
.fa-comments:before {
  content: "\f086";
}
.fa-thumbs-o-up:before {
  content: "\f087";
}
.fa-thumbs-o-down:before {
  content: "\f088";
}
.fa-star-half:before {
  content: "\f089";
}
.fa-heart-o:before {
  content: "\f08a";
}
.fa-sign-out:before {
  content: "\f08b";
}
.fa-linkedin-square:before {
  content: "\f08c";
}
.fa-thumb-tack:before {
  content: "\f08d";
}
.fa-external-link:before {
  content: "\f08e";
}
.fa-sign-in:before {
  content: "\f090";
}
.fa-trophy:before {
  content: "\f091";
}
.fa-github-square:before {
  content: "\f092";
}
.fa-upload:before {
  content: "\f093";
}
.fa-lemon-o:before {
  content: "\f094";
}
.fa-phone:before {
  content: "\f095";
}
.fa-square-o:before {
  content: "\f096";
}
.fa-bookmark-o:before {
  content: "\f097";
}
.fa-phone-square:before {
  content: "\f098";
}
.fa-twitter:before {
  content: "\f099";
}
.fa-facebook-f:before,
.fa-facebook:before {
  content: "\f09a";
}
.fa-github:before {
  content: "\f09b";
}
.fa-unlock:before {
  content: "\f09c";
}
.fa-credit-card:before {
  content: "\f09d";
}
.fa-feed:before,
.fa-rss:before {
  content: "\f09e";
}
.fa-hdd-o:before {
  content: "\f0a0";
}
.fa-bullhorn:before {
  content: "\f0a1";
}
.fa-bell:before {
  content: "\f0f3";
}
.fa-certificate:before {
  content: "\f0a3";
}
.fa-hand-o-right:before {
  content: "\f0a4";
}
.fa-hand-o-left:before {
  content: "\f0a5";
}
.fa-hand-o-up:before {
  content: "\f0a6";
}
.fa-hand-o-down:before {
  content: "\f0a7";
}
.fa-arrow-circle-left:before {
  content: "\f0a8";
}
.fa-arrow-circle-right:before {
  content: "\f0a9";
}
.fa-arrow-circle-up:before {
  content: "\f0aa";
}
.fa-arrow-circle-down:before {
  content: "\f0ab";
}
.fa-globe:before {
  content: "\f0ac";
}
.fa-wrench:before {
  content: "\f0ad";
}
.fa-tasks:before {
  content: "\f0ae";
}
.fa-filter:before {
  content: "\f0b0";
}
.fa-briefcase:before {
  content: "\f0b1";
}
.fa-arrows-alt:before {
  content: "\f0b2";
}
.fa-group:before,
.fa-users:before {
  content: "\f0c0";
}
.fa-chain:before,
.fa-link:before {
  content: "\f0c1";
}
.fa-cloud:before {
  content: "\f0c2";
}
.fa-flask:before {
  content: "\f0c3";
}
.fa-cut:before,
.fa-scissors:before {
  content: "\f0c4";
}
.fa-copy:before,
.fa-files-o:before {
  content: "\f0c5";
}
.fa-paperclip:before {
  content: "\f0c6";
}
.fa-save:before,
.fa-floppy-o:before {
  content: "\f0c7";
}
.fa-square:before {
  content: "\f0c8";
}
.fa-navicon:before,
.fa-reorder:before,
.fa-bars:before {
  content: "\f0c9";
}
.fa-list-ul:before {
  content: "\f0ca";
}
.fa-list-ol:before {
  content: "\f0cb";
}
.fa-strikethrough:before {
  content: "\f0cc";
}
.fa-underline:before {
  content: "\f0cd";
}
.fa-table:before {
  content: "\f0ce";
}
.fa-magic:before {
  content: "\f0d0";
}
.fa-truck:before {
  content: "\f0d1";
}
.fa-pinterest:before {
  content: "\f0d2";
}
.fa-pinterest-square:before {
  content: "\f0d3";
}
.fa-google-plus-square:before {
  content: "\f0d4";
}
.fa-google-plus:before {
  content: "\f0d5";
}
.fa-money:before {
  content: "\f0d6";
}
.fa-caret-down:before {
  content: "\f0d7";
}
.fa-caret-up:before {
  content: "\f0d8";
}
.fa-caret-left:before {
  content: "\f0d9";
}
.fa-caret-right:before {
  content: "\f0da";
}
.fa-columns:before {
  content: "\f0db";
}
.fa-unsorted:before,
.fa-sort:before {
  content: "\f0dc";
}
.fa-sort-down:before,
.fa-sort-desc:before {
  content: "\f0dd";
}
.fa-sort-up:before,
.fa-sort-asc:before {
  content: "\f0de";
}
.fa-envelope:before {
  content: "\f0e0";
}
.fa-linkedin:before {
  content: "\f0e1";
}
.fa-rotate-left:before,
.fa-undo:before {
  content: "\f0e2";
}
.fa-legal:before,
.fa-gavel:before {
  content: "\f0e3";
}
.fa-dashboard:before,
.fa-tachometer:before {
  content: "\f0e4";
}
.fa-comment-o:before {
  content: "\f0e5";
}
.fa-comments-o:before {
  content: "\f0e6";
}
.fa-flash:before,
.fa-bolt:before {
  content: "\f0e7";
}
.fa-sitemap:before {
  content: "\f0e8";
}
.fa-umbrella:before {
  content: "\f0e9";
}
.fa-paste:before,
.fa-clipboard:before {
  content: "\f0ea";
}
.fa-lightbulb-o:before {
  content: "\f0eb";
}
.fa-exchange:before {
  content: "\f0ec";
}
.fa-cloud-download:before {
  content: "\f0ed";
}
.fa-cloud-upload:before {
  content: "\f0ee";
}
.fa-user-md:before {
  content: "\f0f0";
}
.fa-stethoscope:before {
  content: "\f0f1";
}
.fa-suitcase:before {
  content: "\f0f2";
}
.fa-bell-o:before {
  content: "\f0a2";
}
.fa-coffee:before {
  content: "\f0f4";
}
.fa-cutlery:before {
  content: "\f0f5";
}
.fa-file-text-o:before {
  content: "\f0f6";
}
.fa-building-o:before {
  content: "\f0f7";
}
.fa-hospital-o:before {
  content: "\f0f8";
}
.fa-ambulance:before {
  content: "\f0f9";
}
.fa-medkit:before {
  content: "\f0fa";
}
.fa-fighter-jet:before {
  content: "\f0fb";
}
.fa-beer:before {
  content: "\f0fc";
}
.fa-h-square:before {
  content: "\f0fd";
}
.fa-plus-square:before {
  content: "\f0fe";
}
.fa-angle-double-left:before {
  content: "\f100";
}
.fa-angle-double-right:before {
  content: "\f101";
}
.fa-angle-double-up:before {
  content: "\f102";
}
.fa-angle-double-down:before {
  content: "\f103";
}
.fa-angle-left:before {
  content: "\f104";
}
.fa-angle-right:before {
  content: "\f105";
}
.fa-angle-up:before {
  content: "\f106";
}
.fa-angle-down:before {
  content: "\f107";
}
.fa-desktop:before {
  content: "\f108";
}
.fa-laptop:before {
  content: "\f109";
}
.fa-tablet:before {
  content: "\f10a";
}
.fa-mobile-phone:before,
.fa-mobile:before {
  content: "\f10b";
}
.fa-circle-o:before {
  content: "\f10c";
}
.fa-quote-left:before {
  content: "\f10d";
}
.fa-quote-right:before {
  content: "\f10e";
}
.fa-spinner:before {
  content: "\f110";
}
.fa-circle:before {
  content: "\f111";
}
.fa-mail-reply:before,
.fa-reply:before {
  content: "\f112";
}
.fa-github-alt:before {
  content: "\f113";
}
.fa-folder-o:before {
  content: "\f114";
}
.fa-folder-open-o:before {
  content: "\f115";
}
.fa-smile-o:before {
  content: "\f118";
}
.fa-frown-o:before {
  content: "\f119";
}
.fa-meh-o:before {
  content: "\f11a";
}
.fa-gamepad:before {
  content: "\f11b";
}
.fa-keyboard-o:before {
  content: "\f11c";
}
.fa-flag-o:before {
  content: "\f11d";
}
.fa-flag-checkered:before {
  content: "\f11e";
}
.fa-terminal:before {
  content: "\f120";
}
.fa-code:before {
  content: "\f121";
}
.fa-mail-reply-all:before,
.fa-reply-all:before {
  content: "\f122";
}
.fa-star-half-empty:before,
.fa-star-half-full:before,
.fa-star-half-o:before {
  content: "\f123";
}
.fa-location-arrow:before {
  content: "\f124";
}
.fa-crop:before {
  content: "\f125";
}
.fa-code-fork:before {
  content: "\f126";
}
.fa-unlink:before,
.fa-chain-broken:before {
  content: "\f127";
}
.fa-question:before {
  content: "\f128";
}
.fa-info:before {
  content: "\f129";
}
.fa-exclamation:before {
  content: "\f12a";
}
.fa-superscript:before {
  content: "\f12b";
}
.fa-subscript:before {
  content: "\f12c";
}
.fa-eraser:before {
  content: "\f12d";
}
.fa-puzzle-piece:before {
  content: "\f12e";
}
.fa-microphone:before {
  content: "\f130";
}
.fa-microphone-slash:before {
  content: "\f131";
}
.fa-shield:before {
  content: "\f132";
}
.fa-calendar-o:before {
  content: "\f133";
}
.fa-fire-extinguisher:before {
  content: "\f134";
}
.fa-rocket:before {
  content: "\f135";
}
.fa-maxcdn:before {
  content: "\f136";
}
.fa-chevron-circle-left:before {
  content: "\f137";
}
.fa-chevron-circle-right:before {
  content: "\f138";
}
.fa-chevron-circle-up:before {
  content: "\f139";
}
.fa-chevron-circle-down:before {
  content: "\f13a";
}
.fa-html5:before {
  content: "\f13b";
}
.fa-css3:before {
  content: "\f13c";
}
.fa-anchor:before {
  content: "\f13d";
}
.fa-unlock-alt:before {
  content: "\f13e";
}
.fa-bullseye:before {
  content: "\f140";
}
.fa-ellipsis-h:before {
  content: "\f141";
}
.fa-ellipsis-v:before {
  content: "\f142";
}
.fa-rss-square:before {
  content: "\f143";
}
.fa-play-circle:before {
  content: "\f144";
}
.fa-ticket:before {
  content: "\f145";
}
.fa-minus-square:before {
  content: "\f146";
}
.fa-minus-square-o:before {
  content: "\f147";
}
.fa-level-up:before {
  content: "\f148";
}
.fa-level-down:before {
  content: "\f149";
}
.fa-check-square:before {
  content: "\f14a";
}
.fa-pencil-square:before {
  content: "\f14b";
}
.fa-external-link-square:before {
  content: "\f14c";
}
.fa-share-square:before {
  content: "\f14d";
}
.fa-compass:before {
  content: "\f14e";
}
.fa-toggle-down:before,
.fa-caret-square-o-down:before {
  content: "\f150";
}
.fa-toggle-up:before,
.fa-caret-square-o-up:before {
  content: "\f151";
}
.fa-toggle-right:before,
.fa-caret-square-o-right:before {
  content: "\f152";
}
.fa-euro:before,
.fa-eur:before {
  content: "\f153";
}
.fa-gbp:before {
  content: "\f154";
}
.fa-dollar:before,
.fa-usd:before {
  content: "\f155";
}
.fa-rupee:before,
.fa-inr:before {
  content: "\f156";
}
.fa-cny:before,
.fa-rmb:before,
.fa-yen:before,
.fa-jpy:before {
  content: "\f157";
}
.fa-ruble:before,
.fa-rouble:before,
.fa-rub:before {
  content: "\f158";
}
.fa-won:before,
.fa-krw:before {
  content: "\f159";
}
.fa-bitcoin:before,
.fa-btc:before {
  content: "\f15a";
}
.fa-file:before {
  content: "\f15b";
}
.fa-file-text:before {
  content: "\f15c";
}
.fa-sort-alpha-asc:before {
  content: "\f15d";
}
.fa-sort-alpha-desc:before {
  content: "\f15e";
}
.fa-sort-amount-asc:before {
  content: "\f160";
}
.fa-sort-amount-desc:before {
  content: "\f161";
}
.fa-sort-numeric-asc:before {
  content: "\f162";
}
.fa-sort-numeric-desc:before {
  content: "\f163";
}
.fa-thumbs-up:before {
  content: "\f164";
}
.fa-thumbs-down:before {
  content: "\f165";
}
.fa-youtube-square:before {
  content: "\f166";
}
.fa-youtube:before {
  content: "\f167";
}
.fa-xing:before {
  content: "\f168";
}
.fa-xing-square:before {
  content: "\f169";
}
.fa-youtube-play:before {
  content: "\f16a";
}
.fa-dropbox:before {
  content: "\f16b";
}
.fa-stack-overflow:before {
  content: "\f16c";
}
.fa-instagram:before {
  content: "\f16d";
}
.fa-flickr:before {
  content: "\f16e";
}
.fa-adn:before {
  content: "\f170";
}
.fa-bitbucket:before {
  content: "\f171";
}
.fa-bitbucket-square:before {
  content: "\f172";
}
.fa-tumblr:before {
  content: "\f173";
}
.fa-tumblr-square:before {
  content: "\f174";
}
.fa-long-arrow-down:before {
  content: "\f175";
}
.fa-long-arrow-up:before {
  content: "\f176";
}
.fa-long-arrow-left:before {
  content: "\f177";
}
.fa-long-arrow-right:before {
  content: "\f178";
}
.fa-apple:before {
  content: "\f179";
}
.fa-windows:before {
  content: "\f17a";
}
.fa-android:before {
  content: "\f17b";
}
.fa-linux:before {
  content: "\f17c";
}
.fa-dribbble:before {
  content: "\f17d";
}
.fa-skype:before {
  content: "\f17e";
}
.fa-foursquare:before {
  content: "\f180";
}
.fa-trello:before {
  content: "\f181";
}
.fa-female:before {
  content: "\f182";
}
.fa-male:before {
  content: "\f183";
}
.fa-gittip:before,
.fa-gratipay:before {
  content: "\f184";
}
.fa-sun-o:before {
  content: "\f185";
}
.fa-moon-o:before {
  content: "\f186";
}
.fa-archive:before {
  content: "\f187";
}
.fa-bug:before {
  content: "\f188";
}
.fa-vk:before {
  content: "\f189";
}
.fa-weibo:before {
  content: "\f18a";
}
.fa-renren:before {
  content: "\f18b";
}
.fa-pagelines:before {
  content: "\f18c";
}
.fa-stack-exchange:before {
  content: "\f18d";
}
.fa-arrow-circle-o-right:before {
  content: "\f18e";
}
.fa-arrow-circle-o-left:before {
  content: "\f190";
}
.fa-toggle-left:before,
.fa-caret-square-o-left:before {
  content: "\f191";
}
.fa-dot-circle-o:before {
  content: "\f192";
}
.fa-wheelchair:before {
  content: "\f193";
}
.fa-vimeo-square:before {
  content: "\f194";
}
.fa-turkish-lira:before,
.fa-try:before {
  content: "\f195";
}
.fa-plus-square-o:before {
  content: "\f196";
}
.fa-space-shuttle:before {
  content: "\f197";
}
.fa-slack:before {
  content: "\f198";
}
.fa-envelope-square:before {
  content: "\f199";
}
.fa-wordpress:before {
  content: "\f19a";
}
.fa-openid:before {
  content: "\f19b";
}
.fa-institution:before,
.fa-bank:before,
.fa-university:before {
  content: "\f19c";
}
.fa-mortar-board:before,
.fa-graduation-cap:before {
  content: "\f19d";
}
.fa-yahoo:before {
  content: "\f19e";
}
.fa-google:before {
  content: "\f1a0";
}
.fa-reddit:before {
  content: "\f1a1";
}
.fa-reddit-square:before {
  content: "\f1a2";
}
.fa-stumbleupon-circle:before {
  content: "\f1a3";
}
.fa-stumbleupon:before {
  content: "\f1a4";
}
.fa-delicious:before {
  content: "\f1a5";
}
.fa-digg:before {
  content: "\f1a6";
}
.fa-pied-piper-pp:before {
  content: "\f1a7";
}
.fa-pied-piper-alt:before {
  content: "\f1a8";
}
.fa-drupal:before {
  content: "\f1a9";
}
.fa-joomla:before {
  content: "\f1aa";
}
.fa-language:before {
  content: "\f1ab";
}
.fa-fax:before {
  content: "\f1ac";
}
.fa-building:before {
  content: "\f1ad";
}
.fa-child:before {
  content: "\f1ae";
}
.fa-paw:before {
  content: "\f1b0";
}
.fa-spoon:before {
  content: "\f1b1";
}
.fa-cube:before {
  content: "\f1b2";
}
.fa-cubes:before {
  content: "\f1b3";
}
.fa-behance:before {
  content: "\f1b4";
}
.fa-behance-square:before {
  content: "\f1b5";
}
.fa-steam:before {
  content: "\f1b6";
}
.fa-steam-square:before {
  content: "\f1b7";
}
.fa-recycle:before {
  content: "\f1b8";
}
.fa-automobile:before,
.fa-car:before {
  content: "\f1b9";
}
.fa-cab:before,
.fa-taxi:before {
  content: "\f1ba";
}
.fa-tree:before {
  content: "\f1bb";
}
.fa-spotify:before {
  content: "\f1bc";
}
.fa-deviantart:before {
  content: "\f1bd";
}
.fa-soundcloud:before {
  content: "\f1be";
}
.fa-database:before {
  content: "\f1c0";
}
.fa-file-pdf-o:before {
  content: "\f1c1";
}
.fa-file-word-o:before {
  content: "\f1c2";
}
.fa-file-excel-o:before {
  content: "\f1c3";
}
.fa-file-powerpoint-o:before {
  content: "\f1c4";
}
.fa-file-photo-o:before,
.fa-file-picture-o:before,
.fa-file-image-o:before {
  content: "\f1c5";
}
.fa-file-zip-o:before,
.fa-file-archive-o:before {
  content: "\f1c6";
}
.fa-file-sound-o:before,
.fa-file-audio-o:before {
  content: "\f1c7";
}
.fa-file-movie-o:before,
.fa-file-video-o:before {
  content: "\f1c8";
}
.fa-file-code-o:before {
  content: "\f1c9";
}
.fa-vine:before {
  content: "\f1ca";
}
.fa-codepen:before {
  content: "\f1cb";
}
.fa-jsfiddle:before {
  content: "\f1cc";
}
.fa-life-bouy:before,
.fa-life-buoy:before,
.fa-life-saver:before,
.fa-support:before,
.fa-life-ring:before {
  content: "\f1cd";
}
.fa-circle-o-notch:before {
  content: "\f1ce";
}
.fa-ra:before,
.fa-resistance:before,
.fa-rebel:before {
  content: "\f1d0";
}
.fa-ge:before,
.fa-empire:before {
  content: "\f1d1";
}
.fa-git-square:before {
  content: "\f1d2";
}
.fa-git:before {
  content: "\f1d3";
}
.fa-y-combinator-square:before,
.fa-yc-square:before,
.fa-hacker-news:before {
  content: "\f1d4";
}
.fa-tencent-weibo:before {
  content: "\f1d5";
}
.fa-qq:before {
  content: "\f1d6";
}
.fa-wechat:before,
.fa-weixin:before {
  content: "\f1d7";
}
.fa-send:before,
.fa-paper-plane:before {
  content: "\f1d8";
}
.fa-send-o:before,
.fa-paper-plane-o:before {
  content: "\f1d9";
}
.fa-history:before {
  content: "\f1da";
}
.fa-circle-thin:before {
  content: "\f1db";
}
.fa-header:before {
  content: "\f1dc";
}
.fa-paragraph:before {
  content: "\f1dd";
}
.fa-sliders:before {
  content: "\f1de";
}
.fa-share-alt:before {
  content: "\f1e0";
}
.fa-share-alt-square:before {
  content: "\f1e1";
}
.fa-bomb:before {
  content: "\f1e2";
}
.fa-soccer-ball-o:before,
.fa-futbol-o:before {
  content: "\f1e3";
}
.fa-tty:before {
  content: "\f1e4";
}
.fa-binoculars:before {
  content: "\f1e5";
}
.fa-plug:before {
  content: "\f1e6";
}
.fa-slideshare:before {
  content: "\f1e7";
}
.fa-twitch:before {
  content: "\f1e8";
}
.fa-yelp:before {
  content: "\f1e9";
}
.fa-newspaper-o:before {
  content: "\f1ea";
}
.fa-wifi:before {
  content: "\f1eb";
}
.fa-calculator:before {
  content: "\f1ec";
}
.fa-paypal:before {
  content: "\f1ed";
}
.fa-google-wallet:before {
  content: "\f1ee";
}
.fa-cc-visa:before {
  content: "\f1f0";
}
.fa-cc-mastercard:before {
  content: "\f1f1";
}
.fa-cc-discover:before {
  content: "\f1f2";
}
.fa-cc-amex:before {
  content: "\f1f3";
}
.fa-cc-paypal:before {
  content: "\f1f4";
}
.fa-cc-stripe:before {
  content: "\f1f5";
}
.fa-bell-slash:before {
  content: "\f1f6";
}
.fa-bell-slash-o:before {
  content: "\f1f7";
}
.fa-trash:before {
  content: "\f1f8";
}
.fa-copyright:before {
  content: "\f1f9";
}
.fa-at:before {
  content: "\f1fa";
}
.fa-eyedropper:before {
  content: "\f1fb";
}
.fa-paint-brush:before {
  content: "\f1fc";
}
.fa-birthday-cake:before {
  content: "\f1fd";
}
.fa-area-chart:before {
  content: "\f1fe";
}
.fa-pie-chart:before {
  content: "\f200";
}
.fa-line-chart:before {
  content: "\f201";
}
.fa-lastfm:before {
  content: "\f202";
}
.fa-lastfm-square:before {
  content: "\f203";
}
.fa-toggle-off:before {
  content: "\f204";
}
.fa-toggle-on:before {
  content: "\f205";
}
.fa-bicycle:before {
  content: "\f206";
}
.fa-bus:before {
  content: "\f207";
}
.fa-ioxhost:before {
  content: "\f208";
}
.fa-angellist:before {
  content: "\f209";
}
.fa-cc:before {
  content: "\f20a";
}
.fa-shekel:before,
.fa-sheqel:before,
.fa-ils:before {
  content: "\f20b";
}
.fa-meanpath:before {
  content: "\f20c";
}
.fa-buysellads:before {
  content: "\f20d";
}
.fa-connectdevelop:before {
  content: "\f20e";
}
.fa-dashcube:before {
  content: "\f210";
}
.fa-forumbee:before {
  content: "\f211";
}
.fa-leanpub:before {
  content: "\f212";
}
.fa-sellsy:before {
  content: "\f213";
}
.fa-shirtsinbulk:before {
  content: "\f214";
}
.fa-simplybuilt:before {
  content: "\f215";
}
.fa-skyatlas:before {
  content: "\f216";
}
.fa-cart-plus:before {
  content: "\f217";
}
.fa-cart-arrow-down:before {
  content: "\f218";
}
.fa-diamond:before {
  content: "\f219";
}
.fa-ship:before {
  content: "\f21a";
}
.fa-user-secret:before {
  content: "\f21b";
}
.fa-motorcycle:before {
  content: "\f21c";
}
.fa-street-view:before {
  content: "\f21d";
}
.fa-heartbeat:before {
  content: "\f21e";
}
.fa-venus:before {
  content: "\f221";
}
.fa-mars:before {
  content: "\f222";
}
.fa-mercury:before {
  content: "\f223";
}
.fa-intersex:before,
.fa-transgender:before {
  content: "\f224";
}
.fa-transgender-alt:before {
  content: "\f225";
}
.fa-venus-double:before {
  content: "\f226";
}
.fa-mars-double:before {
  content: "\f227";
}
.fa-venus-mars:before {
  content: "\f228";
}
.fa-mars-stroke:before {
  content: "\f229";
}
.fa-mars-stroke-v:before {
  content: "\f22a";
}
.fa-mars-stroke-h:before {
  content: "\f22b";
}
.fa-neuter:before {
  content: "\f22c";
}
.fa-genderless:before {
  content: "\f22d";
}
.fa-facebook-official:before {
  content: "\f230";
}
.fa-pinterest-p:before {
  content: "\f231";
}
.fa-whatsapp:before {
  content: "\f232";
}
.fa-server:before {
  content: "\f233";
}
.fa-user-plus:before {
  content: "\f234";
}
.fa-user-times:before {
  content: "\f235";
}
.fa-hotel:before,
.fa-bed:before {
  content: "\f236";
}
.fa-viacoin:before {
  content: "\f237";
}
.fa-train:before {
  content: "\f238";
}
.fa-subway:before {
  content: "\f239";
}
.fa-medium:before {
  content: "\f23a";
}
.fa-yc:before,
.fa-y-combinator:before {
  content: "\f23b";
}
.fa-optin-monster:before {
  content: "\f23c";
}
.fa-opencart:before {
  content: "\f23d";
}
.fa-expeditedssl:before {
  content: "\f23e";
}
.fa-battery-4:before,
.fa-battery:before,
.fa-battery-full:before {
  content: "\f240";
}
.fa-battery-3:before,
.fa-battery-three-quarters:before {
  content: "\f241";
}
.fa-battery-2:before,
.fa-battery-half:before {
  content: "\f242";
}
.fa-battery-1:before,
.fa-battery-quarter:before {
  content: "\f243";
}
.fa-battery-0:before,
.fa-battery-empty:before {
  content: "\f244";
}
.fa-mouse-pointer:before {
  content: "\f245";
}
.fa-i-cursor:before {
  content: "\f246";
}
.fa-object-group:before {
  content: "\f247";
}
.fa-object-ungroup:before {
  content: "\f248";
}
.fa-sticky-note:before {
  content: "\f249";
}
.fa-sticky-note-o:before {
  content: "\f24a";
}
.fa-cc-jcb:before {
  content: "\f24b";
}
.fa-cc-diners-club:before {
  content: "\f24c";
}
.fa-clone:before {
  content: "\f24d";
}
.fa-balance-scale:before {
  content: "\f24e";
}
.fa-hourglass-o:before {
  content: "\f250";
}
.fa-hourglass-1:before,
.fa-hourglass-start:before {
  content: "\f251";
}
.fa-hourglass-2:before,
.fa-hourglass-half:before {
  content: "\f252";
}
.fa-hourglass-3:before,
.fa-hourglass-end:before {
  content: "\f253";
}
.fa-hourglass:before {
  content: "\f254";
}
.fa-hand-grab-o:before,
.fa-hand-rock-o:before {
  content: "\f255";
}
.fa-hand-stop-o:before,
.fa-hand-paper-o:before {
  content: "\f256";
}
.fa-hand-scissors-o:before {
  content: "\f257";
}
.fa-hand-lizard-o:before {
  content: "\f258";
}
.fa-hand-spock-o:before {
  content: "\f259";
}
.fa-hand-pointer-o:before {
  content: "\f25a";
}
.fa-hand-peace-o:before {
  content: "\f25b";
}
.fa-trademark:before {
  content: "\f25c";
}
.fa-registered:before {
  content: "\f25d";
}
.fa-creative-commons:before {
  content: "\f25e";
}
.fa-gg:before {
  content: "\f260";
}
.fa-gg-circle:before {
  content: "\f261";
}
.fa-tripadvisor:before {
  content: "\f262";
}
.fa-odnoklassniki:before {
  content: "\f263";
}
.fa-odnoklassniki-square:before {
  content: "\f264";
}
.fa-get-pocket:before {
  content: "\f265";
}
.fa-wikipedia-w:before {
  content: "\f266";
}
.fa-safari:before {
  content: "\f267";
}
.fa-chrome:before {
  content: "\f268";
}
.fa-firefox:before {
  content: "\f269";
}
.fa-opera:before {
  content: "\f26a";
}
.fa-internet-explorer:before {
  content: "\f26b";
}
.fa-tv:before,
.fa-television:before {
  content: "\f26c";
}
.fa-contao:before {
  content: "\f26d";
}
.fa-500px:before {
  content: "\f26e";
}
.fa-amazon:before {
  content: "\f270";
}
.fa-calendar-plus-o:before {
  content: "\f271";
}
.fa-calendar-minus-o:before {
  content: "\f272";
}
.fa-calendar-times-o:before {
  content: "\f273";
}
.fa-calendar-check-o:before {
  content: "\f274";
}
.fa-industry:before {
  content: "\f275";
}
.fa-map-pin:before {
  content: "\f276";
}
.fa-map-signs:before {
  content: "\f277";
}
.fa-map-o:before {
  content: "\f278";
}
.fa-map:before {
  content: "\f279";
}
.fa-commenting:before {
  content: "\f27a";
}
.fa-commenting-o:before {
  content: "\f27b";
}
.fa-houzz:before {
  content: "\f27c";
}
.fa-vimeo:before {
  content: "\f27d";
}
.fa-black-tie:before {
  content: "\f27e";
}
.fa-fonticons:before {
  content: "\f280";
}
.fa-reddit-alien:before {
  content: "\f281";
}
.fa-edge:before {
  content: "\f282";
}
.fa-credit-card-alt:before {
  content: "\f283";
}
.fa-codiepie:before {
  content: "\f284";
}
.fa-modx:before {
  content: "\f285";
}
.fa-fort-awesome:before {
  content: "\f286";
}
.fa-usb:before {
  content: "\f287";
}
.fa-product-hunt:before {
  content: "\f288";
}
.fa-mixcloud:before {
  content: "\f289";
}
.fa-scribd:before {
  content: "\f28a";
}
.fa-pause-circle:before {
  content: "\f28b";
}
.fa-pause-circle-o:before {
  content: "\f28c";
}
.fa-stop-circle:before {
  content: "\f28d";
}
.fa-stop-circle-o:before {
  content: "\f28e";
}
.fa-shopping-bag:before {
  content: "\f290";
}
.fa-shopping-basket:before {
  content: "\f291";
}
.fa-hashtag:before {
  content: "\f292";
}
.fa-bluetooth:before {
  content: "\f293";
}
.fa-bluetooth-b:before {
  content: "\f294";
}
.fa-percent:before {
  content: "\f295";
}
.fa-gitlab:before {
  content: "\f296";
}
.fa-wpbeginner:before {
  content: "\f297";
}
.fa-wpforms:before {
  content: "\f298";
}
.fa-envira:before {
  content: "\f299";
}
.fa-universal-access:before {
  content: "\f29a";
}
.fa-wheelchair-alt:before {
  content: "\f29b";
}
.fa-question-circle-o:before {
  content: "\f29c";
}
.fa-blind:before {
  content: "\f29d";
}
.fa-audio-description:before {
  content: "\f29e";
}
.fa-volume-control-phone:before {
  content: "\f2a0";
}
.fa-braille:before {
  content: "\f2a1";
}
.fa-assistive-listening-systems:before {
  content: "\f2a2";
}
.fa-asl-interpreting:before,
.fa-american-sign-language-interpreting:before {
  content: "\f2a3";
}
.fa-deafness:before,
.fa-hard-of-hearing:before,
.fa-deaf:before {
  content: "\f2a4";
}
.fa-glide:before {
  content: "\f2a5";
}
.fa-glide-g:before {
  content: "\f2a6";
}
.fa-signing:before,
.fa-sign-language:before {
  content: "\f2a7";
}
.fa-low-vision:before {
  content: "\f2a8";
}
.fa-viadeo:before {
  content: "\f2a9";
}
.fa-viadeo-square:before {
  content: "\f2aa";
}
.fa-snapchat:before {
  content: "\f2ab";
}
.fa-snapchat-ghost:before {
  content: "\f2ac";
}
.fa-snapchat-square:before {
  content: "\f2ad";
}
.fa-pied-piper:before {
  content: "\f2ae";
}
.fa-first-order:before {
  content: "\f2b0";
}
.fa-yoast:before {
  content: "\f2b1";
}
.fa-themeisle:before {
  content: "\f2b2";
}
.fa-google-plus-circle:before,
.fa-google-plus-official:before {
  content: "\f2b3";
}
.fa-fa:before,
.fa-font-awesome:before {
  content: "\f2b4";
}
.fa-handshake-o:before {
  content: "\f2b5";
}
.fa-envelope-open:before {
  content: "\f2b6";
}
.fa-envelope-open-o:before {
  content: "\f2b7";
}
.fa-linode:before {
  content: "\f2b8";
}
.fa-address-book:before {
  content: "\f2b9";
}
.fa-address-book-o:before {
  content: "\f2ba";
}
.fa-vcard:before,
.fa-address-card:before {
  content: "\f2bb";
}
.fa-vcard-o:before,
.fa-address-card-o:before {
  content: "\f2bc";
}
.fa-user-circle:before {
  content: "\f2bd";
}
.fa-user-circle-o:before {
  content: "\f2be";
}
.fa-user-o:before {
  content: "\f2c0";
}
.fa-id-badge:before {
  content: "\f2c1";
}
.fa-drivers-license:before,
.fa-id-card:before {
  content: "\f2c2";
}
.fa-drivers-license-o:before,
.fa-id-card-o:before {
  content: "\f2c3";
}
.fa-quora:before {
  content: "\f2c4";
}
.fa-free-code-camp:before {
  content: "\f2c5";
}
.fa-telegram:before {
  content: "\f2c6";
}
.fa-thermometer-4:before,
.fa-thermometer:before,
.fa-thermometer-full:before {
  content: "\f2c7";
}
.fa-thermometer-3:before,
.fa-thermometer-three-quarters:before {
  content: "\f2c8";
}
.fa-thermometer-2:before,
.fa-thermometer-half:before {
  content: "\f2c9";
}
.fa-thermometer-1:before,
.fa-thermometer-quarter:before {
  content: "\f2ca";
}
.fa-thermometer-0:before,
.fa-thermometer-empty:before {
  content: "\f2cb";
}
.fa-shower:before {
  content: "\f2cc";
}
.fa-bathtub:before,
.fa-s15:before,
.fa-bath:before {
  content: "\f2cd";
}
.fa-podcast:before {
  content: "\f2ce";
}
.fa-window-maximize:before {
  content: "\f2d0";
}
.fa-window-minimize:before {
  content: "\f2d1";
}
.fa-window-restore:before {
  content: "\f2d2";
}
.fa-times-rectangle:before,
.fa-window-close:before {
  content: "\f2d3";
}
.fa-times-rectangle-o:before,
.fa-window-close-o:before {
  content: "\f2d4";
}
.fa-bandcamp:before {
  content: "\f2d5";
}
.fa-grav:before {
  content: "\f2d6";
}
.fa-etsy:before {
  content: "\f2d7";
}
.fa-imdb:before {
  content: "\f2d8";
}
.fa-ravelry:before {
  content: "\f2d9";
}
.fa-eercast:before {
  content: "\f2da";
}
.fa-microchip:before {
  content: "\f2db";
}
.fa-snowflake-o:before {
  content: "\f2dc";
}
.fa-superpowers:before {
  content: "\f2dd";
}
.fa-wpexplorer:before {
  content: "\f2de";
}
.fa-meetup:before {
  content: "\f2e0";
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
.sr-only-focusable:active,
.sr-only-focusable:focus {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
}




.leaflet-image-layer,.leaflet-layer,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane,.leaflet-pane>canvas,.leaflet-pane>svg,.leaflet-tile,.leaflet-tile-container,.leaflet-zoom-box{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden;-webkit-tap-highlight-color:transparent;background:#ddd;outline:0;font:12px/1.5 "Helvetica Neue",Arial,Helvetica,sans-serif}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-overlay-pane svg,.leaflet-tooltip{-moz-user-select:none}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-overlay-pane svg,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer{max-width:none!important;max-height:none!important}.leaflet-container.leaflet-touch-zoom{-ms-touch-action:pan-x pan-y;touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{-ms-touch-action:pinch-zoom;touch-action:none;touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{-ms-touch-action:none;touch-action:none}.leaflet-container a{-webkit-tap-highlight-color:rgba(51,181,229,.4);color:#0078A8}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;-moz-box-sizing:border-box;box-sizing:border-box;z-index:800}.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:visiblePainted;pointer-events:auto;float:left;clear:both}.leaflet-bottom,.leaflet-top{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-right .leaflet-control{float:right;margin-right:10px}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-fade-anim .leaflet-tile{will-change:opacity}.leaflet-fade-anim .leaflet-popup{opacity:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0}.leaflet-zoom-anim .leaflet-zoom-animated{will-change:transform;-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,.25,1);-o-transition:-o-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-pan-anim .leaflet-tile,.leaflet-zoom-anim .leaflet-tile{-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:-webkit-grab;cursor:-moz-grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-control,.leaflet-popup-pane{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing}.leaflet-image-layer,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-image-layer.leaflet-interactive,.leaflet-marker-icon.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive{pointer-events:visiblePainted;pointer-events:auto}.leaflet-container a.leaflet-active{outline:orange solid 2px}.leaflet-zoom-box{border:2px dotted #38f;background:rgba(255,255,255,.5)}.leaflet-bar{box-shadow:0 1px 5px rgba(0,0,0,.65);border-radius:4px}.leaflet-bar a,.leaflet-bar a:hover{background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;display:block;text-align:center;text-decoration:none;color:#000}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50% 50%;background-repeat:no-repeat;display:block}.leaflet-bar a:hover{background-color:#f4f4f4}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:none}.leaflet-bar a.leaflet-disabled{cursor:default;background-color:#f4f4f4;color:#bbb}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.leaflet-touch .leaflet-bar a:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.leaflet-control-zoom-in,.leaflet-control-zoom-out{font:700 18px 'Lucida Console',Monaco,monospace;text-indent:1px}.leaflet-touch .leaflet-control-zoom-in,.leaflet-touch .leaflet-control-zoom-out{font-size:22px}.leaflet-control-layers{box-shadow:0 1px 5px rgba(0,0,0,.4);background:#fff;border-radius:5px}.leaflet-control-layers-toggle{background-image:url(images/layers.png);width:36px;height:36px}.leaflet-retina .leaflet-control-layers-toggle{background-image:url(images/layers-2x.png);background-size:26px 26px}.leaflet-touch .leaflet-control-layers-toggle{width:44px;height:44px}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{padding:6px 10px 6px 6px;color:#333;background:#fff}.leaflet-control-layers-scrollbar{overflow-y:scroll;overflow-x:hidden;padding-right:5px}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{display:block}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;margin:5px -10px 5px -6px}.leaflet-default-icon-path{background-image:url(images/marker-icon.png)}.leaflet-container .leaflet-control-attribution{background:#fff;background:rgba(255,255,255,.7);margin:0}.leaflet-control-attribution,.leaflet-control-scale-line{padding:0 5px;color:#333}.leaflet-control-attribution a{text-decoration:none}.leaflet-control-attribution a:hover{text-decoration:underline}.leaflet-container .leaflet-control-attribution,.leaflet-container .leaflet-control-scale{font-size:11px}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line{border:2px solid #777;border-top:none;line-height:1.1;padding:2px 5px 1px;font-size:11px;white-space:nowrap;overflow:hidden;-moz-box-sizing:border-box;box-sizing:border-box;background:#fff;background:rgba(255,255,255,.5)}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #777;border-bottom:none;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-touch .leaflet-bar,.leaflet-touch .leaflet-control-attribution,.leaflet-touch .leaflet-control-layers{box-shadow:none}.leaflet-touch .leaflet-bar,.leaflet-touch .leaflet-control-layers{border:2px solid rgba(0,0,0,.2);background-clip:padding-box}.leaflet-popup{position:absolute;text-align:center;margin-bottom:20px}.leaflet-popup-content-wrapper{padding:1px;text-align:left;border-radius:12px}.leaflet-popup-content{margin:13px 19px;line-height:1.4}.leaflet-popup-content p{margin:18px 0}.leaflet-popup-tip-container{width:40px;height:20px;position:absolute;left:50%;margin-left:-20px;overflow:hidden;pointer-events:none}.leaflet-popup-tip{width:17px;height:17px;padding:1px;margin:-10px auto 0;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:#fff;color:#333;box-shadow:0 3px 14px rgba(0,0,0,.4)}.leaflet-container a.leaflet-popup-close-button{position:absolute;top:0;right:0;padding:4px 4px 0 0;border:none;text-align:center;width:18px;height:14px;font:16px/14px Tahoma,Verdana,sans-serif;color:#c3c3c3;text-decoration:none;font-weight:700;background:0 0}.leaflet-container a.leaflet-popup-close-button:hover{color:#999}.leaflet-popup-scrolled{overflow:auto;border-bottom:1px solid #ddd;border-top:1px solid #ddd}.leaflet-oldie .leaflet-popup-content-wrapper{zoom:1}.leaflet-oldie .leaflet-popup-tip{width:24px;margin:0 auto;-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";filter:progid:DXImageTransform.Microsoft.Matrix(M11=.70710678, M12=.70710678, M21=-.70710678, M22=.70710678)}.leaflet-oldie .leaflet-popup-tip-container{margin-top:-1px}.leaflet-oldie .leaflet-control-layers,.leaflet-oldie .leaflet-control-zoom,.leaflet-oldie .leaflet-popup-content-wrapper,.leaflet-oldie .leaflet-popup-tip{border:1px solid #999}.leaflet-div-icon{background:#fff;border:1px solid #666}.leaflet-tooltip{position:absolute;padding:6px;background-color:#fff;border:1px solid #fff;border-radius:3px;color:#222;white-space:nowrap;-webkit-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;box-shadow:0 1px 3px rgba(0,0,0,.4)}.leaflet-tooltip.leaflet-clickable{cursor:pointer;pointer-events:auto}.leaflet-tooltip-bottom:before,.leaflet-tooltip-left:before,.leaflet-tooltip-right:before,.leaflet-tooltip-top:before{position:absolute;pointer-events:none;border:6px solid transparent;background:0 0;content:""}.leaflet-tooltip-bottom{margin-top:6px}.leaflet-tooltip-top{margin-top:-6px}.leaflet-tooltip-bottom:before,.leaflet-tooltip-top:before{left:50%;margin-left:-6px}.leaflet-tooltip-top:before{bottom:0;margin-bottom:-12px;border-top-color:#fff}.leaflet-tooltip-bottom:before{top:0;margin-top:-12px;margin-left:-6px;border-bottom-color:#fff}.leaflet-tooltip-left{margin-left:-6px}.leaflet-tooltip-right{margin-left:6px}.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{top:50%;margin-top:-6px}.leaflet-tooltip-left:before{right:0;margin-right:-12px;border-left-color:#fff}.leaflet-tooltip-right:before{left:0;margin-left:-12px;border-right-color:#fff}
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
	-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
	-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
	-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
	transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}

.leaflet-cluster-spider-leg {
	/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
	-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
	-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
	-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
	transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
}



body {
    margin: 0
}

.sList>div {
    user-select: none
}

#loader span, #onlineCam, #settingsPage, #setttitle, #text, .divicon, .marker-cluster, .sList .favoriteName, .videoButton {
    text-align: center
}

#logo, #onlineCam, #preImage, .favoriteBack {
    bottom: 0;
    top: 0
}

@font-face {
    font-family: 'Material Icons';
    font-style: normal;
    font-weight: 400;
    src: url(/assets/fonts/Material.woff2) format('woff2')
}

.material-icons {
    font-family: 'Material Icons';
    font-weight: 400;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased
}

@font-face {
    font-family: Roboto;
    font-weight: 100;
    src: url(/assets/fonts/Roboto-Light.ttf)
}

@font-face {
    font-family: Roboto;
    font-weight: 300;
    src: url(/assets/fonts/Roboto-Regular.ttf)
}

button, hr, input {
    overflow: visible
}

progress, sub, sup {
    vertical-align: baseline
}

#wrapper {
    position: fixed
}

#buttonPanel, #fullness, #logo, #onlineCam, #preImage, #wrapper, .favoriteBack {
    right: 0;
    left: 0
}

#nav {
    z-index: 999
}

#content, #conttbl {
    width: 100%
}

legend {
    display: table;
    padding: 0
}

details {
    display: block
}

.favoriteBack, .sList .favoriteName {
    user-select: none;
    /*opacity: 0;*/
    transition: all .2s
}

.sList>div, sub, sup {
    position: relative
}

[hidden], template {
    display: none
}

.panelstyle, .switch {
    -moz-appearance: none
}

html {
    line-height: 1.15;
    -webkit-text-size-adjust: 100%
}

h1 {
    font-size: 2em;
    margin: .67em 0
}

hr {
    box-sizing: content-box;
    height: 0
}

#search, .panelLink, .panelLink td, .panelstyle, .sList, .switch, .switch::before, .typename td, [type=checkbox], [type=radio], legend {
    box-sizing: border-box
}

code, kbd, pre, samp {
    font-family: monospace, monospace;
    font-size: 1em
}

a {
    background-color: transparent
}

abbr[title] {
    border-bottom: none;
    text-decoration: underline;
    text-decoration: underline dotted
}

.button, .leaflet-control-attribution a {
    text-decoration: none
}

b, strong {
    font-weight: bolder
}

small {
    font-size: 80%
}

sub, sup {
    font-size: 75%;
    line-height: 0
}

sub {
    bottom: -.25em
}

sup {
    top: -.5em
}

img {
    border-style: none
}

button, input, optgroup, select, textarea {
    font-family: inherit;
    font-size: 100%;
    line-height: 1.15;
    margin: 0
}

button, select {
    text-transform: none
}

[type=button], [type=reset], [type=submit], button {
    -webkit-appearance: button
}

[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner {
    border-style: none;
    padding: 0
}

[type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring {
    outline: ButtonText dotted 1px
}

fieldset {
    padding: .35em .75em .625em
}

legend {
    color: inherit;
    max-width: 100%;
    white-space: normal
}

textarea {
    overflow: auto
}

[type=checkbox], [type=radio] {
    padding: 0
}

[type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button {
    height: auto
}

#content, #conttbl, .sList {
    overflow: auto;
    height: 100%
}

.sList {
    overflow: auto;
    height: calc(100%);
}

[type=search] {
    -webkit-appearance: textfield;
    outline-offset: -2px
}

[type=search]::-webkit-search-decoration {
    -webkit-appearance: none
}

::-webkit-file-upload-button {
    -webkit-appearance: button;
    font: inherit
}

.vis-item .vis-delete-rtl:after, .vis-item .vis-delete:after, body, div.vis-tooltip {
    font-family: Roboto, sans-serif
}

.vis-item.vis-background.positive {
  background: rgba(255, 0, 93, 1);
  /* Fullness (negative) and motion (positive) are both background-type
     items in the same vis-timeline group. The motion timestamp comes
     from the DB with second-precision, the fullness timestamp comes
     from file metadata with ms-precision — so motion's start is
     usually a few hundred ms earlier than its matching fullness.
     vis-timeline appends items to the DOM in roughly start-time order,
     and the later-drawn child wins z-stacking. Without an explicit
     z-index that left blue painted on top of red in the diff-update
     refresh path. Force the order at the CSS layer so it doesn't
     matter what DOM order vis chooses. */
  z-index: 2;
}
.vis-item.vis-background.negative {
  z-index: 1;
}

summary {
    display: list-item
}

body {
    color: #373a3c;
    font-size: 15px;
}

#buttonPanel div, .sList>div {
    display: inline-block
}

#buttonPanel div, #panellist div, .switch {
    vertical-align: top
}

.sList {
    display: flex;
    flex-flow: row wrap;
    align-content: flex-start;
    justify-content: center;
    align-items: stretch;
    padding: 0 0 1px 1px;
    font-size: 0;
    width: 100%;
}

/* Переключатель размеров плиток (#viewtype), распорки .grid-clearfix и подпись
   поверх кадра (.favoriteName / .favoriteBack) ушли вместе со старой плиткой
   360×270 — их место заняли карточки из ui-cards.css. */

#exportTail, .leaflet-overlay-pane {
    display: none
}

#logo {
    opacity: 1
}

#loader, #logo, #onlineCam {
    position: fixed
}

#onlineCam video, #onlineCam video.scale {
    max-width: 100%;
    max-height: 100%;
    position: absolute
}
/*
*/
#logo {
    transition: all 1s;
    z-index: 99999;
    background: 0 0
}

#logo.hidden {
    transition: all 0.1s linear;
    opacity: 0
}

#mapid {
    height: 100%
}

.marker-cluster {
    border: 4px solid rgba(58, 153, 217, .7);
    color: #333;
    padding: 0;
    font-size: 13px;
    background: #fff;
    border-radius: 100px
}

.marker-cluster-large {
    line-height: 50px;
    width: 50px!important;
    height: 50px!important;
}

.marker-cluster-medium {
    width: 40px!important;
    height: 40px!important;
    line-height: 40px
}

.marker-cluster-small {
    width: 30px!important;
    height: 30px!important;
    line-height: 30px
}

.divicon {
    background-image: url(/assets/img/marker.svg);
    width: 50px!important;
    height: 50px!important;
    margin: -45px 0 0 -25px!important;
    font-size: 12px;
    line-height: 41px;
    color: #000;
    background-position: center;
    cursor: pointer
}

#onlineCam {
    z-index: 1000
}

#onlineCam #fon {
    background-size: cover;
    filter: blur(5px);
    position: absolute;
    top: -5px;
    bottom: -5px;
    left: -5px;
    right: -5px
}

#loader span {
    width: 300px;
    margin: auto;
    position: relative;
    display: block;
    left: -115px
}

#loader {
    content: " ";
    top: calc(50% - 32px);
    left: calc(50% - 32px);
    width: 63px;
    height: 63px;
    background: url(/assets/img/6.svg) center no-repeat;
    box-shadow: 0 0 2px 0 rgba(85, 136, 204, .4);
    background-size: 64px;
    color: #fff;
    line-height: 170px;
    font-weight: 100;
    font-size: 27px;
    border-radius: 100px
}

#onlineCam video.scale {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%
}

#onlineCam video.stretch {
    background-size: 100% 100%!important;
    object-fit: fill;
    position: absolute;
    max-width: auto;
    max-height: auto;
    width: 100%;
    height: 100%
}

.cover {
    object-fit: cover;
    background-size: cover!important;
}

#preImage {
    position: fixed;
    background-size: 100% 100%
}

#fullness {
    transition: all .2s;
    background-color: rgba(157, 157, 157, .59);
    width: 100%;
    height: 84px;
    position: fixed;
    bottom: -84px;
    z-index: 1001
}

#fullness.active {
    bottom: -8px
}

#buttonPanel {
    font-size: 0;
    position: absolute;
    transform: translateY(-100%);
    padding: 1vmin
}

.videoButton {
    box-shadow: 0 0 9px 0px #797979;
    -moz-user-select: none;
    -khtml-user-select: none;
    user-select: none;
    cursor: pointer;
    background: #fff;
    border-radius: 100%;
    height: 50px;
    width: 50px;
    max-width: calc((100vw - 90px) / 8);
    max-height: calc((100vw - 90px) / 8);
    margin: 5px;
    font-size: 22px;
    line-height: 50px;
    color: #2e81b7;
    position: relative;
}

.archiveEnd, .archiveStart {
    background: rgba(255, 76, 76, .73)
}

.videoButton i {
    font-size: 23px;
    position: absolute;
    top: 50%;
    width: 100%;
    left: 0;
    transform: translateY(-50%);
}

#closeCam {
    text-shadow: 0 0 2px black
}

.unactive i {
    color: #969696
}

#closeCam, #closeCamEx, #settingFrameClose {
    cursor: pointer;
    position: fixed!important;
    top: 15px;
    right: 15px;
    font-size: 20px;
    color: #fff;
    z-index: 1000
}

#closeCam i, #closeCamEx i, #settingFrameClose i {
    font-size: 48px
}

#exportTail {
    z-index: 101;
    top: -5px;
    left: -5px;
    right: -5px;
    bottom: -5px;
    position: fixed
}

.archiveEnd::before, .archiveStart::before {
    content: 'f';
    width: 0;
    height: 0;
    position: absolute;
    top: -28px
}

#exportTail.active {
    display: block
}

#exportList {
    display: none!important
}

#exportList.active {
    display: inline-block!important
}

#archiveList div, #exportList div {
    transform: scale(0);
    transition: none
}

#archiveList.active div, #exportList.active div {
    transform: scale(1);
    transition: all .2s;
    line-height: 165%;
}

#camSearcher, #csettings #settingsbody, #settingFrame #settingsPage, .btnAddToPanel {
    transform: translateX(-50%) translateY(-50%)
}

#modal, #toasts, .selfToast {
    transform: translateX(-50%)
}

#archiveList {
    display: none!important
}

#archiveList.active {
    display: inline-block!important
}

/* SVG icons (prev/next block, prev/next frame) inside .videoButton.
   Previously used <img src=*.svg>; that doesn't inherit currentColor and
   rendered the icons in their raw SVG fill (black). mask-image lets us
   paint the SVG silhouette with the button's `color` so the new buttons
   match the surrounding Material font icons in any cctv theme. */
.videoButton .archIcon {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    transform: translate(-50%, -50%);
    background-color: currentColor;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-size: 24px 24px;
            mask-size: 24px 24px;
    pointer-events: none;
}
.archIcon.icPrevBlock { -webkit-mask-image: url('../images/icons/archive/prev_block.svg'); mask-image: url('../images/icons/archive/prev_block.svg'); }
.archIcon.icPrevFrame { -webkit-mask-image: url('../images/icons/archive/prev_frame.svg'); mask-image: url('../images/icons/archive/prev_frame.svg'); }
.archIcon.icNextFrame { -webkit-mask-image: url('../images/icons/archive/next_frame.svg'); mask-image: url('../images/icons/archive/next_frame.svg'); }
.archIcon.icNextBlock { -webkit-mask-image: url('../images/icons/archive/next_block.svg'); mask-image: url('../images/icons/archive/next_block.svg'); }

/* Speed selector popup. Anchored to btnUpSpeed; positioned via JS so it
   floats above the speed button. Hidden by default; .open shows it.
   Children are stacked vertically (one speed per row).
   NB: all rules are scoped `#buttonPanel ...` because the global rule
   `#buttonPanel div { display: inline-block; }` (ID specificity) was
   defeating our class-level `.speedSelector { display: none }` — that
   was leaving an empty white 60x8 strip next to the round buttons in
   live mode (the "артефакт" the user reported). Same story for the
   .speedOpt rows showing up in a row instead of a column. */
#buttonPanel .speedSelector {
    display: none;
    position: absolute;
    z-index: 12;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 2px 12px rgba(0,0,0,.25);
    padding: 4px 0;
    min-width: 60px;
    font-size: 14px;
    user-select: none;
    flex-direction: column;
}
#buttonPanel .speedSelector.open {
    display: flex;
}
#buttonPanel .speedSelector .speedOpt {
    display: block;
    padding: 6px 14px;
    cursor: pointer;
    color: #2e81b7;
    text-align: center;
    line-height: 1.2;
    white-space: nowrap;
}
#buttonPanel .speedSelector .speedOpt:hover {
    background: #f0f7fc;
}
#buttonPanel .speedSelector .speedOpt.current {
    background: #2e81b7;
    color: #fff;
}

#normalList {
    display: none!important
}

#normalList.active {
    display: inline-block!important
}

.archiveStart::before {
    font-size: 0;
    right: 0;
    border: 15px solid transparent;
    border-right-color: rgba(255, 76, 76, .73);
    z-index: 99
}

.archiveStart {
    z-index: 100
}

.archiveEnd::before {
    font-size: 0;
    left: 0;
    border: 15px solid transparent;
    border-left-color: rgba(255, 76, 76, .73);
    z-index: 99
}

.switch::after, .switch::before {
    content: '1';
    font-size: 0;
    display: block
}

.archiveEnd>div, .archiveStart>div {
    z-index: 19999;
    position: absolute!important;
    top: -28px!important;
    left: -10px;
    height: 107px!important
}

#backreal, .archiveEnd {
    z-index: 100
}

#progressBar {
    background-size: 1rem 1rem;
    background-color: #3a99d9;
    border-radius: 5px;
    padding: 10px;
    width: 0%;
    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);
    -webkit-animation: progress-bar-stripes 2s linear infinite;
    -o-animation: progress-bar-stripes 2s linear infinite;
    animation: progress-bar-stripes 2s linear infinite;
    transition: all .2s
}

#text {
    font-weight: 300;
    padding: 10px;
    color: #fff
}

#progress {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 80vw;
    transform: translateY(-50%) translateX(-50%)
}

.exportinterval {
    background: rgba(255, 128, 128, .8)!important;
    height: 33%!important;
    bottom: 33%!important
}

#exportFon {
    position: fixed;
    background-size: cover;
    top: -5px;
    left: -5px;
    right: -5px;
    bottom: -5px;
    filter: blur(5px)
}

#closeCamEx {
    z-index: 1001
}

.switch {
    border: 0;
    position: relative;
    top: -2px;
    outline: 0;
    width: 1000px;
    -webkit-appearance: unset;
    cursor: pointer
}

.switch:checked {
    background: 0 0
}

#settingsPage .switch {
    top: 7px
}

.switch::before {
    position: absolute;
    top: 5px;
    left: 0;
    border-radius: 20px;
    width: 42px;
    height: 12px;
    background: #fff;
    border: 1px solid #bbb;
    background: #bbb;
}

.switch::after {
    transition: all .2s;
    position: absolute;
    border-radius: 13px;
    top: 0px;
    left: 0px;
    width: 22px;
    height: 22px;
    background: #999;
}

.switch:checked::after {
    left: 20px;
    background: #3a99d9
}

.switch:checked::before {
    border-color: #73bef1;
    background: #73bef1;
}

#setttitle {
    position: fixed;
    top: -160px;
    display: block;
    width: 100%;
    font-size: 50px;
    font-weight: 600;
    color: #fff
}

#searchRes>div, .inpblock label, .poless, .setpole {
    font-weight: 100
}

#settingFrame #settingsPage {
    color: #fff;
    position: absolute;
    top: 50%;
    text-align: left;
    left: 50%;
    display: inline-block
}

#settingsPage i {
    margin: 0 10px;
    vertical-align: bottom
}

.poless i {
    color: #999
}

.setpole {
    margin: 5px 0
}

#settingsPage {
    box-shadow: 0 0 10px 0 rgba(0, 0, 0, .1);
    max-width: 550px;
    margin: 30px auto;
    padding: 25px 15px;
    border-radius: 5px
}

#settingsPage input {
    float: right;
    width: 45px
}

#settingsPage>div {
    min-height: 30px;
    margin: auto;
    text-align: left
}

#addpanelpage, #camlist>div, .btnAddToPanel, .panelLink, .panelname, .typename {
    text-align: center
}

#settingsPage>.height {
    line-height: 40px;
    color: #373a3c;
    font-weight: 100
}

.height i {
    display: none
}

#settingsPage>.height i {
    display: inline;
    line-height: 40px;
    color: #999
}

hr {
    border: 0;
    border-bottom: 1px solid #eee
}

.settitle {
    font-size: 25px;
    margin-bottom: 15px!important;
    display: block
}

#serchers {
    position: relative
}

#serchers i {
    position: absolute;
    left: 30px;
    top: 28px;
    font-size: 25px;
    color: #bbb
}

#search {
    width: 100%;
    display: block;
    padding: 10px 40px;
    font-size: 16px;
    outline: 0;
    border-radius: 3px;
    border: 1px solid #e6e6e6
}

::-webkit-input-placeholder {
    color: #aaa
}

::-moz-placeholder {
    color: #aaa
}

:-moz-placeholder {
    color: #aaa
}

:-ms-input-placeholder {
    color: #aaa
}

#searchRes {
    padding: 20px
}

#searchRes>div {
    transition: all .2s;
    display: block;
    padding: 10px 5px;
    user-select: none;
    cursor: pointer
}

#searchRes>div:hover {
    background: #f0f0f0
}

iframe {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh
}

#panellist td {
    background-size: cover
}

.panelLink {
    transition: all .2s;
    cursor: pointer;
    background: #fefefe;
    border: 1px solid #d6d6d6;
    margin: 5px;
    border-radius: 3px;
    height: 200px;
    width: 200px;
    display: inline-block;
    padding: 20px;
    position: relative
}

.panelLink:hover {
    background: #f6f6f6
}

.panelname {
    position: absolute;
    bottom: 4px;
    left: 0;
    right: 0;
    color: #777;
    height: 18px;
    padding: 0 5px;
    display: block;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden
}

#camlist, .typename {
    top: 0;
    left: 0;
    right: 0;
    bottom: 0
}

.panelLink table, .typename table {
    height: calc(100% - 20px);
    width: 100%;
    margin: auto
}

.panelLink td, .typename td {
    border: 1px solid #cacaca;
    border-radius: 2px;
    /*width: 50px;
    min-width: 50px;*/
    height: 50px
}

.panelLink .spec22 td, .panelLink .spec32 td {
  height: 75px
}

.panelLink .spec12 td {
  height: 75px
}
.panelLink .spec25 td {
    height: 29px
}

#camlist {
    position: absolute;
    font-size: 0;
    width: 100%;
    height: 100%;
    padding: 0 0 0 1px
}

#camlist>div {
    overflow: hidden;
    position: relative;
    float: left;
    margin: 1px 1px 0 0;
    box-sizing: content-box;
    height: calc(100% / 3 - 1px);
    width: calc(100% / 3 - 1px)
}

#camlist>div.prime {
    height: calc(99.99% / 3 * 2 - 1px);
    width: calc(100% / 3 * 2 - 1px)
}

#camlist>div.half {
    height: calc(100% / 2 - 1px);
    width: calc(100% / 2 - 1px)
}

#camlist>div.s32 {
    height: calc(100% / 2 - 1px);
    width: calc(100% / 3 - 1px)
}

#camlist>div.s23 {
    height: calc(100% / 3 - 1px);
    width: calc(100% / 2 - 1px)
}

#camlist > div.s12{	
	height: calc(100% / 2 - 1px);
	width: calc(100% / 1 - 1px);
}

#camlist > div.s25{	
	height: calc(100% / 5 - 1px);
	width: calc(100% / 2 - 1px);
}

#camlist>div>video {
    object-fit: cover;
    width: 100%;
    height: 100%;
    overflow: hidden
}

#addpanelpage {
    padding: 4% 80px
}

#addpanelpage :not(.inpblock)>label {
    margin: 10px;
    z-index: 20;
    cursor: pointer;
    vertical-align: middle;
    text-align: center;
    position: relative;
    width: 150px;
    height: 150px;
    display: inline-block;
    border: 1px solid #cacaca;
    border-radius: 2px;
    overflow: hidden
}

#addpanelpage :not(.inpblock) label input {
    outline: 0;
    transition: all .2s;
    z-index: 10;
    position: relative;
    cursor: pointer;
    -webkit-appearance: none;
    width: 100%;
    height: 100%;
    background: #fff
}

#addpanelpage :not(.inpblock) label input:checked {
    background: #e7f2fa
}

.typename {
    display: table-cell;
    position: absolute;
    vertical-align: middle;
    z-index: 20
}

#context, #mCalendar {
    z-index: 119;
    outline: 0
}

#camSearcher.active, #panelname {
    display: block
}

#btnUpSpeed i {
    font-style: normal;
}

.typename table {
    padding: 2%;
    width: 100%;
    margin: auto;
    height: 100%
}

.typename td {
    box-sizing: border-box;
    border: 1px solid #cacaca;
    border-radius: 2px;
    width: 45px;
    min-width: 45px;
    height: 45px
}

#filter, #panelname {
    width: 100%;
    box-sizing: border-box;
    outline: 0
}

.typename .spec22 td, .typename .spec32 td {
    height: 69px
}

.typename .spec25 td {
    height: 26px
}

.inpblock {
    margin: 10px;
    position: relative
}

.inpblock label {
    user-select: none;
    position: absolute;
    line-height: 40px;
    left: 10px;
    color: #aaa
}

#addpanelpage div:not(.inpblock)>label {
    transition: all .1s;
    box-shadow: 0 0 0 0 rgba(255, 0, 0, .57)
}

#addpanelpage.error div:not(.inpblock)>label {
    box-shadow: 0 0 12px 1px rgba(255, 0, 0, .57)
}

#panelname {
    color: #555;
    transition: all .1s;
    padding: 10px 40px 10px 105px;
    font-size: 16px;
    border-radius: 3px;
    border: 1px solid #cacaca;
    box-shadow: 0 0 0 0 rgba(255, 0, 0, .57)
}

#panelname.error {
    box-shadow: 0 0 12px 1px rgba(255, 0, 0, .57)
}

#btnAddNewPanel {
    margin: auto
}

#camSearcher {
    box-shadow: 0 0 10px 0 rgba(150, 150, 150, .7);
    display: none;
    padding: 20px;
    background: #fff;
    border-radius: 5px;
    position: fixed;
    width: 500px;
    height: 700px;
    max-width: 100%;
    max-height: 90vh;
    box-sizing: border-box;
    top: calc(50% - 30px);
    left: 50%;
    z-index: 102;
    overflow: hidden
}

#camSearcher span {
    display: block;
    font-weight: 700;
    font-size: 25px
}

#closePanelCamSearch {
    position: absolute;
    right: 10px;
    top: 10px;
    cursor: pointer;
    font-size: 20px
}

#filter {
    margin-top: 30px;
    border: 0;
    border-bottom: 2px solid #ddd;
    padding: 10px 0;
    font-size: 20px
}

#filtResult {
    overflow: auto;
    position: absolute;
    top: 140px;
    left: 20px;
    right: 20px;
    bottom: 64px
}

#searchRes>div:not(.noper),#filtResult>div {
    user-select: none;
    padding: 10px;
    padding-right: 33px;
    border-bottom: 1px solid #eee;
    position: relative;
    color: #2e81b7;
}


#searchRes>div span,#filtResult>div span{
    display: inline; 
    font-weight:100;
    font-size:0.7em;
    color: rgb(51, 51, 51);
}

#filtResult>div:hover {
    background: #eee;
    cursor: pointer
}

.btnAddToPanel {
    transition: all .8s;
    height: 50px;
    color: #777;
    position: absolute;
    top: 50%;
    left: 50%;
    border-radius: 100px;
    font-size: 14px
}

.btnAddToPanel i {
    font-size: 50px
}

.btnAddToPanel:hover {
    border-color: #999;
    color: #58d;
    cursor: pointer
}

#addPanelButton {
    color: #777;
    font-size: 50px;
    line-height: 160px
}

#addPanelButton:hover, #addPanelButton:hover span {
    color: #219cec
}

#addPanelButton span {
    font-size: 15px;
    line-height: 18px
}

/* Здесь была плитка 360×270 с подписью поверх кадра и её правки под низкое
   окно. Размер карточки теперь считает сетка (ui-cards.css), а фиксированная
   ширина оставляла на широком окне пустые поля по краям. */

#modal, .button {
    border-radius: 5px
}

#mCalendar.active {
    display: block
}

#mCalendar {
    display: none;
    border-radius: .5em;
    font-size: 12px;
    position: absolute;
    top: 50%;
    left: 50%;
    box-shadow: 0 0 5px 5px rgba(89, 89, 89, .36);
    background: rgba(255, 255, 255, .85);
    padding: 10px
}

@media screen and (max-height:600px) {
    #mCalendar {
        font-size: 2.2vh
    }
}

#m_days>div, #m_daysw>div {
    height: 3em;
    font-size: 1em;
    display: inline-block;
    text-align: center;
    color: #000;
    user-select: none
}

#m_daysw {
    border-bottom: 1px dotted #ccc
}

#m_daysw>div {
    width: 3em;
    line-height: 40px
}

#m_days {
    width: 21em
}

#m_days>div {
    width: 3em;
    line-height: 3em
}

#m_days>div:not(.unactive):hover {
    background: radial-gradient(#2e81b79c, #2e81b74f, #2e81b700);
    cursor: pointer
}

#m_days .unactive {
    color: #a0a0a0
}

#month_right {
    text-align: right
}

#m_cont {
    display: table;
    width: 100%;
    font-size: 1.3em
}

#m_cont>div {
    display: table-cell;
    cursor: pointer;
    text-align: center;
    padding: 10px;
    max-height: 20px;
    line-height: 1
}

#context {
    font-size: 16px;
    transition: all .2s;
    height: 0;
    overflow: hidden;
    border-radius: 3px;
    position: fixed;
    background: #fff
}

#modal, #modal-buttons div, .button {
    transition: all .2s
}

#context.active {
    height: unset;
    box-shadow: 2px 3px 3px 2px rgba(0, 0, 0, .6)
}

#context>div {
    cursor: pointer;
    padding: 10px 30px;
    border-top: 1px solid #eee;
    font-weight: 100
}

#context>div:first-child {
    border-top: 0
}

#context>div:hover {
    background: #f9f9f9
}

#context>div.redcontext {
    background: #d88
}

#context>div.title {
    cursor: default;
    background: #eee
}

#context>div.redcontext:hover {
    background: #d78484
}

#csettings {
    color: #333;
    font-weight: 100;
    display: none
}

#csettings.active {
    display: block
}

#csettings .csettingsback {
    position: fixed;
    top: 0;
    background: rgba(100, 100, 100, .9);
    left: 0;
    right: 0;
    bottom: 0;
    display: none
}

#csettings #settingsbody {
    position: fixed;
    top: 50%;
    width: 100%;
    max-width: 700px;
    left: 50%
}

#csettings.active .csettingsback {
    display: block
}

#csettings #settingslist {
    margin: auto;
    width: 300px;
    color: #fff;
    font-size: 20px;
    padding: 10px;
    border-radius: 5px
}

#csettings #settingslist>div {
    line-height: 46px
}

#csettings .switchSettings {
    float: right;
    margin-top: 13px;
    width: 45px
}

#csettings>#settingFrameClose {
    margin: auto;
    position: relative;
    z-index: 200
}

#modal, #toasts {
    position: fixed;
    left: 50%
}

#modal.active {
    top: 100px;
    opacity: 1
}

#modal {
    box-shadow: 0 0 10px 0 #999;
    border: 1px solid #ccc;
    width: 300px;
    top: -1000px;
    opacity: 0;
    background: #fff
}

#modal-text {
    border-bottom: 1px solid #ddd;
    min-height: 50px;
    padding: 20px
}

#modal-buttons {
    display: table;
    width: 100%
}

#modal-buttons div {
    user-select: none;
    border-right: 1px solid #ddd;
    cursor: pointer;
    display: table-cell;
    width: 1%;
    text-align: center;
    line-height: 50px
}

#modal-buttons div:hover {
    background: #f9f9f9
}

.button {
    cursor: pointer;
    display: inline-block;
    padding: 10px 60px;
    border: 1px solid #3a99d9;
    color: #3a99d9;
    font-weight: 400;
    width: 80%;
    box-sizing: border-box;
}

#toasts>div, .selfToast {
    padding: 5px 10px;
    max-width: 100%;
    white-space: nowrap
}

.button:hover {
    background: rgba(58, 153, 217, .11)
}

#toasts {
    z-index: 116;
    top: 0;
    max-width: 100%
}

#toasts>div {
    margin: 5px;
    background: rgba(150, 150, 150, .7);
    border-radius: 5px;
    color: #fff
}

#toasts>div a{
  color: #fff;
}

#toasts>div.error {
    background: rgba(255, 100, 100, .7)
}

#toasts>div.info, .selfToast {
    background: rgba(150, 150, 150, .7)
}

#toasts>div.success {
    background: rgba(100, 205, 100, .7)
}

.vis .overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10
}

.vis-active {
    box-shadow: 0 0 10px #86d5f8
}

.vis [class*=span] {
    min-height: 0;
    width: auto
}

div.vis-configuration {
    position: relative;
    display: block;
    float: left;
    font-size: 12px
}

div.vis-configuration-wrapper {
    display: block;
    width: 700px
}

div.vis-configuration-wrapper::after {
    clear: both;
    content: "";
    display: block
}

div.vis-configuration.vis-config-option-container {
    display: block;
    width: 495px;
    background-color: #fff;
    border: 2px solid #f7f8fa;
    border-radius: 4px;
    margin-top: 20px;
    left: 10px;
    padding-left: 5px
}

div.vis-configuration.vis-config-button {
    display: block;
    width: 495px;
    height: 25px;
    line-height: 25px;
    background-color: #f7f8fa;
    border: 2px solid #ceced0;
    border-radius: 4px;
    margin-top: 20px;
    left: 10px;
    padding-left: 5px;
    cursor: pointer;
    margin-bottom: 30px
}

div.vis-configuration.vis-config-button.hover {
    background-color: #4588e6;
    border: 2px solid #214373;
    color: #fff
}

div.vis-configuration.vis-config-item {
    display: block;
    float: left;
    width: 495px;
    height: 25px;
    line-height: 25px
}

div.vis-configuration.vis-config-item.vis-config-s2 {
    left: 10px;
    background-color: #f7f8fa;
    padding-left: 5px;
    border-radius: 3px
}

div.vis-configuration.vis-config-item.vis-config-s3 {
    left: 20px;
    background-color: #e4e9f0;
    padding-left: 5px;
    border-radius: 3px
}

div.vis-configuration.vis-config-item.vis-config-s4 {
    left: 30px;
    background-color: #cfd8e6;
    padding-left: 5px;
    border-radius: 3px
}

div.vis-configuration.vis-config-header {
    font-size: 18px;
    font-weight: 700
}

div.vis-configuration.vis-config-label {
    width: 120px;
    height: 25px;
    line-height: 25px
}

div.vis-configuration.vis-config-label.vis-config-s3 {
    width: 110px
}

div.vis-configuration.vis-config-label.vis-config-s4 {
    width: 100px
}

div.vis-configuration.vis-config-colorBlock {
    top: 1px;
    width: 30px;
    height: 19px;
    border: 1px solid #444;
    border-radius: 2px;
    padding: 0;
    margin: 0;
    cursor: pointer
}

input.vis-configuration.vis-config-checkbox {
    left: -5px
}

input.vis-configuration.vis-config-rangeinput {
    position: relative;
    top: -5px;
    width: 60px;
    padding: 1px;
    margin: 0;
    pointer-events: none
}

input.vis-configuration.vis-config-range {
    -webkit-appearance: none;
    border: 0 solid #fff;
    background-color: rgba(0, 0, 0, 0);
    width: 300px;
    height: 20px
}

input.vis-configuration.vis-config-range::-webkit-slider-runnable-track {
    width: 300px;
    height: 5px;
    background: #dedede;
    background: -moz-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #dedede), color-stop(99%, #c8c8c8));
    background: -webkit-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -o-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -ms-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: linear-gradient(to bottom, #dedede 0, #c8c8c8 99%);
    border: 1px solid #999;
    box-shadow: #aaa 0 0 3px 0;
    border-radius: 3px
}

input.vis-configuration.vis-config-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    border: 1px solid #14334b;
    height: 17px;
    width: 17px;
    border-radius: 50%;
    background: #3876c2;
    background: -moz-linear-gradient(top, #3876c2 0, #385380 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #3876c2), color-stop(100%, #385380));
    background: -webkit-linear-gradient(top, #3876c2 0, #385380 100%);
    background: -o-linear-gradient(top, #3876c2 0, #385380 100%);
    background: -ms-linear-gradient(top, #3876c2 0, #385380 100%);
    background: linear-gradient(to bottom, #3876c2 0, #385380 100%);
    box-shadow: #111927 0 0 1px 0;
    margin-top: -7px
}

input.vis-configuration.vis-config-range:focus {
    outline: 0
}

input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track {
    background: #9d9d9d;
    background: -moz-linear-gradient(top, #9d9d9d 0, #c8c8c8 99%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #9d9d9d), color-stop(99%, #c8c8c8));
    background: -webkit-linear-gradient(top, #9d9d9d 0, #c8c8c8 99%);
    background: -o-linear-gradient(top, #9d9d9d 0, #c8c8c8 99%);
    background: -ms-linear-gradient(top, #9d9d9d 0, #c8c8c8 99%);
    background: linear-gradient(to bottom, #9d9d9d 0, #c8c8c8 99%)
}

input.vis-configuration.vis-config-range::-moz-range-track {
    width: 300px;
    height: 10px;
    background: #dedede;
    background: -moz-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #dedede), color-stop(99%, #c8c8c8));
    background: -webkit-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -o-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: -ms-linear-gradient(top, #dedede 0, #c8c8c8 99%);
    background: linear-gradient(to bottom, #dedede 0, #c8c8c8 99%);
    border: 1px solid #999;
    box-shadow: #aaa 0 0 3px 0;
    border-radius: 3px
}

input.vis-configuration.vis-config-range::-moz-range-thumb {
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: #385380
}

input.vis-configuration.vis-config-range:-moz-focusring {
    outline: #fff solid 1px;
    outline-offset: -1px
}

input.vis-configuration.vis-config-range::-ms-track {
    width: 300px;
    height: 5px;
    background: 0 0;
    border-color: transparent;
    border-width: 6px 0;
    color: transparent
}

input.vis-configuration.vis-config-range::-ms-fill-lower {
    background: #777;
    border-radius: 10px
}

input.vis-configuration.vis-config-range::-ms-fill-upper {
    background: #ddd;
    border-radius: 10px
}

input.vis-configuration.vis-config-range::-ms-thumb {
    border: none;
    height: 16px;
    width: 16px;
    border-radius: 50%;
    background: #385380
}

input.vis-configuration.vis-config-range:focus::-ms-fill-lower {
    background: #888
}

input.vis-configuration.vis-config-range:focus::-ms-fill-upper {
    background: #ccc
}

.vis-configuration-popup {
    position: absolute;
    background: rgba(57, 76, 89, .85);
    border: 2px solid #f2faff;
    line-height: 30px;
    height: 30px;
    width: 150px;
    text-align: center;
    color: #fff;
    font-size: 14px;
    border-radius: 4px;
    -webkit-transition: opacity .3s ease-in-out;
    -moz-transition: opacity .3s ease-in-out;
    transition: opacity .3s ease-in-out
}

.vis-configuration-popup:after, .vis-configuration-popup:before {
    left: 100%;
    top: 50%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none
}

.vis-configuration-popup:after {
    border-color: rgba(136, 183, 213, 0);
    border-left-color: rgba(57, 76, 89, .85);
    border-width: 8px;
    margin-top: -8px
}

.vis-configuration-popup:before {
    border-color: rgba(194, 225, 245, 0);
    border-left-color: #f2faff;
    border-width: 12px;
    margin-top: -12px
}

div.vis-tooltip {
    position: absolute;
    visibility: hidden;
    padding: 5px;
    white-space: nowrap;
    font-size: 14px;
    color: #000;
    background-color: #f5f4ed;
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    border: 1px solid #808074;
    box-shadow: 3px 3px 10px rgba(0, 0, 0, .2);
    pointer-events: none;
    z-index: 5
}

div.vis-color-picker {
    position: absolute;
    top: 0;
    left: 30px;
    margin-top: -140px;
    margin-left: 30px;
    width: 310px;
    height: 444px;
    z-index: 1;
    padding: 10px;
    border-radius: 15px;
    background-color: #fff;
    display: none;
    box-shadow: rgba(0, 0, 0, .5) 0 0 10px 0
}

div.vis-color-picker div.vis-arrow {
    position: absolute;
    top: 147px;
    left: 5px
}

div.vis-color-picker div.vis-arrow::after, div.vis-color-picker div.vis-arrow::before {
    right: 100%;
    top: 50%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none
}

div.vis-color-picker div.vis-arrow:after {
    border-color: rgba(255, 255, 255, 0);
    border-right-color: #fff;
    border-width: 30px;
    margin-top: -30px
}

div.vis-color-picker div.vis-color {
    position: absolute;
    width: 289px;
    height: 289px;
    cursor: pointer
}

div.vis-color-picker div.vis-brightness {
    position: absolute;
    top: 313px
}

div.vis-color-picker div.vis-opacity {
    position: absolute;
    top: 350px
}

div.vis-color-picker div.vis-selector {
    position: absolute;
    top: 137px;
    left: 137px;
    width: 15px;
    height: 15px;
    border-radius: 15px;
    border: 1px solid #fff;
    background: #4c4c4c;
    background: -moz-linear-gradient(top, #4c4c4c 0, #595959 12%, #666 25%, #474747 39%, #2c2c2c 50%, #000 51%, #111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #4c4c4c), color-stop(12%, #595959), color-stop(25%, #666), color-stop(39%, #474747), color-stop(50%, #2c2c2c), color-stop(51%, #000), color-stop(60%, #111), color-stop(76%, #2b2b2b), color-stop(91%, #1c1c1c), color-stop(100%, #131313));
    background: -webkit-linear-gradient(top, #4c4c4c 0, #595959 12%, #666 25%, #474747 39%, #2c2c2c 50%, #000 51%, #111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%);
    background: -o-linear-gradient(top, #4c4c4c 0, #595959 12%, #666 25%, #474747 39%, #2c2c2c 50%, #000 51%, #111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%);
    background: -ms-linear-gradient(top, #4c4c4c 0, #595959 12%, #666 25%, #474747 39%, #2c2c2c 50%, #000 51%, #111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%);
    background: linear-gradient(to bottom, #4c4c4c 0, #595959 12%, #666 25%, #474747 39%, #2c2c2c 50%, #000 51%, #111 60%, #2b2b2b 76%, #1c1c1c 91%, #131313 100%)
}

div.vis-color-picker div.vis-initial-color, div.vis-color-picker div.vis-new-color {
    width: 140px;
    height: 20px;
    top: 380px;
    font-size: 10px;
    color: rgba(0, 0, 0, .4);
    line-height: 20px;
    position: absolute;
    vertical-align: middle
}

div.vis-color-picker div.vis-new-color {
    border: 1px solid rgba(0, 0, 0, .1);
    border-radius: 5px;
    left: 159px;
    text-align: right;
    padding-right: 2px
}

div.vis-color-picker div.vis-initial-color {
    border: 1px solid rgba(0, 0, 0, .1);
    border-radius: 5px;
    left: 10px;
    text-align: left;
    padding-left: 2px
}

div.vis-color-picker div.vis-label {
    position: absolute;
    width: 300px;
    left: 10px
}

div.vis-color-picker div.vis-label.vis-brightness {
    top: 300px
}

div.vis-color-picker div.vis-label.vis-opacity {
    top: 338px
}

div.vis-color-picker div.vis-button {
    position: absolute;
    width: 68px;
    height: 25px;
    border-radius: 10px;
    vertical-align: middle;
    text-align: center;
    line-height: 25px;
    top: 410px;
    border: 2px solid #d9d9d9;
    background-color: #f7f7f7;
    cursor: pointer
}

div.vis-color-picker div.vis-button.vis-cancel {
    left: 5px
}

div.vis-color-picker div.vis-button.vis-load {
    left: 82px
}

div.vis-color-picker div.vis-button.vis-apply {
    left: 159px
}

div.vis-color-picker div.vis-button.vis-save {
    left: 236px
}

div.vis-color-picker input.vis-range {
    width: 290px;
    height: 20px
}

div.vis-network div.vis-manipulation {
    box-sizing: content-box;
    border-width: 0;
    border-bottom: 1px;
    border-style: solid;
    border-color: #d6d9d8;
    background: #fff;
    background: -moz-linear-gradient(top, #fff 0, #fcfcfc 48%, #fafafa 50%, #fcfcfc 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(48%, #fcfcfc), color-stop(50%, #fafafa), color-stop(100%, #fcfcfc));
    background: -webkit-linear-gradient(top, #fff 0, #fcfcfc 48%, #fafafa 50%, #fcfcfc 100%);
    background: -o-linear-gradient(top, #fff 0, #fcfcfc 48%, #fafafa 50%, #fcfcfc 100%);
    background: -ms-linear-gradient(top, #fff 0, #fcfcfc 48%, #fafafa 50%, #fcfcfc 100%);
    background: linear-gradient(to bottom, #fff 0, #fcfcfc 48%, #fafafa 50%, #fcfcfc 100%);
    padding-top: 4px;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 28px
}

div.vis-network div.vis-edit-mode {
    position: absolute;
    left: 0;
    top: 5px;
    height: 30px
}

div.vis-network div.vis-close {
    position: absolute;
    right: 0;
    top: 0;
    width: 30px;
    height: 30px;
    background-position: 20px 3px;
    background-repeat: no-repeat;
    background-image: url(img/network/cross.png);
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none
}

div.vis-network div.vis-close:hover {
    opacity: .6
}

div.vis-network div.vis-edit-mode div.vis-button, div.vis-network div.vis-manipulation div.vis-button {
    font-family: Roboto, sans-serif;
    font-size: 12px;
    -moz-border-radius: 15px;
    border-radius: 15px;
    display: inline-block;
    background-position: 0 0;
    background-repeat: no-repeat;
    height: 24px;
    margin-left: 10px;
    cursor: pointer;
    padding: 0 8px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none
}

div.vis-network div.vis-manipulation div.vis-button:hover {
    box-shadow: 1px 1px 8px rgba(0, 0, 0, .2)
}

div.vis-network div.vis-manipulation div.vis-button:active {
    box-shadow: 1px 1px 8px rgba(0, 0, 0, .5)
}

div.vis-network div.vis-manipulation div.vis-button.vis-back {
    background-image: url(img/network/backIcon.png)
}

div.vis-network div.vis-manipulation div.vis-button.vis-none:hover {
    box-shadow: 1px 1px 8px transparent;
    cursor: default
}

div.vis-network div.vis-manipulation div.vis-button.vis-none:active {
    box-shadow: 1px 1px 8px transparent
}

div.vis-network div.vis-manipulation div.vis-button.vis-none {
    padding: 0
}

div.vis-network div.vis-manipulation div.notification {
    margin: 2px;
    font-weight: 700
}

div.vis-network div.vis-manipulation div.vis-button.vis-add {
    background-image: url(img/network/addNodeIcon.png)
}

div.vis-network div.vis-edit-mode div.vis-button.vis-edit, div.vis-network div.vis-manipulation div.vis-button.vis-edit {
    background-image: url(img/network/editIcon.png)
}

div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode {
    background-color: #fcfcfc;
    border: 1px solid #ccc
}

div.vis-network div.vis-manipulation div.vis-button.vis-connect {
    background-image: url(img/network/connectIcon.png)
}

div.vis-network div.vis-manipulation div.vis-button.vis-delete {
    background-image: url(img/network/deleteIcon.png)
}

div.vis-network div.vis-edit-mode div.vis-label, div.vis-network div.vis-manipulation div.vis-label {
    margin: 0 0 0 23px;
    line-height: 25px
}

#joystick div i, #joystickreset {
    line-height: 50px
}

div.vis-network div.vis-manipulation div.vis-separator-line {
    display: inline-block;
    width: 1px;
    height: 21px;
    background-color: #bdbdbd;
    margin: 0 7px 0 15px
}

div.vis-network div.vis-navigation div.vis-button {
    width: 34px;
    height: 34px;
    -moz-border-radius: 17px;
    border-radius: 17px;
    position: absolute;
    display: inline-block;
    background-position: 2px 2px;
    background-repeat: no-repeat;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none
}

div.vis-network div.vis-navigation div.vis-button:hover {
    box-shadow: 0 0 3px 3px rgba(56, 207, 21, .3)
}

div.vis-network div.vis-navigation div.vis-button:active {
    box-shadow: 0 0 1px 3px rgba(56, 207, 21, .95)
}

div.vis-network div.vis-navigation div.vis-button.vis-up {
    background-image: url(img/network/upArrow.png);
    bottom: 50px;
    left: 55px
}

div.vis-network div.vis-navigation div.vis-button.vis-down {
    background-image: url(img/network/downArrow.png);
    bottom: 10px;
    left: 55px
}

div.vis-network div.vis-navigation div.vis-button.vis-left {
    background-image: url(img/network/leftArrow.png);
    bottom: 10px;
    left: 15px
}

div.vis-network div.vis-navigation div.vis-button.vis-right {
    background-image: url(img/network/rightArrow.png);
    bottom: 10px;
    left: 95px
}

div.vis-network div.vis-navigation div.vis-button.vis-zoomIn {
    background-image: url(img/network/plus.png);
    bottom: 10px;
    right: 15px
}

div.vis-network div.vis-navigation div.vis-button.vis-zoomOut {
    background-image: url(img/network/minus.png);
    bottom: 10px;
    right: 55px
}

div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends {
    background-image: url(img/network/zoomExtends.png);
    bottom: 50px;
    right: 15px
}

.vis-current-time {
    background-color: #ff7f6e;
    width: 2px;
    z-index: 1;
    pointer-events: none
}

.vis-rolling-mode-btn {
    height: 40px;
    width: 40px;
    position: absolute;
    top: 7px;
    right: 20px;
    border-radius: 50%;
    font-size: 28px;
    cursor: pointer;
    opacity: .8;
    color: #fff;
    font-weight: 700;
    text-align: center;
    background: #3876c2
}

.vis-rolling-mode-btn:before {
    content: "\26F6"
}

.vis-rolling-mode-btn:hover {
    opacity: 1
}

.vis-custom-time {
    background-color: #6e94ff;
    width: 2px;
    cursor: move
}

.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal {
    position: absolute;
    width: 100%;
    height: 0;
    border-bottom: 1px solid
}

.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor {
    border-color: #e5e5e5
}

.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major {
    border-color: #bfbfbf
}

.vis-data-axis .vis-y-axis.vis-major {
    width: 100%;
    position: absolute;
    color: #4d4d4d;
    white-space: nowrap
}

.vis-data-axis .vis-y-axis.vis-major.vis-measure {
    padding: 0;
    margin: 0;
    border: 0;
    visibility: hidden;
    width: auto
}

.vis-data-axis .vis-y-axis.vis-minor {
    position: absolute;
    width: 100%;
    color: #bebebe;
    white-space: nowrap
}

.vis-data-axis .vis-y-axis.vis-minor.vis-measure {
    padding: 0;
    margin: 0;
    border: 0;
    visibility: hidden;
    width: auto
}

.vis-data-axis .vis-y-axis.vis-title {
    position: absolute;
    color: #4d4d4d;
    white-space: nowrap;
    bottom: 20px;
    text-align: center
}

.vis-data-axis .vis-y-axis.vis-title.vis-measure {
    padding: 0;
    margin: 0;
    visibility: hidden;
    width: auto
}

.vis-data-axis .vis-y-axis.vis-title.vis-left {
    bottom: 0;
    -webkit-transform-origin: left top;
    -moz-transform-origin: left top;
    -ms-transform-origin: left top;
    -o-transform-origin: left top;
    transform-origin: left bottom;
    -webkit-transform: rotate(-90deg);
    -moz-transform: rotate(-90deg);
    -ms-transform: rotate(-90deg);
    -o-transform: rotate(-90deg);
    transform: rotate(-90deg)
}

.vis-data-axis .vis-y-axis.vis-title.vis-right {
    bottom: 0;
    -webkit-transform-origin: right bottom;
    -moz-transform-origin: right bottom;
    -ms-transform-origin: right bottom;
    -o-transform-origin: right bottom;
    transform-origin: right bottom;
    -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    transform: rotate(90deg)
}

.vis-legend {
    background-color: rgba(247, 252, 255, .65);
    padding: 5px;
    border: 1px solid #b3b3b3;
    box-shadow: 2px 2px 10px rgba(154, 154, 154, .55)
}

.vis-legend-text {
    white-space: nowrap;
    display: inline-block
}

.vis-item {
    position: absolute;
    color: #1a1a1a;
    border-color: #97b0f8;
    border-width: 1px;
    background-color: #d5ddf6;
    display: inline-block;
    z-index: 1
}

.vis-item.vis-point.vis-selected, .vis-item.vis-selected {
    background-color: #fff785
}

.vis-item.vis-selected {
    border-color: #ffc200;
    z-index: 2
}

.vis-editable.vis-selected {
    cursor: move
}

.vis-item.vis-box {
    text-align: center;
    border-style: solid;
    border-radius: 2px
}

.vis-item.vis-point {
    background: 0 0
}

.vis-item.vis-dot {
    position: absolute;
    padding: 0;
    border-width: 4px;
    border-style: solid;
    border-radius: 4px
}

.vis-item.vis-range {
    border-style: solid;
    border-radius: 2px;
    box-sizing: border-box
}

.vis-item.vis-background {
    border: none;
    background-color: rgba(213, 221, 246, .4);
    box-sizing: border-box;
    padding: 0;
    margin: 0
}

.vis-item .vis-item-overflow {
    position: relative;
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
    overflow: hidden
}

.vis-item-visible-frame {
    white-space: nowrap
}

.vis-item.vis-range .vis-item-content {
    position: relative;
    display: inline-block
}

.vis-item.vis-background .vis-item-content {
    position: absolute;
    display: inline-block
}

.vis-item.vis-line {
    padding: 0;
    position: absolute;
    width: 0;
    border-left-width: 1px;
    border-left-style: solid
}

.vis-item .vis-item-content {
    white-space: nowrap;
    box-sizing: border-box;
    padding: 5px
}

.vis-item .vis-onUpdateTime-tooltip {
    position: absolute;
    background: #4f81bd;
    color: #fff;
    width: 200px;
    text-align: center;
    white-space: nowrap;
    padding: 5px;
    border-radius: 1px;
    transition: .4s;
    -o-transition: .4s;
    -moz-transition: .4s;
    -webkit-transition: .4s
}

.vis-item .vis-delete, .vis-item .vis-delete-rtl {
    position: absolute;
    top: 0;
    width: 24px;
    height: 24px;
    box-sizing: border-box;
    padding: 0 5px;
    cursor: pointer;
    -webkit-transition: background .2s linear;
    -moz-transition: background .2s linear;
    -ms-transition: background .2s linear;
    -o-transition: background .2s linear;
    transition: background .2s linear
}

.vis-item .vis-delete {
    right: -24px
}

.vis-item .vis-delete-rtl {
    left: -24px
}

.vis-item .vis-delete-rtl:after, .vis-item .vis-delete:after {
    content: "\00D7";
    color: red;
    font-size: 22px;
    font-weight: 700;
    -webkit-transition: color .2s linear;
    -moz-transition: color .2s linear;
    -ms-transition: color .2s linear;
    -o-transition: color .2s linear;
    transition: color .2s linear
}

.vis-item .vis-delete-rtl:hover, .vis-item .vis-delete:hover {
    background: red
}

.vis-item .vis-delete-rtl:hover:after, .vis-item .vis-delete:hover:after {
    color: #fff
}

.vis-item .vis-drag-center {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    cursor: move
}

.vis-item.vis-range .vis-drag-left, .vis-item.vis-range .vis-drag-right {
    position: absolute;
    width: 24px;
    max-width: 20%;
    min-width: 2px;
    height: 100%;
    top: 0
}

.vis-item.vis-range .vis-drag-left {
    left: -4px;
    cursor: w-resize
}

.vis-item.vis-range .vis-drag-right {
    right: -4px;
    cursor: e-resize
}

.vis-range.vis-item.vis-readonly .vis-drag-left, .vis-range.vis-item.vis-readonly .vis-drag-right {
    cursor: auto
}

#joystick div, .leaflet-interactive, .vis-labelset .vis-label.draggable, .vis-nesting-group {
    cursor: pointer
}

.vis-itemset {
    position: relative;
    padding: 0;
    margin: 0;
    box-sizing: border-box
}

.vis-itemset .vis-background, .vis-itemset .vis-foreground {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: visible
}

.vis-axis {
    position: absolute;
    width: 100%;
    height: 0;
    left: 0;
    z-index: 1
}

.vis-foreground .vis-group {
    position: relative;
    box-sizing: border-box;
    border-bottom: 1px solid #bfbfbf
}

.vis-foreground .vis-group:last-child {
    border-bottom: none
}

.vis-nested-group {
    background: #f5f5f5
}

.vis-label.vis-nesting-group.expanded:before {
    content: "\25BC"
}

.vis-label.vis-nesting-group.collapsed-rtl:before {
    content: "\25C0"
}

.vis-label.vis-nesting-group.collapsed:before {
    content: "\25B6"
}

.vis-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10
}

.vis-labelset, .vis-labelset .vis-label {
    position: relative;
    box-sizing: border-box
}

.vis-labelset {
    overflow: hidden
}

.vis-labelset .vis-label {
    left: 0;
    top: 0;
    width: 100%;
    color: #4d4d4d;
    border-bottom: 1px solid #bfbfbf
}

.vis-labelset .vis-label:last-child {
    border-bottom: none
}

.vis-labelset .vis-label .vis-inner {
    display: inline-block;
    padding: 5px
}

.vis-labelset .vis-label .vis-inner.vis-hidden {
    padding: 0
}

.vis-panel {
    position: absolute;
    padding: 0;
    margin: 0;
    box-sizing: border-box
}

.vis-panel.vis-bottom, .vis-panel.vis-center, .vis-panel.vis-left, .vis-panel.vis-right, .vis-panel.vis-top {
    border: 1px #bfbfbf
}

.vis-panel.vis-center, .vis-panel.vis-left, .vis-panel.vis-right {
    border-top-style: solid;
    border-bottom-style: solid;
    overflow: hidden
}

.vis-left.vis-panel.vis-vertical-scroll, .vis-right.vis-panel.vis-vertical-scroll {
    height: 100%;
    overflow-x: hidden;
    overflow-y: scroll
}

.vis-left.vis-panel.vis-vertical-scroll {
    direction: rtl
}

.vis-left.vis-panel.vis-vertical-scroll .vis-content, .vis-right.vis-panel.vis-vertical-scroll {
    direction: ltr
}

.vis-right.vis-panel.vis-vertical-scroll .vis-content {
    direction: rtl
}

.vis-panel.vis-bottom, .vis-panel.vis-center, .vis-panel.vis-top {
    border-left-style: solid;
    border-right-style: solid
}

.vis-panel>.vis-content {
    position: relative
}

.vis-panel .vis-shadow {
    position: absolute;
    width: 100%;
    height: 1px;
    box-shadow: 0 0 10px rgba(0, 0, 0, .8)
}

.vis-panel .vis-shadow.vis-top {
    top: -1px;
    left: 0
}

.vis-panel .vis-shadow.vis-bottom {
    bottom: -1px;
    left: 0
}

.vis-graph-group0 {
    fill: #4f81bd;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #4f81bd
}

.vis-graph-group1 {
    fill: #f79646;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #f79646
}

.vis-graph-group2 {
    fill: #8c51cf;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #8c51cf
}

.vis-graph-group3 {
    fill: #75c841;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #75c841
}

.vis-graph-group4 {
    fill: #ff0100;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #ff0100
}

.vis-graph-group5 {
    fill: #37d8e6;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #37d8e6
}

.vis-graph-group6 {
    fill: #042662;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #042662
}

.vis-graph-group7 {
    fill: #00ff26;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #00ff26
}

.vis-graph-group8 {
    fill: #f0f;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #f0f
}

.vis-graph-group9 {
    fill: #8f3938;
    fill-opacity: 0;
    stroke-width: 2px;
    stroke: #8f3938
}

.vis-timeline .vis-fill {
    fill-opacity: .1;
    stroke: none
}

.vis-timeline .vis-bar {
    fill-opacity: .5;
    stroke-width: 1px
}

.vis-timeline .vis-point {
    stroke-width: 2px;
    fill-opacity: 1
}

.vis-timeline .vis-legend-background {
    stroke-width: 1px;
    fill-opacity: .9;
    fill: #fff;
    stroke: #c2c2c2
}

.vis-timeline .vis-outline {
    stroke-width: 1px;
    fill-opacity: 1;
    fill: #fff;
    stroke: #e5e5e5
}

.vis-timeline .vis-icon-fill {
    fill-opacity: .3;
    stroke: none
}

.vis-time-axis {
    position: relative;
    overflow: hidden
}

.vis-time-axis.vis-foreground {
    top: 0;
    left: 0;
    width: 100%
}

.vis-time-axis.vis-background {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%
}

.vis-time-axis .vis-text {
    position: absolute;
    color: #4d4d4d;
    padding: 3px;
    overflow: hidden;
    box-sizing: border-box;
    white-space: nowrap
}

.vis-time-axis .vis-text.vis-measure {
    position: absolute;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
    visibility: hidden
}

.vis-time-axis .vis-grid.vis-vertical {
    position: absolute;
    border-left: 1px solid
}

.vis-time-axis .vis-grid.vis-vertical-rtl {
    position: absolute;
    border-right: 1px solid
}

.vis-time-axis .vis-grid.vis-minor {
    border-color: #e5e5e5
}

.vis-time-axis .vis-grid.vis-major {
    border-color: #bfbfbf
}

.vis-timeline {
    position: relative;
    border: 1px solid #bfbfbf;
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    height: 77px!important
}

.vis-item {
    background: linear-gradient(to bottom, #3a99d9, #2e81b7)
}

.vis-background, .vis-timeline {
    overflow: visible
}

.vis-minor {
    color: #fcfcfc!important
}

.vis-custom-time {
    background: #ff4c4c;
    z-index: 2
}

.vis-text {
    font-size: 14px;
    color: #fff!important
}

.exportinterval {
    z-index: 2
}

.right {
    float: right
}

#joystickdown, #joystickup {
    left: 40px;
    position: absolute
}

/*
#btnJoystick i, #btnTakeScreenshot i {
    position: relative;
    top: 1px
}
*/

.btnactive {
    background: #4b9fd6;
    color: #fff
}

#joystick.active {
    display: block!important
}

#joystick {
    display: none!important;
    padding: 5px;
    border-radius: 12px;
    position: absolute;
    top: -160px;
    background: rgba(0, 0, 0, .58);
    width: 250px;
    height: 120px;
    border: 10px solid transparent
}

#joystick div {
    user-select: none;
    width: 50px;
    height: 50px;
    border-radius: 100px;
    background: #fff;
    text-align: center
}

#joystickleft{
	position: absolute;
	top: 50%;
	left: 0;
	transform: translateY(-50%);
}
#joystickup{
	position: absolute;
	top: 0;
	left: 40px;
}
#joystickdown{
	position: absolute;
	bottom: 0;
	left: 40px;
}
#joystickright{
	position: absolute;
	left: 80px;
	top: 50%;
  transform: translateY(-50%);
}

#joystickplus {
    position: absolute;
    right: 0;
    top: 0
}

#joystickminus {
    position: absolute;
    right: 60px;
    top: 0
}

#joystickreset {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 110px!important;
    font-size: 15px
}

#timebar {
  position: absolute;
  bottom: 157px;
  right: 10px;
  color: #fff;
  text-shadow: 0 -1px 2px rgba(0, 0, 0, .2), 0 -1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), -1px 0 5px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px 0 2px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2)
}

#namebar {
  position: absolute;
  bottom: 179px;
  right: 10px;
  color: #fff;
  text-shadow: 0 -1px 2px rgba(0, 0, 0, .2), 0 -1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), -1px 0 5px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px 0 2px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2)
}

#namebar span {
  font-size: 0.8em;
}

.subname{
  position: absolute;
  bottom: 1px;
  right: 3px;
  font-size: 11px;
  color: #fff;
  text-shadow: 0 -1px 2px rgba(0, 0, 0, .2), 0 -1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), 0 1px 2px rgba(0, 0, 0, .2), -1px 0 5px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px 0 2px rgba(0, 0, 0, .2), 1px 0 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2), -1px -1px 2px rgba(0, 0, 0, .2), 1px -1px 2px rgba(0, 0, 0, .2), -1px 1px 2px rgba(0, 0, 0, .2), 1px 1px 2px rgba(0, 0, 0, .2)
}

#backbutton {
    position: fixed;
    top: 5px;
    left: 5px;
    z-index: 2;
}

#backreal.active {
    display: block
}

#backreal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0
}

#btnJoystick i {
    left: 1px
}

.lvml, .selfToast {
    position: absolute
}

.selfToast {
    top: 0;
    left: 50%;
    font-size: 15px;
    margin: 5px;
    border-radius: 5px;
    color: #fff
}

.selfToast.error {
    background: rgba(255, 100, 100, .7)
}

.leaflet-image-layer, .leaflet-layer, .leaflet-marker-icon, .leaflet-marker-shadow, .leaflet-pane, .leaflet-pane>canvas, .leaflet-pane>svg, .leaflet-tile, .leaflet-tile-container, .leaflet-zoom-box {
    position: absolute;
    left: 0;
    top: 0
}

.leaflet-container {
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
    background: #ddd;
    outline: 0;
    font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif
}

.leaflet-marker-icon, .leaflet-marker-shadow, .leaflet-tile {
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    -webkit-user-drag: none
}

.leaflet-overlay-pane svg, .leaflet-tooltip {
    -moz-user-select: none
}

.leaflet-safari .leaflet-tile {
    image-rendering: -webkit-optimize-contrast
}

.leaflet-safari .leaflet-tile-container {
    width: 1600px;
    height: 1600px;
}

.leaflet-marker-icon, .leaflet-marker-shadow {
    display: block
}

.leaflet-container .leaflet-marker-pane img, .leaflet-container .leaflet-overlay-pane svg, .leaflet-container .leaflet-shadow-pane img, .leaflet-container .leaflet-tile-pane img, .leaflet-container img.leaflet-image-layer {
    max-width: none!important;
    max-height: none!important
}

.leaflet-container.leaflet-touch-zoom {
    -ms-touch-action: pan-x pan-y;
    touch-action: pan-x pan-y
}

.leaflet-container.leaflet-touch-drag {
    -ms-touch-action: pinch-zoom;
    touch-action: none;
    touch-action: pinch-zoom
}

.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
    -ms-touch-action: none;
    touch-action: none
}

.leaflet-container a {
    -webkit-tap-highlight-color: rgba(51, 181, 229, .4);
    color: #0078A8
}

.leaflet-tile {
    filter: inherit;
    visibility: hidden
}

.leaflet-tile-loaded {
    visibility: inherit
}

.leaflet-zoom-box {
    width: 0;
    height: 0;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    z-index: 800;
    border: 2px dotted #38f;
    background: rgba(255, 255, 255, .5)
}

.leaflet-pane {
    z-index: 400
}

.leaflet-tile-pane {
    z-index: 200
}

.leaflet-overlay-pane {
    z-index: 400
}

.leaflet-shadow-pane {
    z-index: 500
}

.leaflet-marker-pane {
    z-index: 600
}

.leaflet-tooltip-pane {
    z-index: 650
}

.leaflet-popup-pane {
    z-index: 700
}

.leaflet-map-pane canvas {
    z-index: 100
}

.leaflet-map-pane svg {
    z-index: 200
}

.leaflet-vml-shape {
    width: 1px;
    height: 1px
}

.lvml {
    behavior: url(#default#VML);
    display: inline-block
}

.leaflet-control {
    position: relative;
    z-index: 800;
    pointer-events: visiblePainted;
    pointer-events: auto;
    float: left;
    clear: both
}

.leaflet-bottom, .leaflet-top {
    position: absolute;
    z-index: 1000;
    pointer-events: none
}

.leaflet-top {
    top: 0
}

.leaflet-right {
    right: 0
}

.leaflet-bottom {
    bottom: 0
}

.leaflet-left {
    left: 0
}

.leaflet-right .leaflet-control {
    float: right;
    margin-right: 10px
}

.leaflet-top .leaflet-control {
    margin-top: 10px
}

.leaflet-bottom .leaflet-control {
    margin-bottom: 10px
}

.leaflet-left .leaflet-control {
    margin-left: 10px
}

.leaflet-fade-anim .leaflet-tile {
    will-change: opacity
}

.leaflet-fade-anim .leaflet-popup {
    opacity: 0;
    -webkit-transition: opacity .2s linear;
    -moz-transition: opacity .2s linear;
    -o-transition: opacity .2s linear;
    transition: opacity .2s linear
}

.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
    opacity: 1
}

.leaflet-zoom-animated {
    -webkit-transform-origin: 0 0;
    -ms-transform-origin: 0 0;
    transform-origin: 0 0
}

.leaflet-zoom-anim .leaflet-zoom-animated {
    will-change: transform;
    -webkit-transition: -webkit-transform .25s cubic-bezier(0, 0, .25, 1);
    -moz-transition: -moz-transform .25s cubic-bezier(0, 0, .25, 1);
    -o-transition: -o-transform .25s cubic-bezier(0, 0, .25, 1);
    transition: transform .25s cubic-bezier(0, 0, .25, 1)
}

.leaflet-pan-anim .leaflet-tile, .leaflet-zoom-anim .leaflet-tile {
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none
}

.leaflet-zoom-anim .leaflet-zoom-hide {
    visibility: hidden
}

.leaflet-grab {
    cursor: -webkit-grab;
    cursor: -moz-grab
}

.leaflet-crosshair, .leaflet-crosshair .leaflet-interactive {
    cursor: crosshair
}

.leaflet-control, .leaflet-popup-pane {
    cursor: auto
}

.leaflet-dragging .leaflet-grab, .leaflet-dragging .leaflet-grab .leaflet-interactive, .leaflet-dragging .leaflet-marker-draggable {
    cursor: move;
    cursor: -webkit-grabbing;
    cursor: -moz-grabbing
}

.leaflet-image-layer, .leaflet-marker-icon, .leaflet-marker-shadow, .leaflet-pane>svg path, .leaflet-tile-container {
    pointer-events: none
}

.leaflet-image-layer.leaflet-interactive, .leaflet-marker-icon.leaflet-interactive, .leaflet-pane>svg path.leaflet-interactive {
    pointer-events: visiblePainted;
    pointer-events: auto
}

.leaflet-container a.leaflet-active {
    outline: orange solid 2px
}

.leaflet-bar {
    box-shadow: 0 1px 5px rgba(0, 0, 0, .65);
    border-radius: 4px
}

.leaflet-bar a, .leaflet-bar a:hover {
    background-color: #fff;
    border-bottom: 1px solid #ccc;
    width: 26px;
    height: 26px;
    line-height: 26px;
    display: block;
    text-align: center;
    text-decoration: none;
    color: #000
}

.leaflet-bar a, .leaflet-control-layers-toggle {
    background-position: 50% 50%;
    background-repeat: no-repeat;
    display: block
}

.leaflet-bar a:hover {
    background-color: #f4f4f4
}

.leaflet-bar a:first-child {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px
}

.leaflet-bar a:last-child {
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    border-bottom: none
}

.leaflet-bar a.leaflet-disabled {
    cursor: default;
    background-color: #f4f4f4;
    color: #bbb
}

.leaflet-touch .leaflet-bar a {
    width: 30px;
    height: 30px;
    line-height: 30px
}

.leaflet-touch .leaflet-bar a:first-child {
    border-top-left-radius: 2px;
    border-top-right-radius: 2px
}

.leaflet-touch .leaflet-bar a:last-child {
    border-bottom-left-radius: 2px;
    border-bottom-right-radius: 2px
}

.leaflet-control-zoom-in, .leaflet-control-zoom-out {
    font: 700 18px 'Lucida Console', Monaco, monospace;
    text-indent: 1px
}

.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
    font-size: 22px
}

.leaflet-control-layers {
    box-shadow: 0 1px 5px rgba(0, 0, 0, .4);
    background: #fff;
    border-radius: 5px
}

.leaflet-control-layers-toggle {
    background-image: url(images/layers.png);
    width: 36px;
    height: 36px
}

.leaflet-retina .leaflet-control-layers-toggle {
    background-image: url(images/layers-2x.png);
    background-size: 26px 26px
}

.leaflet-touch .leaflet-control-layers-toggle {
    width: 44px;
    height: 44px
}

.leaflet-control-layers .leaflet-control-layers-list, .leaflet-control-layers-expanded .leaflet-control-layers-toggle {
    display: none
}

.leaflet-control-layers-expanded .leaflet-control-layers-list {
    display: block;
    position: relative
}

.leaflet-control-layers-expanded {
    padding: 6px 10px 6px 6px;
    color: #333;
    background: #fff
}

.leaflet-control-layers-scrollbar {
    overflow-y: scroll;
    overflow-x: hidden;
    padding-right: 5px
}

.leaflet-control-layers-selector {
    margin-top: 2px;
    position: relative;
    top: 1px
}

.leaflet-control-layers label {
    display: block
}

.leaflet-control-layers-separator {
    height: 0;
    border-top: 1px solid #ddd;
    margin: 5px -10px 5px -6px
}

.leaflet-default-icon-path {
    background-image: url(images/marker-icon.png)
}

.leaflet-container .leaflet-control-attribution {
    background: #fff;
    background: rgba(255, 255, 255, .7);
    margin: 0
}

.leaflet-control-attribution, .leaflet-control-scale-line {
    padding: 0 5px;
    color: #333
}

.leaflet-control-attribution a:hover {
    text-decoration: underline
}

.leaflet-container .leaflet-control-attribution, .leaflet-container .leaflet-control-scale {
    font-size: 11px
}

.leaflet-left .leaflet-control-scale {
    margin-left: 5px
}

.leaflet-bottom .leaflet-control-scale {
    margin-bottom: 5px
}

.leaflet-control-scale-line {
    border: 2px solid #777;
    border-top: none;
    line-height: 1.1;
    padding: 2px 5px 1px;
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    background: #fff;
    background: rgba(255, 255, 255, .5)
}

.leaflet-control-scale-line:not(:first-child) {
    border-top: 2px solid #777;
    border-bottom: none;
    margin-top: -2px
}

.leaflet-control-scale-line:not(:first-child):not(:last-child) {
    border-bottom: 2px solid #777
}

.leaflet-touch .leaflet-bar, .leaflet-touch .leaflet-control-attribution, .leaflet-touch .leaflet-control-layers {
    box-shadow: none
}

.leaflet-touch .leaflet-bar, .leaflet-touch .leaflet-control-layers {
    border: 2px solid rgba(0, 0, 0, .2);
    background-clip: padding-box
}

.leaflet-popup {
    position: absolute;
    text-align: center;
    margin-bottom: 20px
}

.leaflet-popup-content-wrapper {
    padding: 1px;
    text-align: left;
    border-radius: 12px
}

.leaflet-popup-content {
    margin: 13px 19px;
    line-height: 1.4
}

.leaflet-popup-content p {
    margin: 18px 0
}

.leaflet-popup-tip-container {
    width: 40px;
    height: 20px;
    position: absolute;
    left: 50%;
    margin-left: -20px;
    overflow: hidden;
    pointer-events: none
}

.leaflet-popup-tip {
    width: 17px;
    height: 17px;
    padding: 1px;
    margin: -10px auto 0;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -o-transform: rotate(45deg);
    transform: rotate(45deg)
}

.leaflet-popup-content-wrapper, .leaflet-popup-tip {
    background: #fff;
    color: #333;
    box-shadow: 0 3px 14px rgba(0, 0, 0, .4)
}

.leaflet-container a.leaflet-popup-close-button {
    position: absolute;
    top: 0;
    right: 0;
    padding: 4px 4px 0 0;
    border: none;
    text-align: center;
    width: 18px;
    height: 14px;
    font: 16px/14px Tahoma, Verdana, sans-serif;
    color: #c3c3c3;
    text-decoration: none;
    font-weight: 700;
    background: 0 0
}

.leaflet-container a.leaflet-popup-close-button:hover {
    color: #999
}

.leaflet-popup-scrolled {
    overflow: auto;
    border-bottom: 1px solid #ddd;
    border-top: 1px solid #ddd
}

.leaflet-oldie .leaflet-popup-content-wrapper {
    zoom: 1
}

.leaflet-oldie .leaflet-popup-tip {
    width: 24px;
    margin: 0 auto;
    -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
    filter: progid:DXImageTransform.Microsoft.Matrix(M11=.70710678, M12=.70710678, M21=-.70710678, M22=.70710678)
}

.leaflet-oldie .leaflet-popup-tip-container {
    margin-top: -1px
}

.leaflet-oldie .leaflet-control-layers, .leaflet-oldie .leaflet-control-zoom, .leaflet-oldie .leaflet-popup-content-wrapper, .leaflet-oldie .leaflet-popup-tip {
    border: 1px solid #999
}

.leaflet-div-icon {
    background: #fff;
    border: 1px solid #666
}

.leaflet-tooltip {
    position: absolute;
    padding: 6px;
    background-color: #fff;
    border: 1px solid #fff;
    border-radius: 3px;
    color: #222;
    white-space: nowrap;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
    pointer-events: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .4)
}

.leaflet-tooltip.leaflet-clickable {
    cursor: pointer;
    pointer-events: auto
}

.leaflet-tooltip-bottom:before, .leaflet-tooltip-left:before, .leaflet-tooltip-right:before, .leaflet-tooltip-top:before {
    position: absolute;
    pointer-events: none;
    border: 6px solid transparent;
    background: 0 0;
    content: ""
}

.leaflet-tooltip-bottom {
    margin-top: 6px
}

.leaflet-tooltip-top {
    margin-top: -6px
}

.leaflet-tooltip-bottom:before, .leaflet-tooltip-top:before {
    left: 50%;
    margin-left: -6px
}

.leaflet-tooltip-top:before {
    bottom: 0;
    margin-bottom: -12px;
    border-top-color: #fff
}

.leaflet-tooltip-bottom:before {
    top: 0;
    margin-top: -12px;
    margin-left: -6px;
    border-bottom-color: #fff
}

.leaflet-tooltip-left {
    margin-left: -6px
}

.leaflet-tooltip-right {
    margin-left: 6px
}

.leaflet-tooltip-left:before, .leaflet-tooltip-right:before {
    top: 50%;
    margin-top: -6px
}

.leaflet-tooltip-left:before {
    right: 0;
    margin-right: -12px;
    border-left-color: #fff
}

.leaflet-tooltip-right:before {
    left: 0;
    margin-left: -12px;
    border-right-color: #fff
}

.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
    -webkit-transition: -webkit-transform .3s ease-out, opacity .3s ease-in;
    -moz-transition: -moz-transform .3s ease-out, opacity .3s ease-in;
    -o-transition: -o-transform .3s ease-out, opacity .3s ease-in;
    transition: transform .3s ease-out, opacity .3s ease-in
}

.touch #backbutton {
    display: none;
}

.leaflet-cluster-spider-leg {
    -webkit-transition: -webkit-stroke-dashoffset .3s ease-out, -webkit-stroke-opacity .3s ease-in;
    -moz-transition: -moz-stroke-dashoffset .3s ease-out, -moz-stroke-opacity .3s ease-in;
    -o-transition: -o-stroke-dashoffset .3s ease-out, -o-stroke-opacity .3s ease-in;
    transition: stroke-dashoffset .3s ease-out, stroke-opacity .3s ease-in
}

#modal_container {
    display: none;
    position: fixed;
    top: calc(50% - 34px);
    left: 50%;
    width: calc(100vw - 50px);
    height: calc(100vh - 67px - 50px);
    z-index: 1001;
}

#modal_result {
    background: #fff;
    transition: all 0.2s;
    opacity: 0;
    position: absolute;
    border-radius: 5px;
    border: 1px solid #d6d6d6;
    box-shadow: 0 0 10px 0px rgba(0, 0, 0, .5);
    top: -50%;
    left: -50%;
    transform: scale(0);
    width: calc(100vw - 50px);
    height: calc(100vh - 67px - 50px);
}

#modal_container.show {
    display: block;
}

#modal_container.show #modal_result {
    opacity: 1;
    transform: scale(1);
}

#modal_content {
    margin-top: 40px;
    padding: 30px;
    max-height: calc(100% - 40px)
}

#modal_title {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    text-align: center;
    padding: 12px;
    box-sizing: border-box;
    font-weight: 700;
}

#modal_close {
    user-select: none;
    position: absolute;
    z-index: 1;
    top: 5px;
    right: 5px;
    cursor: pointer;
}

.leaflet-control-zoom {
    border: 0!important;
    position: fixed;
    margin: 0!important;
    top: calc((100% - 69px) / 2);
    right: 0;
    transform: translateY(-50%)
}

a.leaflet-control-zoom-in, a.leaflet-control-zoom-out {
    font-weight: 700!important;
    font-size: 30px!important;
    background: #fff;
    margin: 10px;
    line-height: 50px!important;
    border-radius: 100px!important;
    height: 50px!important;
    width: 50px!important;
    text-align: center;
    box-shadow: 0 0 10px 0 rgba(100, 100, 100, .6);
    color: #219cec;
}

a.leaflet-control-zoom-in:not(.leaflet-disabled):hover, a.leaflet-control-zoom-out:not(.leaflet-disabled):hover {
    color: #219cec;
}

/*
[data-srcbg]{
    display: none!important;
}*/

#view_offert {
    display: none;
    background: #fff;
    position: fixed;
    box-shadow: 0 0 9px 0px rgba(165, 165, 165, 0.5);
    top: 50%;
    left: 50%;
    z-index: 100;
    transform: translateX(-50%) translateY(-50%);
    
    width: 800px;
    border-radius: 3px;
}

#view_offert #heding {
    padding: 25px;
    border-bottom: 1px dotted #bdbdbd;
    font-weight: 600;
    font-size: 22px;
    text-align: center;
}

#ofert_text {
    padding: 30px;
    max-height: 62vh;
    overflow: auto;
}

#view_offert button {
    width: auto;
    transition: all 0.3s;
    background: #fff;
    border: 1px solid #bbb;
    padding: 5px 23px;
    cursor: pointer;
    border-radius: 3px;
    box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.26);
}

#view_offert button:hover {
    background: #fbfbfb;
}

.letmein{
    line-height: 60px;
    color: #000;
    font-size: 19px;
    padding: 14px;
    border: 1px solid #ddd;
    margin: 5px 0;
    outline: 0;
    border-radius: 4px;
    text-decoration: none;
    transition: all .2s;
}

.letmein:hover{
background: #eee;

}

#mobileapp {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 1001;
}

.mobilebg {
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: white;
  z-index: 1000;
}
#mobilebgcl {
  position: absolute;
  left: 50%;
  top: 0vw;
  height: 1vw;
  width: 1vw;
  z-index: 1005;
}
#mobileapp .mobileapptitle {
    text-align: center;
    width: 80vw;
}
#mobileapp .mobileappurls {
    display: flex;
    margin-top: 9vw;
}
#mobileapp .mobileappurls .app {
    margin: 0 auto;
}
#mobileapp .mobileappurls .app .appicon {
    background-size: contain;
    background-repeat: no-repeat;
    height: 18vw;
    width: 34vw;
}
#mobileapp .mobileappurls .app .title {
    display: none;
}

#mobileapp .mobileappurls .app.playmarket .appicon {
  background-image: url(/assets/img/google.svg);
}
#mobileapp .mobileappurls .app.appstore .appicon {
  background-image: url(/assets/img/apple.svg);
}

#mobileapp .mobileappurls .app.rustore .appicon {
    background-image: url(/assets/img/rustore-mob.png);
}
#mobileapp .mobileappurls .app.appgallery .appicon {
    background-image: url(/assets/img/huawei.png);
}
  


.inputModal{
    display: block;
    margin-top: 10px;
    padding: 0px 0;
    width: 100%;
    border: 0;
    border-bottom: 1px solid #d4d4d4;
    outline: none;
}

#addField{
    position: absolute;
    bottom: 0;
    text-align: center;
    width: 100%;
    padding: 10px 0;
}

#add{
    background: #a3c7df;
    transition: all 0.3s;
    border: red;
    padding: 10px 30px;
    border-radius: 5px;
    color: #3c3c3c;
    cursor: pointer;
}

#add:hover{
    background:#7db2d4
}

.addNumber{
    background: #a3c7df;
    position: absolute;
    right: 7px;
    top: 9px;
    border-radius: 100px;
    width: 20px;
    height: 20px;
    color: #3c3c3c;
    text-align: center;
    line-height: 20px;
}


div#total_selected_wrap {
    position: absolute;
    bottom: 19px;
}

span#total_selected {
    font-size: unset;
    display: inline;
    font-weight: normal;
}



/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */

/* Document
   ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/* Sections
   ========================================================================== */

/**
 * Remove the margin in all browsers.
 */

body {
  margin: 0;
}

/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/* Grouping content
   ========================================================================== */

/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */

hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/* Text-level semantics
   ========================================================================== */

/**
 * Remove the gray background on active links in IE 10.
 */

a {
  background-color: transparent;
}

/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */

abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}

/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */

b,
strong {
  font-weight: bolder;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/**
 * Add the correct font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/* Embedded content
   ========================================================================== */

/**
 * Remove the border on images inside links in IE 10.
 */

img {
  border-style: none;
}

/* Forms
   ========================================================================== */

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */

button,
input { /* 1 */
  overflow: visible;
}

/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */

button,
select { /* 1 */
  text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */

button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */

fieldset {
  padding: 0.35em 0.75em 0.625em;
}

/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */

legend {
  box-sizing: border-box; /* 1 */
  color: inherit; /* 2 */
  display: table; /* 1 */
  max-width: 100%; /* 1 */
  padding: 0; /* 3 */
  white-space: normal; /* 1 */
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */

progress {
  vertical-align: baseline;
}

/**
 * Remove the default vertical scrollbar in IE 10+.
 */

textarea {
  overflow: auto;
}

/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */

[type="checkbox"],
[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */

[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/* Interactive
   ========================================================================== */

/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */

details {
  display: block;
}

/*
 * Add the correct display in all browsers.
 */

summary {
  display: list-item;
}

/* Misc
   ========================================================================== */

/**
 * Add the correct display in IE 10+.
 */

template {
  display: none;
}

/**
 * Add the correct display in IE 10.
 */

[hidden] {
  display: none;
}



/* ============================================================
   Theme variables and overrides.
   Day theme is the existing UI; dark theme is applied by setting
   [data-theme="dark"] on <html>. JS resolves the user's preference
   (light / dark / auto) to a concrete attribute value.
   ============================================================ */

/* Старые имена переменных остались (на них завязано ~137 мест в этом файле),
   но значения теперь берутся из токенов ui.css — палитры десктопа. Так весь
   интерфейс стал монохромным разом, а не по мере переоформления экранов. */
:root {
  color-scheme: light;
  --cctv-bg: var(--bg);
  --cctv-bg-elev: var(--bg-elev);
  --cctv-bg-deep: var(--bg-deep);
  --cctv-fg: var(--fg);
  --cctv-fg-muted: var(--fg-muted);
  --cctv-accent: var(--accent);
  --cctv-link: var(--link);
  --cctv-border: var(--border);
  --cctv-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

html[data-theme="dark"] {
  color-scheme: dark;
  --cctv-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}

/* ----------- <select> styling (works in both themes, native arrow) ----------- */

.selectSettings {
  padding: 6px 12px;
  border: 1px solid var(--cctv-border);
  border-radius: 6px;
  background-color: var(--cctv-bg-elev);
  /* Explicit (not inherit) — the #csettings popup forces color: #fff on
     its descendants, which would make our day-theme select unreadable
     (white text on near-white bg). */
  color: var(--cctv-fg);
  font-family: inherit;
  font-size: 16px;
  line-height: 1.2;
  cursor: pointer;
  outline: 0;
  transition: border-color .15s;
}
.selectSettings option {
  color: var(--cctv-fg);
  background-color: var(--cctv-bg-elev);
}

.selectSettings:hover { border-color: var(--cctv-fg-muted); }
.selectSettings:focus { border-color: var(--cctv-accent); }

/* Align the theme select with the other rows in both settings views */
#settingsPage .selectSettings {
  float: right;
  margin-top: 4px;
  min-width: 140px;
}

#csettings .selectSettings {
  float: right;
  margin-top: 8px;
  min-width: 140px;
}

/* Settings popup overlay: the original 300px width was too narrow for
   the longer "Видео в полный кадр на панели" label, causing it to wrap
   and the floated switch to spill into the next row (visually attaching
   itself to the Тема select). Widen the popup and contain each row's
   floats so layout stays one-row-per-setting. */
#csettings #settingslist {
  width: 380px !important;
  max-width: calc(100vw - 40px);
}
#csettings #settingslist > div.height,
#settingsPage > div.height {
  overflow: hidden;
}

/* ----------- Dark theme: surface overrides ----------- */

/* !important so it beats the inline background-color JS sets on <body>
   (login.main() forces #f3f3f4, post-login sets "white") — otherwise
   that light bar shows through wherever the dark containers don't reach,
   e.g. the strip below the centered login card. */
html[data-theme="dark"] body { background: var(--cctv-bg) !important; color: var(--cctv-fg); }

html[data-theme="dark"] #wrapper,
html[data-theme="dark"] #conttbl,
html[data-theme="dark"] #content,
html[data-theme="dark"] #settingsPage,
html[data-theme="dark"] #panellist,
html[data-theme="dark"] #fon {
  background: var(--cctv-bg);
  color: var(--cctv-fg);
}

/* Переключатель размеров плиток (#viewtype) убран вместе со старой плиткой. */

/* Боковая панель и её тёмный вид — в ui.css, по токенам десктопа. */

/* Calendar, context menu, modal, settings popup — surfaces that need a
   solid panel background. #toasts is intentionally excluded: it's only
   a positioning container, each toast bubble paints its own rgba
   background, and a panel-coloured rectangle under the bubble showed
   through the rounded corners as an ugly dark backdrop on top of the
   video. */
html[data-theme="dark"] #mCalendar,
html[data-theme="dark"] #context,
html[data-theme="dark"] #csettings,
html[data-theme="dark"] #settingsbody {
  background: var(--cctv-bg-elev) !important;
  color: var(--cctv-fg);
  border-color: var(--cctv-border);
  box-shadow: var(--cctv-shadow);
}
html[data-theme="dark"] #toasts {
  background: transparent !important;
  color: var(--cctv-fg);
}

/* Loading spinner — visible only when explicitly activated by the player
   (initial open, archive seek/speed stalls). Without `display: none` as
   the default, the legacy markup left it permanently in the DOM behind
   the video element. */
#loader { display: none; }
#loader.active { display: flex; }
/* Одиночная камера получает ту же плашку, что и ячейка панели (.cellStatus).
   Прежний спиннер — кольцо 6.svg 63×63 с надписью «Загрузка» — убран: язык
   статусов один на весь клиент и на десктоп. Правила из main.css (#loader и
   #loader span) перебиваем по id, иначе фон-картинка и span шириной 300px
   со смещением -115px ломают плашку. */
#loader.cellStatus {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: auto; height: auto;
  background: rgba(40, 44, 52, 0.85);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
  line-height: normal;
  font-size: 13px;
  font-weight: 600;
  z-index: 6;
}
#loader.cellStatus.nosignal { background: rgba(200, 51, 51, 0.92); }
#loader.cellStatus > .txt {
  display: inline; width: auto; position: static; left: auto; margin: 0;
}
#loader.cellStatus > .dots {
  display: inline-flex; width: auto; position: static; left: auto;
}
/* У вердикта точек нет — правило .cellStatus.nosignal .dots перебивается
   селектором по id выше, поэтому повторяем его на том же уровне. */
#loader.cellStatus.nosignal > .dots { display: none; }
/* Calendar day cells — default text is hard-coded #000 which is
   unreadable on dark bg. Restore contrast in both themes. */
html[data-theme="dark"] #m_days > div,
html[data-theme="dark"] #m_daysw > div {
  color: var(--cctv-fg);
}
html[data-theme="dark"] #m_days .unactive {
  color: var(--cctv-fg-muted);
  opacity: 0.45;
}
html[data-theme="dark"] #m_daysw {
  border-bottom-color: var(--cctv-border);
}
html[data-theme="dark"] #m_days > div:not(.unactive):hover {
  background: radial-gradient(rgba(31, 156, 214, 0.6),
                              rgba(31, 156, 214, 0.3),
                              rgba(31, 156, 214, 0));
  color: #fff;
}
html[data-theme="dark"] #m_cont {
  color: var(--cctv-fg);
}
html[data-theme="dark"] #month_left,
html[data-theme="dark"] #month_right {
  color: var(--cctv-accent);
}
html[data-theme="dark"] .csettingsback { background: rgba(0, 0, 0, 0.6); }

html[data-theme="dark"] #modal {
  background: var(--cctv-bg-elev);
  color: var(--cctv-fg);
  border-color: var(--cctv-border);
  box-shadow: 0 0 10px 0 rgba(0,0,0,0.7);
}
html[data-theme="dark"] #modal-text { border-bottom-color: var(--cctv-border); }
html[data-theme="dark"] #modal-buttons div {
  border-right-color: var(--cctv-border);
}
html[data-theme="dark"] #modal-buttons div:hover {
  background: var(--cctv-bg-deep);
}

/* Right-click context menu */
html[data-theme="dark"] #context {
  background: var(--cctv-bg-elev) !important;
  color: var(--cctv-fg);
}
html[data-theme="dark"] #context > div {
  border-top-color: var(--cctv-border);
}
html[data-theme="dark"] #context > div:hover {
  background: var(--cctv-bg-deep);
}
html[data-theme="dark"] #context > div.title {
  background: var(--cctv-bg-deep);
  color: var(--cctv-fg-muted);
}
html[data-theme="dark"] #context > div.redcontext {
  background: rgba(200, 60, 60, 0.6);
  color: var(--cctv-fg);
}
html[data-theme="dark"] #context > div.redcontext:hover {
  background: rgba(200, 60, 60, 0.8);
}

/* Search input + results */
html[data-theme="dark"] #search {
  background: var(--cctv-bg-deep);
  color: var(--cctv-fg);
  border-color: var(--cctv-border);
}
html[data-theme="dark"] #searchRes > div:hover,
html[data-theme="dark"] #filtResult > div:hover {
  background: var(--cctv-bg-deep);
}
html[data-theme="dark"] #searchRes > div:not(.noper),
html[data-theme="dark"] #filtResult > div {
  color: var(--cctv-link);
  border-bottom-color: var(--cctv-border);
}
html[data-theme="dark"] #searchRes > div span,
html[data-theme="dark"] #filtResult > div span {
  color: var(--cctv-fg-muted);
}

/* Cam searcher modal (camera-add picker on the panel screen) */
html[data-theme="dark"] #camSearcher {
  background: var(--cctv-bg-elev);
  color: var(--cctv-fg);
  box-shadow: 0 0 10px 0 rgba(0,0,0,0.7);
}
html[data-theme="dark"] #filter {
  background: transparent;
  color: var(--cctv-fg);
  border-bottom-color: var(--cctv-border);
}

/* Panel list cards (the "list of dashboards" thumbnails) */
html[data-theme="dark"] .panelLink {
  background: var(--cctv-bg-elev);
  border-color: var(--cctv-border);
}
html[data-theme="dark"] .panelLink:hover { background: var(--cctv-bg-deep); }
html[data-theme="dark"] .panelname { color: var(--cctv-fg-muted); }
html[data-theme="dark"] #panellist td { background-color: var(--cctv-bg-elev); }

/* Buttons */
html[data-theme="dark"] .button {
  background: var(--cctv-bg-elev);
  color: var(--cctv-fg);
  border-color: var(--cctv-border);
}
html[data-theme="dark"] .btnAddToPanel {
  color: var(--cctv-fg-muted);
  background: transparent;
  border: 0;
}

/* Form inputs */
html[data-theme="dark"] input[type="text"],
html[data-theme="dark"] input[type="password"],
html[data-theme="dark"] input[type="search"],
html[data-theme="dark"] input[type="number"],
html[data-theme="dark"] input[type="email"],
html[data-theme="dark"] textarea,
html[data-theme="dark"] select {
  background: var(--cctv-bg-deep);
  color: var(--cctv-fg);
  border: 1px solid var(--cctv-border);
}
html[data-theme="dark"] input::placeholder,
html[data-theme="dark"] textarea::placeholder { color: var(--cctv-fg-muted); }
html[data-theme="dark"] a { color: var(--cctv-accent); }

/* Settings rows — the existing dark-gray text (#373a3c, #999) becomes unreadable on dark.
   Lift to the high-contrast foreground for text, muted for inline icons. */
html[data-theme="dark"] #settingsPage > .height,
html[data-theme="dark"] #csettings #settingslist {
  color: var(--cctv-fg);
}
html[data-theme="dark"] #settingsPage > .height i,
html[data-theme="dark"] .poless i { color: var(--cctv-fg-muted); }
html[data-theme="dark"] .settitle,
html[data-theme="dark"] .setpole,
html[data-theme="dark"] #setttitle { color: var(--cctv-fg); }
html[data-theme="dark"] .poless { border-color: var(--cctv-border); }

html[data-theme="dark"] hr { border-color: var(--cctv-border); }

/* ============================================================
   Panel cell fit mode: when the "Видео в полный кадр" setting
   is enabled, video is shown contained (no cropping). We also
   strip any inline background-image placeholder on the cell so
   nothing peeks through the letterbox area around the video.
   ============================================================ */

#camlist.panel-fit-contain > div {
  background: var(--cctv-bg) !important;
}
#camlist.panel-fit-contain > div > video {
  object-fit: contain !important;
}
/* Скриншот-подложка отдельным слоем (см. drawVideo). В обычном режиме он
   заполняет ячейку — ровно как видео с object-fit: cover. */
#camlist > div > .camShot {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  z-index: 0;
  pointer-events: none;
}
/* В режиме полного кадра слой остаётся на всю ячейку, а вписывается САМА
   картинка — contain повторяет object-fit: contain у видео один в один.
   Считать коробку в CSS (width:100% + aspect-ratio) нельзя: у ячейки
   произвольные пропорции, и при широкой ячейке заданная ширина побеждает
   aspect-ratio — скриншот растягивался на всю ячейку, пока видео было
   вписано с полями. */
#camlist.panel-fit-contain > div > .camShot {
  background-size: contain;
}
/* Первый кадр пришёл — подложка не нужна. Признак на самой ячейке, а не на
   соседстве элементов: порядок детей внутри ячейки меняется. */
/* Слой скриншота позиционирован, а <video> — нет, поэтому по правилам покраски
   он лёг бы ПОВЕРХ кадра в окно между первым кадром и классом .hasVideo.
   Поднимаем видео в собственный слой. */
#camlist > div > video { position: relative; z-index: 1; }
#camlist > div.hasVideo > .camShot { display: none; }
/* Скриншот-подложку убираем ТОЛЬКО когда видео уже пошло: тогда поля по бокам
   должны быть фоном темы, а не растянутым кадром. Пока видео нет (подключаемся
   или «Нет сигнала») скриншот остаётся — иначе плашка висит на пустом фоне.
   Так же устроено в десктопе: там Image со скриншотом скрывается по playing. */
#camlist.panel-fit-contain > div > video.hasVideo {
  background: var(--cctv-bg) !important;
  background-size: auto !important;
}

/* ============================================================
   Misc cleanups: thumbnails inside the panel-list cards used
   to have a 1px gray border around every cell — remove it.
   The empty-search placeholder ("Введите запрос…") used to
   hard-code white inline background; force transparent so the
   theme background shows through.
   ============================================================ */

/* Panel-list thumbnails (cards on #panellist) — preserve aspect ratio
   without inner cell borders. */
.panelLink td {
  border: none !important;
  background-size: contain !important;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-color: var(--cctv-bg-deep);
}
/* Schema preview tiles on the "Add panel" page (.typename) — KEEP cell
   borders so the user can see the layout. Use accent color in both
   themes for clarity. */
.typename td {
  border: 1px solid var(--cctv-fg-muted) !important;
}

/* Make the card slightly taller and lock the thumbnail table to its
   original size, so the extra height appears as breathing room above
   the panel name (instead of growing the table and shrinking the gap).
   This keeps fixed-height cell layouts like spec12 visually correct. */
.panelLink {
  height: 215px !important;
}
.panelLink table {
  height: 140px !important;
}
.panelname {
  bottom: 10px !important;
  color: var(--cctv-fg-muted);
}

#searchRes > div.noper {
  background: transparent !important;
  color: var(--cctv-fg-muted) !important;
}

/* "Add panel" page — simplified, mirroring the iOS app:
   name → camera count → 2 mosaic presets → "Добавить" button. */

#addpanelpage {
  max-width: 720px;
  margin: 0 auto;
  padding: 30px 20px;
}
#addpanelpage .inpblock {
  text-align: center;
  margin: 24px auto;
}
#addpanelpage .inpblock label {
  /* main.min.css has .inpblock label { position: absolute } which makes
     the label overlap the input. Force a static block layout so the
     label sits above the input on its own line. */
  position: static !important;
  display: block;
  margin-bottom: 10px;
  line-height: 1.4;
  font-size: 18px;
  font-weight: 400;
  color: var(--cctv-fg) !important;
  text-align: center;
  left: auto;
}
#panelname {
  display: block;
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  padding: 10px 14px;
  font-size: 17px;
  border: 1px solid var(--cctv-border);
  border-radius: 6px;
  background: var(--cctv-bg-elev) !important;
  color: var(--cctv-fg) !important;
  outline: 0;
  text-align: center;
  transition: border-color .15s;
}
#panelname:focus { border-color: var(--cctv-accent); }
#panelname::placeholder {
  color: var(--cctv-fg-muted) !important;
  opacity: 0.6;
}
#panelname::-webkit-input-placeholder {
  color: var(--cctv-fg-muted) !important;
  opacity: 0.6;
}

.addpanelSection {
  text-align: center;
  font-size: 18px;
  font-weight: 400;
  margin: 28px 0 14px;
  color: var(--cctv-fg);
}

/* Number grid (1-16) → type 11. */
#panelCountGrid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: 540px;
  margin: 0 auto;
}
#panelCountGrid > button {
  width: 56px;
  height: 48px;
  font-size: 18px;
  border: 1px solid var(--cctv-border);
  border-radius: 6px;
  background: var(--cctv-bg-elev);
  color: var(--cctv-fg);
  cursor: pointer;
  transition: all .12s;
}
#panelCountGrid > button:hover { border-color: var(--cctv-accent); }
#panelCountGrid > button.selected {
  background: var(--cctv-accent);
  color: #fff;
  border-color: var(--cctv-accent);
}

/* Two non-standard mosaic presets (types 2 and 3). */
.addpanelPresets {
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}
.addpanelPresets label {
  cursor: pointer;
  display: inline-block;
  /* main.min.css forces #addpanelpage :not(.inpblock)>label to 150×150
     with its own 1px border + 10px margin. That outer label-border was
     the "second rectangle" around the typename preview. Strip it. */
  width: 140px !important;
  height: 140px !important;
  margin: 0 !important;
  border: none !important;
  border-radius: 0 !important;
  overflow: visible !important;
}
.addpanelPresets .panelstyle {
  display: none; /* hidden radio, .typename is the click target */
}
/* main.min.css forces .typename to display:table-cell + position:absolute
   plus .typename td to width/min-width/height:45px — these together
   create the "double border" effect (table sized by cell minimums, not
   by container). Normalize the box model so cells split the container
   evenly. */
.addpanelPresets .typename {
  display: block !important;
  position: relative !important;
  width: 140px !important;
  height: 140px !important;
  padding: 0 !important;
  margin: 0 !important;
  border: none !important;
  background: var(--cctv-bg-elev);
  overflow: hidden;
  box-sizing: border-box;
  transition: box-shadow .15s, background .15s;
}
.addpanelPresets label:hover .typename {
  box-shadow: 0 0 0 2px var(--cctv-fg-muted);
}
.addpanelPresets .panelstyle:checked + .typename {
  box-shadow: 0 0 0 2px var(--cctv-accent);
  background: rgba(85, 136, 204, 0.10);
}
.addpanelPresets .typename table {
  position: absolute !important;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  padding: 0 !important;
  margin: 0 !important;
  border-collapse: collapse !important;
  border-spacing: 0 !important;
  table-layout: fixed !important;
}
.addpanelPresets .typename td {
  padding: 0 !important;
  margin: 0 !important;
  border-radius: 0 !important;
  /* Drop the 45px hard-coded width/height that main.min.css forces —
     it makes the table size to fit cells rather than the container, so
     the table renders SMALLER than .typename and a fake outer rect
     appears. Auto lets table-layout:fixed split evenly. */
  width: auto !important;
  min-width: 0 !important;
  height: auto !important;
}

/* Zoom-and-pan: when the user is dragging the zoomed video, swap the
   cursor to "grabbing" for feedback. */
#onlineCamera.cam-panning { cursor: grabbing !important; }

/* Export-mode screenshot preview: when the user drags one of the two
   export markers and releases, the server returns a screenshot for that
   timestamp. We display it on top of the (paused) video, full-bleed,
   so the user immediately sees what frame they picked.
   The element exists already (#preImage created inside #onlineCam);
   main.min.css just gives it 0×0 size — fix that here. */
#preImage {
  position: absolute !important;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  background-size: contain !important;
  background-position: center !important;
  background-repeat: no-repeat !important;
  background-color: #000;
  z-index: 5;
  pointer-events: none;
  /* Hidden by default — JS in core.js sets display:block when a
     screenshot blob arrives, and back to display:none when leaving
     archive/export mode. The plain (non-!important) `display: none`
     here lets the inline style from JS override it. */
  display: none;
}

/* Кнопки плеера теперь полностью описаны в ui-player.css по образцу
   десктопа: в живом режиме светлый круг с тёмной иконкой, в архиве —
   тёмная плашка с белой, включённая — белая заливка с ТЁМНОЙ иконкой.
   Прежние правила отсюда мешали дважды: перекрашивали заливку в серый
   (--cctv-accent вместо чистого белого) и держали иконку белой, из-за
   чего на включённой кнопке она пропадала. Держались на !important,
   поэтому перебить их из ui-player.css было нельзя — удалены. */

/* Old single-color (red) archive marker styling is replaced below by the
   YouTube-style handles. Intentionally empty here so the rule slot
   remains a reference point in the diff. */

/* Joystick / zoom panel — dark theme overrides. The default buttons
   are pure white which feels out of place over dark video; theme them
   to match. */
html[data-theme="dark"] #joystick {
  background: rgba(0, 0, 0, 0.7) !important;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
}
html[data-theme="dark"] #joystick div {
  background: var(--cctv-bg-elev) !important;
  color: var(--cctv-fg);
}
html[data-theme="dark"] #joystick div:hover {
  background: var(--cctv-bg-deep) !important;
}
html[data-theme="dark"] #joystick div i {
  color: var(--cctv-fg);
}
html[data-theme="dark"] #joystickreset {
  background: var(--cctv-accent) !important;
  color: #fff !important;
}
html[data-theme="dark"] #joystickreset:hover {
  filter: brightness(1.15);
}

/* Drag-and-drop reordering in the live panel grid. Click-hold + move
   triggers panel.startDrag; cells highlight as drop targets. */
.cam.cam-dragging {
  opacity: 0.4;
  outline: 2px dashed var(--cctv-accent);
  cursor: grabbing !important;
}
#camlist > div.cam-drop-target {
  outline: 2px solid var(--cctv-accent);
  outline-offset: -2px;
  background-color: rgba(85, 136, 204, 0.15);
}
/* Ghost thumbnail that follows the cursor while dragging. */
.cam-drag-ghost {
  position: fixed !important;
  z-index: 9999;
  pointer-events: none;
  border: 2px solid var(--cctv-accent);
  border-radius: 4px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
  opacity: 0.85;
  background-color: #000;
}

/* Перетаскивание карточек в избранном и приватных — в ui-cards.css:
   там подсветка цели рисуется подложкой карточки, а не рамкой по кадру. */

/* Camera name under each cell in the live panel grid — center it
   horizontally instead of pinning to the bottom-right corner. */
.subname {
  left: 0 !important;
  right: 0 !important;
  text-align: center;
  padding: 0 6px;
  pointer-events: none;
}

/* Global toast container (#toasts) — center the message over the video
   instead of pinning it to top-center of the page. Container itself is
   transparent, only the toast bubble has color, so there's no "black
   backdrop" effect. Clicks pass through. */
#toasts {
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
  background: transparent !important;
  pointer-events: none;
  z-index: 116;
  max-width: 90%;
}
#toasts > div {
  margin: 0 !important;
  padding: 10px 18px !important;
  border-radius: 8px !important;
  font-size: 15px !important;
  text-align: center;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
  white-space: normal !important;
}
#toasts > div.error {
  background: rgba(200, 60, 60, 0.92) !important;
  color: #fff !important;
}
#toasts > div.info {
  background: rgba(40, 40, 40, 0.88) !important;
  color: #fff !important;
}
#toasts > div.success {
  background: rgba(70, 175, 90, 0.92) !important;
  color: #fff !important;
}

/* Per-cell toast (e.g. "Нет сигнала" on a frozen panel camera) — center
   in the cell instead of pinning to top-left. Don't intercept clicks
   so user can still click the underlying tile. */
.selfToast {
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
  margin: 0 !important;
  padding: 8px 14px;
  font-size: 14px;
  text-align: center;
  pointer-events: none;
  max-width: 80%;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
}
.selfToast.error {
  background: rgba(200, 60, 60, 0.85) !important;
}

/* ──────────────────────────────────────────────────────────────────
   Export interval picker (Mark In / Mark Out / range HUD)
   Modeled after UniFi Protect / Eagle Eye Cloud — user marks "[" at
   the in-point and "]" at the out-point while watching the archive.
   The HUD between the bracket buttons and Start Export shows the
   chosen range and current duration.
   ────────────────────────────────────────────────────────────────── */

/* Big readable "[" / "]" glyphs centered inside the 50×50 button the
   same way .videoButton i (material-icons) is centered — absolute +
   transform. Without this the bracket sits on the text baseline and
   visually drops to the bottom of the circle. */
#exportList .markBtn .bracket {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
}

/* "Set" state — once the corresponding marker exists, the bracket
   button stays highlighted so the user knows the mark is committed. */
#exportList .markBtn.set {
  background: var(--cctv-accent, #5588cc) !important;
  color: #fff !important;
}
html[data-theme="dark"] #exportList .markBtn.set {
  background: var(--cctv-accent) !important;
  color: #fff !important;
}

/* The HUD — inline pill between bracket buttons and Start Export.
   Height 50px to match the .videoButton circles (line-height:50 in
   main.css), with flex center so the text doesn't drift to the top of
   the row. Margin matches the buttons' 5px. !important on display
   because main.css's `#exportList.active div` line-height:165% rule
   otherwise wins on equal-id-selectors and breaks vertical centering. */
#exportRange {
  display: inline-flex !important;
  align-items: center;
  gap: 4px;
  padding: 0 12px 0 14px;
  margin: 5px;
  height: 50px;
  min-width: 0;
  font-size: 13px;
  line-height: 1;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, 0.35);
  color: #fff;
  border-radius: 25px;
  white-space: nowrap;
  user-select: none;
  vertical-align: top;
  box-sizing: border-box;
}
/* Each text slot gets a deterministic width so dragging a marker
   (which mutates the time strings every frame) doesn't reflow the
   pill and shift the surrounding toolbar icons. tabular-nums on the
   container keeps digit glyphs uniform width inside the slots. */
#exportRange #exportRangeStart,
#exportRange #exportRangeEnd {
  display: inline-block;
  min-width: 70px;
  text-align: center;
  cursor: text;
  padding: 2px 3px;
  border-radius: 4px;
  transition: background 0.15s;
  box-sizing: border-box;
  font-size: 12px;
}
#exportRange #exportRangeStart:hover,
#exportRange #exportRangeEnd:hover {
  background: rgba(255, 255, 255, 0.08);
}
/* While editing, the span is replaced by an inline input. The input
   keeps the same monospace tabular-nums look so it doesn't jump in
   size when the user types. */
#exportRange input.timeEdit {
  width: 70px;
  min-width: 70px;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: 1px solid var(--cctv-accent, #5588cc);
  border-radius: 4px;
  padding: 2px 3px;
  font: inherit;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  outline: none;
}
#exportRange .sep { width: 12px; text-align: center; font-size: 12px; }
#exportRange .dur {
  display: inline-block;
  min-width: 52px;
  text-align: right;
  font-size: 12px;
  font-weight: 600;
  color: var(--cctv-accent, #5588cc);
  margin-left: 2px;
}
#exportRange .sep { opacity: 0.6; }
#exportRange .dur.over { color: #e26060; }
/* No display:none on empty .dur — that would collapse the width slot
   and re-introduce the pill jiggling we just fixed. We show an
   invisible placeholder when duration is 0 so the width holds. */
html[data-theme="dark"] #exportRange {
  background: var(--cctv-bg-elev) !important;
  color: var(--cctv-fg) !important;
}

/* Start Export button — always keeps a solid circular background (like
   the other controls) so it never dissolves into the camera image.
   When disabled (no valid range) we dim ONLY the icon, not the whole
   button — opacity on the button itself made the circle ~transparent
   and it blended with the video behind it. */
#exportList #btnStartExport {
  background: var(--cctv-bg-elev, #fff) !important;
  box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.45);
}
#exportList #btnStartExport.disabled {
  cursor: not-allowed;
  pointer-events: none;
}
#exportList #btnStartExport.disabled i {
  opacity: 0.35;
}

/* Compact the bracket buttons a touch — they're already legible. */
#exportList .markBtn {
  text-align: center;
}

/* ──────────────────────────────────────────────────────────────────
   Range markers on the archive timeline
   The existing main.css renders archiveStart/archiveEnd as 107px
   tall handles with triangle caps that float above the timeline.
   We don't restyle the geometry — that fights vis-timeline's
   internal positioning and shifts the whole axis. Instead just
   recolor: green for start, red for end, so the user can tell the
   two ends apart. The triangle caps in main.css use border-color so
   we override those rules per marker.
   ────────────────────────────────────────────────────────────────── */

/* Start marker (in-point) — green */
.archiveStart {
  background: rgba(76, 175, 80, 0.78) !important;
}
.archiveStart::before {
  border-right-color: rgba(76, 175, 80, 0.78) !important;
}

/* End marker (out-point) — red (slightly cleaner than the legacy red) */
.archiveEnd {
  background: rgba(255, 82, 82, 0.85) !important;
}
.archiveEnd::before {
  border-left-color: rgba(255, 82, 82, 0.85) !important;
}

/* The export_interval item is kept (the drag logic reads its start to
   move both flags together) but rendered INVISIBLE. vis-timeline drew
   it as a stray ~10px horizontal stripe between the markers, not the
   intended full-height highlight — and the green/red flags already
   bracket the range, so the tint was redundant noise. Transparent +
   no border = nothing shows. */
.exportinterval {
  background-color: transparent !important;
  border: none !important;
}
html[data-theme="dark"] .exportinterval {
  background-color: transparent !important;
}

/* ──────────────────────────────────────────────────────────────────
   Login form (login_form.css) — dark theme.
   The card was missed in the original dark-theme pass, so it rendered
   as a bright white box on the navy background. Recolor the card,
   inputs, labels, links and buttons to the dark palette. login_form.css
   sorts before theme.css in main.min.css, so these rules win.
   ────────────────────────────────────────────────────────────────── */

html[data-theme="dark"] .loginblock {
  background-color: var(--cctv-bg-elev);
  box-shadow: 0 0 0.3vw 0.1vw rgba(0, 0, 0, 0.5);
  border: 1px solid var(--cctv-border);
}

/* Heading — keep the brand-blue feel with the vivid dark accent. */
html[data-theme="dark"] .loginblock .header {
  color: var(--cctv-accent);
}

/* Field labels ("Введите логин/пароль"). */
html[data-theme="dark"] .loginblock .inputfield .title {
  color: var(--cctv-fg-muted);
}

/* Inputs — give them a slightly deeper surface so the field reads on
   the elevated card, with off-white text and a visible border. */
html[data-theme="dark"] .loginblock .inputfield input {
  background-color: var(--cctv-bg-deep);
  color: var(--cctv-fg);
  border-color: var(--cctv-border);
}
html[data-theme="dark"] .loginblock .inputfield input:focus {
  border-color: var(--cctv-accent);
}

/* Browser autofill paints its own pale-yellow/lavender background and
   dark text. Override both: inset box-shadow repaints the field's dark
   surface, text-fill-color keeps the typed value off-white. */
html[data-theme="dark"] .loginblock .inputfield input:-webkit-autofill,
html[data-theme="dark"] .loginblock .inputfield input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--cctv-fg) !important;
  -webkit-box-shadow: 0 0 0 1000px var(--cctv-bg-deep) inset !important;
  box-shadow: 0 0 0 1000px var(--cctv-bg-deep) inset !important;
  caret-color: var(--cctv-fg);
}

/* Password eye icon — muted by default, accent when toggled on. */
html[data-theme="dark"] .loginblock .inputfield .passwordeye {
  background-color: var(--cctv-fg-muted);
}
html[data-theme="dark"] .loginblock .inputfield .passwordeye[data-checked='true'] {
  background-color: var(--cctv-accent);
}

/* "Не помню пароль" / "ЗАРЕГИСТРИРОВАТЬСЯ" links. */
html[data-theme="dark"] .loginblock .passwordhelp,
html[data-theme="dark"] .loginblock .btn.registercctv {
  color: var(--cctv-link);
}

/* Primary "ВОЙТИ" action. */
html[data-theme="dark"] .loginblock .btn.entercctv {
  color: var(--cctv-fg);
}

/* ──────────────────────────────────────────────────────────────────
   Статус ячейки панели: «подключаюсь» и «нет сигнала».

   Заменяет прежний тост «Нет сигнала», который исчезал сам через
   несколько секунд и появлялся заново на каждой неудачной попытке —
   ячейка мигала. Лоадер показывается только до первого решения;
   дальше висит плашка, пока не пойдёт кадр (см. panelCellStatus).
   ────────────────────────────────────────────────────────────────── */
#camlist > div { position: relative; }

.cellStatus {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;   /* клик по ячейке должен проходить насквозь */
  z-index: 5;
}

/* Ожидание — та же плашка, что и «Нет сигнала», только приглушённая: единый
   язык вместо «крутилка, потом надпись». */
.cellStatus {
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(40, 44, 52, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

/* Точки: место под все три зарезервировано, меняется только яркость —
   поэтому плашка не дёргается по ширине. */
.cellStatus .dots { display: inline-flex; gap: 3px; margin-left: 2px; }
.cellStatus .dots i {
  width: 3px; height: 3px; border-radius: 50%;
  background: #ffffff; opacity: 0.25;
  animation: cellStatusDot 1.2s infinite;
}
.cellStatus .dots i:nth-child(2) { animation-delay: 0.2s; }
.cellStatus .dots i:nth-child(3) { animation-delay: 0.4s; }

@keyframes cellStatusDot {
  0%, 70%, 100% { opacity: 0.25; }
  35%           { opacity: 1; }
}

/* У «Нет сигнала» точек нет: решение принято, ждать нечего. */
.cellStatus.nosignal .dots { display: none; }

.cellStatus.nosignal {
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(200, 51, 51, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.25);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
}

.cellStatus .txt {
  color: #ffffff;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

/* История поиска в разделе «Поиск». Цвета — через переменные темы, чтобы
   строки читались и в тёмном оформлении. Заголовок помечен .noper: это
   служебная строка, кликать по ней нечего (и подсветки при наведении у неё
   нет — правило #searchRes>div:hover перекрываем явно). */
#searchRes > div.searchHistHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px;
  color: var(--cctv-fg-muted, #6b6f76);
  cursor: default;
  border-bottom: 1px solid var(--cctv-border, rgba(0, 0, 0, 0.08));
}
/* Правило #searchRes>div span{font-size:0.7em} сделано для «(адреса)» в
   выдаче — строки истории оно мельчит. Возвращаем им обычный размер: текст
   запроса такой же, как названия камер рядом, подписи чуть меньше. */
#searchRes > div.searchHistHead span { font-size: 13px; }
#searchRes > div.searchHistItem span.searchHistText {
  font-size: 1em;
  font-weight: 100;
  color: inherit;
}
#searchRes > div.searchHistItem span.searchHistDel { font-size: 15px; }
#searchRes > div.searchHistHead:hover { background: none; }
.searchHistClear {
  cursor: pointer;
  text-decoration: underline;
  color: var(--cctv-link, #2e81b7);
}
#searchRes > div.searchHistItem {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.searchHistDel {
  color: var(--cctv-fg-muted, #9a9a9a);
  font-size: 13px;
  padding: 0 4px;
  flex: 0 0 auto;
}
.searchHistDel:hover { color: var(--cctv-fg, #1f1f1f); }

/* Крестик очистки в строке поиска. Место под него уже есть: у #search
   padding 40px справа — тот же отступ, что под лупой слева. */
#searchClear {
  position: absolute;
  right: 30px;
  top: 28px;
  display: none;
  font-size: 18px;
  line-height: 1;
  padding: 2px 4px;
  color: #bbbbbb;
  cursor: pointer;
  user-select: none;
}
#searchClear:hover { color: var(--cctv-fg, #444444); }




/* Списки камер по образцу десктоп-клиента
 * (../desktop_app: qml/components/CameraList.qml, CameraCard.qml, PageHeader.qml).
 *
 * Отдельный файл, а не дописывание в ui.css: экраны переносятся параллельно,
 * и разводить их по файлам дешевле, чем сводить правки в одном. Сборщик
 * (tools/build.sh) склеивает css по алфавиту, поэтому ui-cards.css встаёт
 * после main.css и theme.css (перебивает старую плитку) и до ui.css.
 *
 * Разбор и план — docs/desktop-look-port.md.
 */

/* ── Каркас раздела ─────────────────────────────────────────────────────
 * Шапка не уезжает при прокрутке: в десктопе PageHeader прибит к верху, а
 * список живёт во Flickable под ним. Сам .pageHeader описан в ui.css.
 */
.pageWrap {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.pageWrap > .pageHeader {
    flex: none;
}

/* ── Сетка карточек ─────────────────────────────────────────────────────
 * Колонок столько, сколько влезает вокруг целевых 300 px, остаток делится
 * поровну. auto-fill даёт ровно ту же формулу, что CameraList.qml:
 * floor((доступная ширина + зазор) / (300 + зазор)).
 * Раньше плитка была фиксированной (360×270), и на широком окне ряд висел
 * по центру с пустыми полями по краям.
 */
.sList {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
    gap: 16px;
    align-content: start;
    padding: 0;
    /* main.css гасил здесь шрифт (font-size:0), чтобы убрать зазоры между
       inline-block плитками. В гриде зазор задаёт gap, текст снова нужен. */
    font-size: 14px;
}

/* Поля страницы — как у шапки: содержимое выравнено по её заголовку.
   Снизу 40 px, чтобы последний ряд не упирался в край (contentHeight
   в CameraList.qml — flow.height + 40). */
.camGrid {
    padding: 0 var(--page-pad) var(--page-pad);
}

.pageWrap > .sList {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    overflow: auto;
}

/* ── Карточка ───────────────────────────────────────────────────────────
 * Кадр 16:9 со скруглением, под ним название и адрес. Подпись поверх кадра
 * (как было) всегда с ним спорит: ночью её не видно на светлом потолке,
 * днём — наоборот.
 */
.sList > .camCard {
    position: relative;
    width: auto;
    height: auto;
    margin: 0;
    cursor: pointer;
    background-repeat: no-repeat;
    /* Кадр висит фоном на КОРНЕ карточки, а рисует его .camCard-thumb через
       background-image:inherit. Так остальной код — пересъёмка превью
       (uPersonal.refreshShot) и призрак перетаскивания — по-прежнему читает и
       пишет tile.style.backgroundImage и про вёрстку карточки ничего не знает.
       Сам корень картинку не рисует: фон нулевого размера не отрисовывается. */
    background-size: 0 0;
}

/* Подложка наведения и выделения — с запасом вокруг карточки, чтобы кадр не
   упирался в её край. Зазор сетки 16 > 2×6, поэтому подложки не смыкаются. */
.camCard::before {
    content: "";
    position: absolute;
    inset: -6px;
    border: 2px solid transparent;
    border-radius: 12px;
    pointer-events: none;
    transition: background-color var(--t-fast) linear,
                border-color var(--t-fast) linear;
}

.camCard:hover::before {
    background-color: var(--nav-hover-bg);
}

.camCard-thumb {
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    background-image: inherit;
    background-color: var(--bg-elev);
    background-size: cover;
    background-position: center;
}

html[data-theme="dark"] .camCard-thumb {
    background-color: var(--bg-deep);
}

/* Высота подписи ровно 46 px: 8 + 20 + 2 + 16. Вместе с кадром это и есть
   высота карточки из CameraCard.qml (thumbHeight + 46). */
.camCard-name,
.camCard-addr {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.camCard-name {
    margin-top: 8px;
    height: 20px;
    line-height: 20px;
    font-size: 14px;
    color: var(--fg);
}

.camCard-addr {
    margin-top: 2px;
    height: 16px;
    line-height: 16px;
    font-size: 12px;
    color: var(--fg-muted);
}

/* ── Пустое состояние ───────────────────────────────────────────────────
 * Текст по центру свободной площади. :has() тут не обязателен: без него
 * строка просто встанет сверху, оставшись читаемой.
 */
.camGrid-empty {
    grid-column: 1 / -1;
    text-align: center;
    font-size: 16px;
    color: var(--fg-muted);
}

.sList:has(> .camGrid-empty) {
    align-content: center;
}

/* ── Перетаскивание плиток (избранное, приватные) ───────────────────────
 * Цель обводится той же подложкой, что и наведение, — рамка по самому кадру
 * (как было в theme.css) резала скруглённый угол превью.
 */
.camCard.reorder-dragging {
    opacity: .35;
    cursor: grabbing;
}

.camCard.reorder-drop-target::before {
    border-color: var(--accent);
}

/* Призрак за курсором — 180×101, как в CameraList.qml. Свой класс, а не
   общий .cam-drag-ghost: у сетки панели призрак другого размера. */
.camCard-ghost {
    position: fixed;
    z-index: 9999;
    box-sizing: border-box;
    width: 180px;
    height: 101px;
    border: 2px solid var(--accent);
    border-radius: 8px;
    opacity: .9;
    pointer-events: none;
    background-color: var(--bg-deep);
    background-size: cover;
    background-position: center;
}




/* Настройки и общий «хром» интерфейса по образцу десктоп-клиента.
 *
 * Эталон — ../desktop_app: qml/pages/SettingsPage.qml, qml/components/
 * SettingsSwitch.qml, ToastLayer.qml, ModalLayer.qml, ContextMenu.qml,
 * ContextMenuItem.qml, CalendarPopup.qml. Размеры и тексты перенесены
 * оттуда один в один.
 *
 * Почему отдельный файл, а не дописка в ui.css: ui.css собирает оболочку
 * (токены, шрифт, боковая панель, вход, шапка раздела) и его параллельно
 * правят другие экраны. Сборщик (tools/build.sh) склеивает css по имени,
 * и "ui-chrome.css" встаёт между theme.css и ui.css — этого достаточно,
 * чтобы перебить main.css и theme.css, и при этом не мешать ui.css.
 *
 * Про !important и лишние `html` в селекторах. Старые правила живут в
 * main.css (по id) и в theme.css (`html[data-theme="dark"] #id`, местами
 * с !important). Специфичность id+атрибут+тег выше, чем у голого id,
 * поэтому базовые правила здесь пишутся как `html #modal.uiModal` —
 * та же специфичность, но позже в каскаде. Там, где в theme.css стоит
 * !important, он повторён и здесь. Всё это уйдёт вместе с theme.css.
 *
 * Свои цвета не вводятся: всё из токенов ui.css. Полупрозрачные оттенки
 * десктопа (трек переключателя, подсветка danger) собираются color-mix
 * из тех же токенов; перед каждым таким объявлением стоит запасное на
 * случай движка без color-mix.
 */

/* ══ Настройки: страница ══════════════════════════════════════════════
 * SettingsPage.qml: заголовок раздела, ниже колонка x:40 шириной
 * min(width−80, 1120) и карточки во Flow с зазором 24.
 */

/* Две колонки при ширине СТРАНИЦЫ ≥ 1104 (десктоп: 2×500 + 24 + 80).
 * В вебе ширина страницы — это #setPage, а не окно: слева стоит меню
 * 248/76 px, и медиазапрос по окну промахивался бы на свёрнутом меню.
 * Отсюда контейнерный запрос: 1104 − поля 80 = 1024 по контенту. */
#setPage {
    container-type: inline-size;
    padding: 0 var(--page-pad) 96px;
    box-sizing: border-box;
}

.setCards {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 24px;
    max-width: 1120px;
}

.setCard {
    box-sizing: border-box;
    width: 100%;
    /* В одну колонку карточка шире: maxCardWidth + 60. */
    max-width: 560px;
    padding: 22px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--bg);
}

html[data-theme="dark"] .setCard {
    background: var(--bg-elev);
}

@container (min-width: 1024px) {
    .setCard {
        width: calc((100% - 24px) / 2);
        max-width: 500px;
    }
}

.setCardHead {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Column spacing 12 между шапкой карточки и её телом. */
    margin-bottom: 12px;
}

.setCardHead .icon {
    color: var(--fg-muted);
}

.setCardHead h2 {
    margin: 0;
    font-size: 17px;
    font-weight: 500;
    line-height: 20px;
    color: var(--fg);
}

.setCardBody {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* ── Строка «подпись → значение» (InfoRow) ───────────────────────────── */
.setInfo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: 34px;
}

.setInfoLabel {
    flex: none;
    font-size: 14px;
    color: var(--fg-muted);
}

.setInfoValue {
    min-width: 0;
    font-size: 15px;
    color: var(--fg);
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Пояснение под строкой настройки ─────────────────────────────────
 * Почему настройка не может работать (разрешение браузера на уведомления
 * отозвано или запрещено). Появляется редко, поэтому не «карточка в
 * карточке», а строка текста с отбивкой слева — как подсказка под
 * переключателем, только заметнее.
 */
.setNote {
    padding: 8px 10px;
    border-left: 2px solid var(--fg-muted);
    border-radius: 0 6px 6px 0;
    background: color-mix(in srgb, var(--fg) 6%, transparent);
    font-size: 13px;
    line-height: 17px;
    color: var(--fg-muted);
}

/* ── Строка-переключатель (ToggleRow) ────────────────────────────────── */
.setToggle {
    display: flex;
    align-items: center;
    min-height: 44px;
    /* height = max(44, тексты + 12) — поля по 6 сверху и снизу. */
    padding: 6px 0;
    box-sizing: border-box;
}

.setToggleText {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-right: 16px;
}

.setToggleLabel {
    font-size: 15px;
    line-height: 18px;
    color: var(--fg);
}

.setToggleHint {
    font-size: 13px;
    line-height: 16px;
    color: var(--fg-muted);
}

/* ── Переключатель (SettingsSwitch.qml) ──────────────────────────────
 * Габарит 42×22: трек 42×12 радиусом 6 по центру, кружок 22×22 радиусом
 * 11 выступает над треком на 5 px сверху и снизу — характерная «гантель».
 * Остаётся <input type=checkbox>: на .checked завязаны взаимоисключения
 * «Растягивать»/«Заполнять» в cSettings.prms.
 */
.uiSwitch {
    position: relative;
    top: 0;
    flex: none;
    width: 42px;
    height: 22px;
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}

/* Перебиваем старые правила ширины/обтекания из main.css (#csettings
   .switchSettings{float:right;width:45px}); класс .switch с элемента снят,
   но .switchSettings нужен коду выборок по настройкам. */
#csettings .uiSwitch,
.setToggle .uiSwitch {
    float: none;
    width: 42px;
    margin-top: 0;
}

/* Трек */
.uiSwitch::before {
    content: "";
    position: absolute;
    top: 5px;
    left: 0;
    display: block;
    width: 42px;
    height: 12px;
    border: 0;
    border-radius: 6px;
    background: var(--border);
    background: color-mix(in srgb, var(--fg) 16%, transparent);
    transition: background-color 200ms linear;
}

html[data-theme="dark"] .uiSwitch::before {
    background: color-mix(in srgb, var(--fg) 18%, transparent);
}

.uiSwitch:checked::before {
    background: var(--nav-active-bg);
    background: color-mix(in srgb, var(--accent) 40%, transparent);
}

/* Кружок */
.uiSwitch::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    width: 22px;
    height: 22px;
    border-radius: 11px;
    background: var(--fg-muted);
    transition: left 200ms var(--ease), background-color 200ms linear;
}

.uiSwitch:checked::after {
    left: 20px;
    background: var(--accent);
}

.uiSwitch:focus-visible::after {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ── Сегментный переключатель темы ───────────────────────────────────
 * Три варианта — переключатель, а не выпадающий список: все состояния
 * видны сразу и выбираются одним нажатием (SettingsPage.qml, Segmented).
 */
.setSeg {
    display: flex;
    height: 36px;
    padding: 3px;
    box-sizing: border-box;
    /* Рамку рисуем тенью внутрь, а не border: при border-box она съедала 2 px
       высоты, внутреннего места оставалось 28 против 30 у сегмента, и
       выбранный сегмент висел со смещением — 4 px сверху, 2 снизу. В QML
       рамка тоже рисуется внутрь и на раскладку не влияет. */
    border: 0;
    box-shadow: inset 0 0 0 1px var(--border);
    border-radius: 9px;
    background: var(--bg-elev);
}

html[data-theme="dark"] .setSeg {
    background: var(--bg-deep);
}

.setSegItem {
    /* Дробные ширины (446/3) складываются ровно во внутреннюю ширину, поэтому
       ничего не выпирает и подрезать контейнер не нужно: подрезка срезала
       скругления самого сегмента об угол рамки. */
    flex: 1 1 0;
    min-width: 0;
    height: 30px;
    margin: 0;
    padding: 0 4px;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 7px;
    background: transparent;
    font-family: inherit;
    font-size: 14px;
    font-weight: 400;
    color: var(--fg-muted);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

.setSegItem:hover {
    background: var(--nav-hover-bg);
}

.setSegItem[aria-checked="true"] {
    border-color: var(--border);
    background: var(--bg);
    font-weight: 500;
    color: var(--fg);
}

html[data-theme="dark"] .setSegItem[aria-checked="true"] {
    background: var(--nav-active-bg);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* ── Кнопка выхода ──────────────────────────────────────────────────── */
.setExit {
    width: 150px;
    height: 38px;
    margin-top: 6px;
    padding: 0;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: transparent;
    font-family: inherit;
    font-size: 14px;
    color: var(--fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

.setExit:hover {
    background: var(--nav-active-bg);
}

/* ══ Настройки: оверлей в плеере (#csettings) ═════════════════════════
 * Тех же карточек, что на странице, но по центру экрана: в десктопе
 * настройки из плеера не открываются, поэтому вид собран из общих правил.
 */
html #csettings.uiSettingsOverlay {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1050;
    display: none;
    background: transparent !important;
    color: var(--fg);
    font-weight: 400;
}

html #csettings.uiSettingsOverlay.active {
    display: block;
}

html #csettings.uiSettingsOverlay .csettingsback {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: block;
    /* Затемнение ModalLayer.qml. */
    background: rgba(0, 0, 0, .35);
}

html #csettings.uiSettingsOverlay #settingsbody {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 420px;
    max-width: calc(100vw - 32px);
    max-height: calc(100vh - 64px);
    overflow: auto;
    padding: 22px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--bg);
}

html[data-theme="dark"] #csettings.uiSettingsOverlay #settingsbody {
    background: var(--bg-elev) !important;
}

html #csettings.uiSettingsOverlay #setttitle {
    position: static;
    display: block;
    width: auto;
    margin: 0 0 16px;
    /* main.css выравнивает #setttitle по центру — здесь это заголовок окна
       над разделами, он должен стоять слева, как в карточках. */
    text-align: left;
    font-size: 22px;
    font-weight: 500;
    color: var(--fg);
}

html #csettings.uiSettingsOverlay #settingFrameClose {
    position: absolute;
    top: 16px;
    right: 16px;
    z-index: 2;
    width: 28px;
    height: 28px;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

html #csettings.uiSettingsOverlay #settingFrameClose:hover {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

html #csettings.uiSettingsOverlay #settingslist {
    width: auto !important;
    max-width: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
    border-radius: 0;
    background: transparent;
    font-size: 14px;
    line-height: normal;
    color: var(--fg);
}

/* Карточка в карточке смотрелась бы вложенной коробкой: внутри оверлея
   у разделов остаются только шапка и тело. */
html #csettings.uiSettingsOverlay .setCard {
    width: auto;
    max-width: none;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
}

/* ══ Тосты (ToastLayer.qml) ═══════════════════════════════════════════
 * Стопка в правом верхнем углу. Внизу они стоять не могут: там ряд
 * круглых кнопок плеера и полоса архива — сообщение садилось прямо на то,
 * чем в этот момент управляют.
 */
html #toasts.uiToasts {
    position: fixed;
    top: 24px !important;
    right: 24px;
    bottom: auto;
    left: auto !important;
    z-index: 1000;
    transform: none;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
    max-width: calc(100vw - 60px);
    background: transparent !important;
    pointer-events: none;
}

html #toasts.uiToasts > .uiToast {
    position: relative;
    box-sizing: border-box;
    min-width: 260px;
    max-width: 100%;
    min-height: 52px;
    margin: 0 !important;
    /* 18 слева до текста, справа 48 = зазор 10 + крестик 28 + поле 10.
       Ширина плашки набирается содержимым, как metrics.width + 86 в
       эталоне; крестик вынут из потока, иначе его 28 px растягивали бы
       плашку до 58 вместо 52. */
    padding: 14px 48px 14px 18px !important;
    display: flex;
    align-items: center;
    border: 1px solid var(--border);
    border-radius: 12px !important;
    /* В эталоне у плашки только рамка — тень прежних тостов из theme.css
       выдавала бы её за всплывающее окно. */
    box-shadow: none;
    background: var(--bg) !important;
    font-size: 14px !important;
    line-height: 18px;
    text-align: left;
    color: var(--fg) !important;
    white-space: normal !important;
    pointer-events: auto;
    animation: uiToastFade 160ms linear both, uiToastSlide 180ms var(--ease) both;
}

html[data-theme="dark"] #toasts.uiToasts > .uiToast {
    background: var(--bg-elev) !important;
}

/* Цветная полоса слева: тип сообщения виден мгновенно, а заливать всю
   плашку цветом нельзя — читать длинный текст на ней тяжелее. */
html #toasts.uiToasts > .uiToast::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 4px;
    border-radius: 2px;
    background: var(--accent);
}

html #toasts.uiToasts > .uiToast.success::before {
    background: var(--ok);
}

html #toasts.uiToasts > .uiToast.error::before {
    background: var(--err);
}

html #toasts.uiToasts > .uiToast .uiToastText {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: break-word;
}

html #toasts.uiToasts > .uiToast .uiToastText a {
    color: var(--link);
}

html #toasts.uiToasts > .uiToast .uiToastClose {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: color var(--t-fast) linear;
}

html #toasts.uiToasts > .uiToast .uiToastClose:hover {
    color: var(--fg);
}

@keyframes uiToastFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes uiToastSlide {
    from { transform: translateX(24px); }
    to   { transform: none; }
}

/* ══ Модальные окна (ModalLayer.qml) ══════════════════════════════════ */
#modalBack {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1099;
    display: none;
    /* Затемнение ModalLayer.qml. */
    background: rgba(0, 0, 0, .35);
    opacity: 0;
    transition: opacity 150ms linear;
}

#modalBack.active {
    display: block;
    opacity: 1;
}

html #modal.uiModal {
    position: fixed;
    top: -400px;
    left: 50%;
    z-index: 1100;
    transform: translateX(-50%);
    width: 320px;
    max-width: calc(100vw - 32px);
    box-sizing: border-box;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-elev);
    box-shadow: none;
    color: var(--fg);
    opacity: 0;
    transition: top 200ms var(--ease), opacity 150ms linear;
}

html #modal.uiModal.active {
    top: 100px;
    opacity: 1;
}

html #modal.uiModal #modal-text {
    min-height: 0;
    padding: 20px 20px 16px;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
    line-height: 20px;
    color: var(--fg);
    overflow-wrap: break-word;
}

html #modal.uiModal .uiModalInput {
    display: block;
    width: 100%;
    height: 40px;
    margin-top: 16px;
    padding: 0 10px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg-deep);
    font-family: inherit;
    font-size: 15px;
    color: var(--fg);
    outline: 0;
}

html #modal.uiModal .uiModalInput:focus {
    border-color: var(--accent);
}

html #modal.uiModal #modal-buttons {
    display: flex;
    width: auto;
    height: 50px;
}

html #modal.uiModal #modal-buttons > div {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: auto;
    border: 0;
    line-height: normal;
    font-size: 15px;
    color: var(--fg);
    cursor: pointer;
    user-select: none;
    transition: background-color var(--t-fast) linear;
}

html #modal.uiModal #modal-buttons > div + div {
    border-left: 1px solid var(--border);
}

html #modal.uiModal #modal-buttons > div:hover {
    background: var(--bg-deep);
}

html #modal.uiModal #modal-buttons > div.uiBtnPrimary {
    font-weight: 500;
    color: var(--accent);
}

html #modal.uiModal #modal-buttons > div.uiBtnDanger {
    font-weight: 500;
    color: var(--err);
}

/* ══ Контекстное меню (ContextMenu.qml + ContextMenuItem.qml) ═════════ */
html #context.uiMenu {
    position: fixed;
    z-index: 1200;
    display: none;
    height: auto;
    min-width: 240px;
    max-width: 420px;
    padding: 6px;
    box-sizing: border-box;
    overflow: visible;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--bg);
    /* Тень десктопного попапа рисует оконная система; здесь — мягкая
       замена вместо прежней жёсткой «2px 3px 3px 2px rgba(0,0,0,.6)». */
    box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
    font-size: 15px;
    color: var(--fg);
}

html[data-theme="dark"] #context.uiMenu {
    background: var(--bg-elev) !important;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

html #context.uiMenu.active {
    display: block;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
}

html[data-theme="dark"] #context.uiMenu.active {
    box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

html #context.uiMenu > div {
    position: relative;
    /* Поля пункта 20 = 4 (подсветка inset) + 16 (внутри подсветки). */
    padding: 0 4px;
    border: 0;
    background: transparent;
    font-weight: 400;
}

/* Разделитель между пунктами — но не перед первым. */
html #context.uiMenu > div + div::before {
    content: "";
    position: absolute;
    top: 0;
    right: 12px;
    left: 12px;
    height: 1px;
    background: var(--border);
}

html #context.uiMenu > div > .uiMenuLabel {
    display: flex;
    align-items: center;
    height: 40px;
    padding: 0 16px;
    border-radius: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: background-color var(--t-fast) linear;
}

html #context.uiMenu > div:hover > .uiMenuLabel {
    background: var(--nav-hover-bg);
}

html #context.uiMenu > div.redcontext {
    background: transparent;
    color: var(--err);
}

html #context.uiMenu > div.redcontext:hover {
    background: transparent;
}

html #context.uiMenu > div.redcontext:hover > .uiMenuLabel {
    background: var(--nav-hover-bg);
    background: color-mix(in srgb, var(--err) 15%, transparent);
}

/* Заголовок группы: в десктопе таких пунктов нет, в вебе ими подписаны
   камеры. Не кликается и не подсвечивается. */
html #context.uiMenu > div.title {
    background: transparent;
    cursor: default;
    color: var(--fg-muted);
}

html #context.uiMenu > div.title > .uiMenuLabel {
    height: 34px;
    font-size: 13px;
    background: transparent;
}

/* ══ Календарь (CalendarPopup.qml) ════════════════════════════════════
 * Карточка 280 радиусом 8: поля 14 и семь ячеек по 36 дают ровно 280.
 */
html #mCalendar.uiCal {
    position: fixed;
    z-index: 1150;
    display: none;
    width: 280px;
    padding: 14px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--bg);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
    font-size: 13px;
    color: var(--fg);
}

html[data-theme="dark"] #mCalendar.uiCal {
    background: var(--bg-elev) !important;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

html #mCalendar.uiCal.active {
    display: block;
}

html #mCalendar.uiCal #m_cont {
    display: flex;
    align-items: center;
    width: auto;
    height: 28px;
    font-size: 15px;
    color: var(--fg);
}

html #mCalendar.uiCal #m_cont > div {
    display: block;
    max-height: none;
    padding: 0;
    line-height: normal;
}

html #mCalendar.uiCal #month_left,
html #mCalendar.uiCal #month_right {
    flex: none;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--fg);
    cursor: pointer;
}

html #mCalendar.uiCal #m_month {
    flex: 1 1 auto;
    text-align: center;
    font-size: 15px;
    font-weight: 500;
    color: var(--fg);
}

html #mCalendar.uiCal #m_daysw {
    display: flex;
    margin-top: 8px;
    border-bottom: 0;
}

html #mCalendar.uiCal #m_daysw > div {
    flex: none;
    width: 36px;
    height: 20px;
    line-height: 20px;
    font-size: 11px;
    text-align: center;
    color: var(--fg-muted);
    user-select: none;
}

html #mCalendar.uiCal #m_days {
    display: flex;
    flex-wrap: wrap;
    width: 252px;
    margin-top: 8px;
}

html #mCalendar.uiCal #m_days > div {
    flex: none;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    line-height: normal;
    color: var(--fg);
    background: none;
    user-select: none;
}

/* Кружок дня: 30×30 радиусом 15 внутри ячейки 36. */
html #mCalendar.uiCal #m_days > div > span {
    position: relative;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 15px;
    transition: background-color var(--t-fast) linear;
}

html #mCalendar.uiCal #m_days > div:not(.unactive) {
    cursor: pointer;
}

html #mCalendar.uiCal #m_days > div:not(.unactive):hover {
    background: none;
    color: var(--fg);
}

html #mCalendar.uiCal #m_days > div:not(.unactive):hover > span {
    background: var(--nav-active-bg);
}

html #mCalendar.uiCal #m_days > div.today > span {
    border-color: var(--accent);
}

html #mCalendar.uiCal #m_days > div.selday > span,
html #mCalendar.uiCal #m_days > div.selday:hover > span {
    border-color: transparent;
    background: var(--accent);
    color: var(--accent-fg);
}

html #mCalendar.uiCal #m_days > div.unactive {
    color: var(--fg-muted);
    opacity: .45;
}

/* Точка «в этот день есть архив» — 4×4 внизу кружка. У выбранного дня
   её не рисуем: на залитом кружке она читается как грязь. */
html #mCalendar.uiCal #m_days > div.hasArchive > span::after {
    content: "";
    position: absolute;
    bottom: 3px;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 2px;
    background: var(--accent);
}

html #mCalendar.uiCal #m_days > div.selday.hasArchive > span::after {
    display: none;
}




/* Детекция людей — экран событий поверх плеера, по образцу десктопа
 * (../desktop_app/qml/components/DetectionsOverlay.qml).
 *
 * Отдельный файл, а не дописывание в ui.css: экраны переносятся параллельно
 * разными руками, и разводить их по файлам дешевле, чем сводить правки в
 * одном. Сборщик (tools/build.sh) склеивает css по алфавиту, поэтому этот
 * файл встаёт после main.css/theme.css (перебивает старое) и ДО ui-player.css
 * — всё, что спорит с правилами плеера, пишется селектором с запасом по весу
 * (см. #closeCam и #btnDetection ниже).
 *
 * Разбор и план — docs/desktop-look-port.md.
 */

:root {
    /* Выделенная строка события — акцент 16 %, как в DetectionsOverlay.qml.
       Токена «акцент с прозрачностью» в ui.css нет, а сам акцент монохромный,
       поэтому значение раскрыто здесь и переопределено для тёмной темы. */
    --det-row-sel: rgba(28, 30, 33, .16);
}

html[data-theme="dark"] {
    --det-row-sel: rgba(233, 235, 237, .16);
}

/* ── Слой ───────────────────────────────────────────────────────────────
 * Экран закрывает плеер целиком: клики не должны проваливаться на видео, а
 * живой поток за ним продолжает идти — как в десктопе, где оверлей просто
 * ложится поверх работающего плеера.
 *
 * z-index 1010 — выше хрома плеера (1002) и экрана экспорта (1003–1006), но
 * ниже тостов, модалок и контекстных меню (1099+): сообщение о действии
 * должно быть видно и отсюда.
 */
#detScreen {
    display: none;
}

body.detOpen #detScreen {
    position: fixed;
    inset: 0;
    z-index: 1010;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    color: var(--fg);
}

/* Кнопка выхода самого плеера на этом экране лишняя: своя стрелка «назад»
   стоит в шапке, а чужая висела бы поверх неё. */
body.detOpen #closeCam {
    display: none;
}

/* ── Шапка ──────────────────────────────────────────────────────────────
 * Та же, что на других экранах: стрелка слева, заголовок, действие справа.
 */
#detHeader {
    flex: none;
    height: 48px;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 18px 0 12px;
    box-sizing: border-box;
    border-bottom: 1px solid var(--border);
}

.detBack,
.detRefresh {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--fg-muted);
    cursor: pointer;
    transition: color var(--t-fast) linear, background-color var(--t-fast) linear;
}

.detBack {
    width: 34px;
    height: 34px;
    border-radius: 17px;
}

.detBack:hover {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

.detRefresh {
    width: 26px;
    height: 26px;
}

.detRefresh:hover {
    color: var(--fg);
}

.detTitle {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 15px;
    font-weight: 500;
    color: var(--fg);
}

/* ── Фрагмент ───────────────────────────────────────────────────────────
 * Половина высоты экрана под видео, фон чёрный: ролик приходит от сервиса
 * детекции обычным mp4 и его пропорции заранее неизвестны.
 */
#detStage {
    position: relative;
    flex: none;
    height: 50%;
    background: #000;
    overflow: hidden;
}

#detVideo {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    display: block;
}

/* Подпись «выберите событие» — та же плашка статуса, что и в ячейке панели. */
.detPlate {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    padding: 8px 14px;
    border-radius: 8px;
    background: var(--overlay-panel);
    color: var(--overlay-fg);
    font-size: 13px;
    pointer-events: none;
}

/* ── Панель управления фрагментом ───────────────────────────────────────
 * Как у обычного плеера: слева переход по событиям и пауза, по центру
 * время и полоса, справа день и полный экран.
 */
#detControls {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 56px;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 12px;
    box-sizing: border-box;
    background: rgba(0, 0, 0, .55);
}

.detCtlLeft,
.detCtlRight {
    flex: none;
    display: flex;
    align-items: center;
    gap: 6px;
}

.detBtn {
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 19px;
    color: var(--overlay-fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, opacity var(--t-fast) linear;
}

.detBtn:hover {
    background: rgba(255, 255, 255, .18);
}

/* Недоступная кнопка гаснет, но остаётся на месте: ряд не должен прыгать
   при переходе на первое и последнее событие. */
.detBtn.off {
    opacity: .35;
    pointer-events: none;
}

.detTime {
    flex: none;
    font-size: 12px;
    color: var(--overlay-fg);
    font-variant-numeric: tabular-nums;
}

.detSeek {
    flex: 1 1 auto;
    min-width: 40px;
    height: 20px;
    display: flex;
    align-items: center;
    cursor: pointer;
}

.detSeekTrack {
    width: 100%;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .25);
}

#detSeekFill {
    width: 0;
    height: 100%;
    border-radius: 2px;
    background: var(--overlay-fg);
}

/* День событий — рядом с перемоткой, а не в шапке: в десктопе его там не
   замечали. Родной выбор дня лежит поверх чипа прозрачным, как на экране
   экспорта: вид остаётся десктопным, календарь — системным. */
.detDay {
    position: relative;
    height: 32px;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 11px;
    border-radius: 16px;
    background: rgba(255, 255, 255, .12);
    color: var(--overlay-fg);
    font-size: 12px;
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

.detDay:hover {
    background: rgba(255, 255, 255, .22);
}

.detDayIcon {
    display: flex;
}

.detDay input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    opacity: 0;
    cursor: pointer;
}

/* ── Список событий ─────────────────────────────────────────────────────── */
#detBody {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
}

#detList {
    height: 100%;
    overflow: auto;
}

.detRow {
    position: relative;
    height: 84px;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 16px;
    box-sizing: border-box;
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

.detRow:hover {
    background: var(--nav-hover-bg);
}

.detRow.sel {
    background: var(--det-row-sel);
}

/* Разделитель не во всю ширину: поля те же 16 px, что и у строки. */
.detRow::after {
    content: "";
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 0;
    height: 1px;
    background: var(--border);
}

.detThumb {
    position: relative;
    flex: none;
    width: 128px;
    height: 72px;
    overflow: hidden;
    background: var(--bg-deep);
}

.detThumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.detDur {
    position: absolute;
    right: 4px;
    bottom: 4px;
    padding: 2px 4px;
    border-radius: 3px;
    background: rgba(0, 0, 0, .6);
    color: #fff;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.2;
}

.detInfo {
    flex: 1 1 auto;
    min-width: 0;
}

.detInfo div {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 13px;
    line-height: 18px;
    color: var(--fg);
}

.detInfo b {
    font-weight: 500;
}

/* Загрузка и пустое состояние — по центру свободной площади под кадром. */
.detStatus {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    font-size: 14px;
    color: var(--fg-muted);
    pointer-events: none;
}

.detMore {
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    color: var(--fg-muted);
}

/* ── Кнопка детекции в плеере ───────────────────────────────────────────
 * В архиве нижний левый ряд занят управлением архивом, и детекции там не
 * место (в десктопе ряд живой камеры в архиве целиком скрыт). Селектор из
 * двух id — чтобы ui-player.css, который грузится после, не вернул кнопку
 * своим display у .videoButton.
 */
#fullness.active #btnDetection {
    display: none;
}

/* ── Значки на карточке камеры ──────────────────────────────────────────
 * Справа вверху кадра, в ряд. Тёмная подложка и белый штрих здесь не из
 * темы: значки лежат на фотографии, а она бывает любой — и ночным потолком,
 * и белой стеной.
 */
/* Кадру нужна своя система координат: значки прибиты к его углу, а не к углу
   карточки — под кадром ещё две строки подписи. */
.camCard-thumb {
    position: relative;
}

.camCard-badges {
    position: absolute;
    top: 6px;
    right: 6px;
    display: flex;
    gap: 4px;
    pointer-events: none;
}

.camCard-badge {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: rgba(0, 0, 0, .55);
    color: #fff;
}

/* Перечёркнутый колокольчик приглушён: уведомлений по этой камере не будет. */
.camCard-badge.off {
    opacity: .7;
}




/* Экран экспорта фрагмента архива — по образцу десктопа
 * (qml/components/ExportDialog.qml, TimeField.qml).
 *
 * Прежде экспорт был режимом панели плеера (кнопки «[», «]» и полоска
 * диапазона в ряду круглых кнопок). Теперь это отдельный полноэкранный
 * экран, как в десктопе.
 *
 * ВАЖНО про порядок файлов: сборщик склеивает css по алфавиту, и
 * ui-player.css идёт ПОСЛЕ этого файла. Поэтому всё, что переопределяет
 * правила плеера (#closeCamEx, #progress, #exportFon), пишется селектором
 * из двух id — иначе его перебьёт ui-player.css.
 */

/* ── Слои ───────────────────────────────────────────────────────────────
 * #exportBack — подложка ПОД кадром: закрывает хром плеера и панель архива.
 * #onlineCam  — тот же <video>, что и в архиве, поднятый и обрезанный по
 *               рамке кадра. Переносить его по DOM нельзя: извлечение
 *               медиаэлемента из документа ставит его на паузу и рвёт MSE.
 * #exportScreen — шапка, оверлей паузы и нижняя панель, НАД кадром.
 */
#exportBack,
#exportScreen {
    display: none;
}

body.exportOpen #exportBack {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1003;
    background: var(--bg);
}

body.exportOpen #onlineCam {
    top: 52px;
    left: 16px;
    right: 16px;
    bottom: 184px;   /* 176 панели + 8 зазора */
    z-index: 1004;
    background: #000;
    border-radius: 10px;
    overflow: hidden;
}

/* Кадр целиком, полями по краям — как VideoOutput.PreserveAspectFit. */
body.exportOpen #onlineCam video {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    object-fit: contain;
}

/* Заставка-скриншот повторяет рамку кадра. Сейчас её и так распирает по
   #onlineCam правилами из theme.css с !important, но тот файл по плану
   уходит — без этих строк она вернулась бы к position:fixed из main.css и
   растянулась бы на весь экран поверх панели. */
body.exportOpen #preImage {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    border-radius: 10px;
}

body.exportOpen #exportScreen {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1005;
    /* Слой сквозной: кликается только то, что нарисовано. */
    pointer-events: none;
    color: var(--fg);
    font-size: 14px;
}

body.exportOpen #exportScreen > * {
    pointer-events: auto;
}

/* Кнопка выхода из плеера принадлежит архиву — на экране экспорта её место
   занимает шеврон в шапке. */
body.exportOpen #closeCam {
    display: none;
}

/* ── Шапка 52 ───────────────────────────────────────────────────────── */
#exportHeader {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 52px;
    display: flex;
    align-items: center;
}

#exportHeader .expBack {
    position: absolute;
    left: 12px;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    color: var(--fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

#exportHeader .expBack:hover {
    background: var(--nav-hover-bg);
}

#exportHeader .expTitle {
    width: 100%;
    text-align: center;
    font-size: 17px;
    font-weight: 500;
    color: var(--fg);
}

/* ── Кадр и оверлей паузы ───────────────────────────────────────────── */
#exportStage {
    position: absolute;
    top: 52px;
    left: 16px;
    right: 16px;
    bottom: 184px;
    border-radius: 10px;
    cursor: pointer;
}

#exportPausePad {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 72px;
    height: 72px;
    margin: -36px 0 0 -36px;
    display: none;
    align-items: center;
    justify-content: center;
    border-radius: 36px;
    background: rgba(0, 0, 0, .45);
    color: #fff;
}

#exportPausePad.on {
    display: flex;
}

/* ── Нижняя панель: 76 лента + 42 поля + 58 итог ────────────────────── */
#exportPanel {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 176px;
}

#exportPanel .expMiniRow,
#exportPanel .expFields,
#exportPanel .expFoot {
    margin: 0 24px;
}

/* ── Мини-таймлайн ──────────────────────────────────────────────────── */
.expMiniRow {
    height: 76px;
    display: flex;
    align-items: center;
}

#exportPanel .expPlay {
    flex: none;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 20px;
    background: var(--bg-deep);
    color: var(--fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

#exportPanel .expPlay:hover {
    background: var(--nav-active-bg);
}

/* Иконку ставит общий обработчик паузы (syncPauseUi) размером 22 —
   в круге 40 это тяжело, ужимаем до десктопных 16. */
#exportPanel .expPlay .icon {
    width: 16px;
    height: 16px;
}

.expMini {
    position: relative;
    flex: 1 1 auto;
    height: 100%;
    margin-left: 16px;
}

.expMini canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* Метка in/out: пилюля 8×34, зона захвата шире на 6 px со всех сторон. */
.expHandle {
    position: absolute;
    top: 9px;          /* центр ленты (76/2 − 6) минус половина высоты */
    width: 20px;
    height: 46px;
    margin-left: -10px;
    cursor: col-resize;
    touch-action: none;
}

.expHandle::after {
    content: "";
    position: absolute;
    top: 6px;
    left: 6px;
    width: 8px;
    height: 34px;
    border-radius: 4px;
    background: var(--fg-muted);
}

.expHandle:hover::after,
.expHandle.pressed::after {
    background: var(--fg);
}

/* ── Поля начала/конца и скорость ───────────────────────────────────── */
.expFields {
    height: 42px;
    display: flex;
    align-items: center;
    gap: 24px;
}

.expField {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 42px;
}

.expLabel {
    color: var(--fg-muted);
    font-size: 14px;
    white-space: nowrap;
}

.expDate {
    position: relative;
    width: 112px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: var(--bg-deep);
    color: var(--fg);
    font-size: 14px;
    cursor: pointer;
}

/* Родной выбор дня лежит поверх плашки прозрачным: вид остаётся десктопным,
   а календарь — системным, без своей реализации. */
.expDate input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    opacity: 0;
    cursor: pointer;
}

.expTime {
    width: 116px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: var(--bg-deep);
    color: var(--fg);
    font-size: 14px;
    outline: none;
    box-sizing: border-box;
    border: 1px solid transparent;
}

.expTime:focus {
    border-color: var(--accent);
}

.expTime .expSeg {
    width: 26px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    cursor: text;
}

.expTime .expSeg.on {
    /* Подсветка активного сегмента — accent с альфой 0,18, как в TimeField.
       Первое объявление — запасное для движка без color-mix. */
    background: var(--nav-active-bg);
    background: color-mix(in srgb, var(--accent) 18%, transparent);
}

.expTime .expSep {
    width: 8px;
    text-align: center;
}

.expSpeeds {
    display: flex;
    gap: 6px;
}

.expSpeed {
    width: 44px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: var(--bg-deep);
    color: var(--fg);
    font-size: 14px;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

.expSpeed.sel {
    background: var(--accent);
    color: var(--accent-fg);
    font-weight: 500;
}

/* ── Строка итога и кнопки ──────────────────────────────────────────── */
.expFoot {
    height: 58px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.expInfo {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    color: var(--fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.expInfo.bad {
    color: #ff8080;
}

.expBtns {
    flex: none;
    display: flex;
    gap: 14px;
}

.expBtn {
    height: 36px;
    box-sizing: border-box;   /* рамка «Отмены» не должна раздувать 110×36 */
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    font-size: 14px;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--t-fast) linear, opacity var(--t-fast) linear;
}

.expBtn.ghost {
    width: 110px;
    border: 1px solid var(--border);
    color: var(--fg-muted);
}

.expBtn.ghost:hover {
    background: var(--nav-hover-bg);
}

.expBtn.main {
    width: 130px;
    background: var(--accent);
    color: var(--accent-fg);
    font-weight: 500;
}

.expBtn.main:hover {
    background: var(--accent-hover);
}

/* Недопустимый диапазон гасит кнопку, а не прячет её. */
.expBtn.main.disabled {
    background: var(--bg-deep);
    color: var(--fg-muted);
    cursor: default;
}

/* ── Оверлей прогресса ──────────────────────────────────────────────────
 * Остаётся поверх плеера, но выглядит по-десктопному: затемнение, заголовок,
 * полоса 320×8 и кнопка «Отмена». Селекторы из двух id — иначе их перебьёт
 * ui-player.css, который идёт следом.
 */
#exportTail {
    z-index: 1006;
}

#exportTail #exportFon {
    inset: 0;
    /* Раньше тут лежал размытый скриншот камеры; десктоп просто затемняет
       кадр, и лишний запрос к screenshot.php больше не нужен. */
    filter: none;
    background: var(--overlay-scrim);
}

#exportTail #progress {
    width: 320px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

#exportTail #text {
    /* Поле 10 px из main.css ломало бы зазор 16 между заголовком и полосой.
       Кегль не трогаем: его для этого оверлея задаёт ui-player.css. */
    padding: 0;
    color: var(--overlay-fg);
}

#exportTail .expProgTrack {
    width: 320px;
    height: 8px;
    border-radius: 4px;
    background: rgba(255, 255, 255, .22);
    overflow: hidden;
}

#exportTail #progressBar {
    height: 8px;
    padding: 0;
    border-radius: 4px;
    background: var(--overlay-fg);
    background-image: none;
    animation: none;
}

#exportTail #closeCamEx {
    position: static !important;
    box-sizing: border-box;   /* рамка не должна раздувать 120×40 */
    width: 120px;
    height: 40px;
    border-radius: 8px;
    background: transparent;
    border: 1px solid var(--overlay-border);
    color: var(--overlay-muted);
    font-size: 14px;
}

#exportTail #closeCamEx:hover {
    background: rgba(255, 255, 255, .08);
}

/* Рамка кадра в экспорте — чёрная, как в десктопе. #fon — размытая подложка
   обычного плеера (светлая в светлой теме); в этом экране она лежит поверх
   кадра и давала светлые поля по бокам вместо чёрных. Режим экспорта
   помечается классом exportOpen на #wrapper — #fon лежит вне #exportScreen. */
/* !important — потому что цвет подложки ставит JS прямо в style элемента,
   а класс режима экспорта висит на body. */
body.exportOpen #fon {
    background-color: #000 !important;
    background-image: none !important;
}




/* Панели — список и создание. Вид перенесён из десктопа
 * (../desktop_app: qml/pages/PanelPage.qml, qml/components/PanelCard.qml,
 * qml/pages/AddPanelPage.qml, qml/components/PanelLayouts.qml).
 *
 * Отдельный файл, а не дописка в ui.css: экраны переносятся этапами, и так
 * видно, что уже переоформлено. По алфавиту файл идёт после main.css и
 * theme.css (их правила перебиваются) и перед ui.css — токены оттуда
 * подставляются в момент использования, порядок на них не влияет.
 *
 * Старые правила списка панелей (.panelLink, .typename, #panelname и
 * соседние) в main.css / theme.css больше ни к чему не цепляются: разметка
 * ниже целиком на новых классах. Их удаление — общая уборка этапа.
 */

:root {
    /* Незанятая ячейка мозаики. В светлой теме это не токен, а собственный
     * оттенок десктопа (PanelCard.qml): между --bg-elev подложки превью и
     * --bg-deep он читается как «место под камеру», а не как дырка в карточке.
     * Больше нигде не нужен, поэтому и живёт здесь, а не в ui.css.
     */
    --panel-cell-empty: #e8eaec;
}

html[data-theme="dark"] {
    /* В тёмной теме подложка превью и пустая ячейка совпадают — так в десктопе. */
    --panel-cell-empty: var(--bg-deep);
}

/* ── Список панелей ─────────────────────────────────────────────────────
 * Колонка во всю высоту #content: шапка сверху, дальше сетка карточек либо
 * пустое состояние — оно тянется на весь остаток и центрируется в нём.
 */
.panelsPage {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    background: var(--bg);
}

/* Действие шапки — единственная кнопка добавления: плитки «добавить панель»
 * в сетке больше нет (PanelPage.qml).
 */
.panelsAddBtn {
    height: 38px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px;
    border: 0;
    border-radius: 10px;
    background: var(--accent);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    color: var(--accent-fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, transform 90ms var(--ease);
}

.panelsAddBtn:hover {
    background: var(--accent-hover);
}

.panelsAddBtn:active {
    transform: scale(.97);
}

.panelsAddBtn:focus {
    outline: 0;
}

.panelsAddBtn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Сетка: целевая ширина карточки 300, зазор 16, поле страницы 40.
 * auto-fill повторяет расчёт десктопа (cols = floor((W + 16) / 316)), а
 * min() не даёт колонке распереть узкое окно.
 */
#panellist.panelsGrid {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
    gap: 16px;
    align-content: start;
    padding: 0 var(--page-pad) var(--page-pad);
    box-sizing: border-box;
}

/* Карточка: превью 16:9 + 46 px подписи под ним. Высота складывается из
 * 8 отступа, 16 имени, 2 отступа, 14 подписи и 6 запаса снизу (PanelCard.qml:
 * height = previewHeight + 46).
 */
.panelCard {
    position: relative;
    padding-bottom: 6px;
    cursor: pointer;
}

/* Подложка наведения выходит за карточку на 6 px — как в десктопе, где это
 * отдельный прямоугольник с margins: -6.
 */
.panelCard::before {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: 12px;
    transition: background-color var(--t-fast) linear;
}

.panelCard:hover::before {
    background: var(--nav-hover-bg);
}

.panelCardPreview {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-elev);
}

html[data-theme="dark"] .panelCardPreview {
    background: var(--bg-deep);
}

/* Мозаика раскладки. Зазор 1 px и такие же поля справа и снизу дают ровно
 * ту же ячейку, что в десктопе: colSpan * cellW − 1.
 */
.panelCardMosaic {
    position: absolute;
    inset: 0;
    display: grid;
    gap: 1px;
    padding: 0 1px 1px 0;
    box-sizing: border-box;
}

.panelCardCell {
    background-color: var(--panel-cell-empty);
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
}

.panelCardName {
    margin-top: 8px;
    height: 16px;
    line-height: 16px;
    font-size: 14px;
    color: var(--fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.panelCardMeta {
    margin-top: 2px;
    height: 14px;
    line-height: 14px;
    font-size: 12px;
    color: var(--fg-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Пустое состояние центрируется по всей странице, а не по остатку под
 * шапкой: нижнее поле высотой шапки возвращает центр на середину экрана
 * (в десктопе это anchors.centerIn у страницы целиком).
 */
#panellist.panelsEmpty {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 0 var(--page-pad) var(--header-h);
    box-sizing: border-box;
}

.panelsEmptyTitle {
    font-size: 18px;
    font-weight: 500;
    color: var(--fg);
}

/* Перенос строки в тексте задан явно (\n в textContent) — как в эталоне. */
.panelsEmptyText {
    font-size: 14px;
    line-height: 1.2;
    color: var(--fg-muted);
    text-align: center;
    white-space: pre-line;
}

/* ── Создание панели ────────────────────────────────────────────────────
 * Колонка по центру шириной min(480, ширина − 60); кнопка «назад» вне её,
 * в левом верхнем углу страницы (AddPanelPage.qml).
 */
.addPanelPage {
    position: relative;
    min-height: 100%;
    padding: 40px 30px 80px;
    box-sizing: border-box;
    background: var(--bg);
}

.addPanelForm {
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    text-align: center;
}

/* Кнопка «назад» на странице — без подложки: кружок нужен только поверх
 * кадра (BackButton.qml, variant "surface").
 */
.addPanelBack {
    position: absolute;
    top: 14px;
    left: 16px;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 20px;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: color var(--t-fast) linear;
}

.addPanelBack:hover {
    color: var(--fg);
}

/* Между подписью и её полем 12, между блоками 32 (в десктопе это spacing 12
 * плюс распорка 8), перед кнопкой 36.
 */
.addPanelLabel {
    margin-top: 32px;
    font-size: 15px;
    color: var(--fg-muted);
}

.addPanelForm > .addPanelLabel:first-child {
    margin-top: 0;
}

.addPanelName {
    width: 100%;
    height: 44px;
    margin-top: 12px;
    padding: 0 14px;
    box-sizing: border-box;   /* рамка внутрь: поле ровно 44 */
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg);
    font-family: inherit;
    font-size: 16px;
    color: var(--fg);
    text-align: center;
    outline: 0;
    transition: border-color var(--t-fast) linear;
}

html[data-theme="dark"] .addPanelName {
    background: var(--bg-elev);
}

.addPanelName::placeholder {
    color: var(--fg-muted);
    opacity: 1;
}

.addPanelName:focus {
    border-color: var(--accent);
}

/* Имя не введено — поле обводится красным на время тоста. */
.addPanelName_error,
.addPanelName_error:focus {
    border-color: var(--err);
}

/* Количество камер: 8 колонок по 50×44 с зазором 6 — 442 px, уже колонки. */
.addPanelCounts {
    display: grid;
    grid-template-columns: repeat(8, 50px);
    gap: 6px;
    justify-content: center;
    margin-top: 12px;
}

.addPanelCount {
    width: 50px;
    height: 44px;
    padding: 0;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-elev);
    font-family: inherit;
    font-size: 16px;
    color: var(--fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, border-color var(--t-fast) linear,
                color var(--t-fast) linear;
}

.addPanelCount:hover {
    background: var(--bg-deep);
}

.addPanelCount_on,
.addPanelCount_on:hover {
    border-color: var(--accent);
    background: var(--accent);
    color: var(--accent-fg);
}

.addPanelPresets {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin-top: 12px;
}

/* Диаграмма-пресет 120×120. Выбранная берётся рамкой 2 px акцентом: заливки
 * у неё нет — синяя подсветка десктопа осталась от прежней фирменной гаммы,
 * в монохромной палитре её заменить нечем.
 */
.addPanelPreset {
    width: 120px;
    height: 120px;
    /* Поля 10 считаются от внешнего края (в QML рамка рисуется внутрь), поэтому
       из них вычтена толщина рамки; 3 справа и снизу — тот же зазор между
       ячейками, что и между строками (span * cell − 3). */
    padding: 9px 12px 12px 9px;
    box-sizing: border-box;
    display: grid;
    gap: 3px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg-elev);
    cursor: pointer;
    transition: border-color var(--t-fast) linear;
}

.addPanelPreset:hover {
    border-color: var(--fg-muted);
}

.addPanelPreset_on,
.addPanelPreset_on:hover {
    /* Рамка 2 px вместо 1 — поля уменьшены на тот же пиксель, иначе схема
       внутри дёргалась бы при выборе. */
    padding: 8px 11px 11px 8px;
    border: 2px solid var(--accent);
}

.addPanelPresetCell {
    border: 1px solid var(--fg-muted);
    border-radius: 2px;
}

.addPanelSubmit {
    width: 100%;
    height: 46px;
    margin-top: 36px;
    padding: 0;
    border: 0;
    border-radius: 10px;
    background: var(--accent);
    font-family: inherit;
    font-size: 16px;
    font-weight: 500;
    color: var(--accent-fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, transform 90ms var(--ease);
}

.addPanelSubmit:hover {
    background: var(--accent-hover);
}

.addPanelSubmit:active {
    transform: scale(.97);
}

.addPanelSubmit:focus {
    outline: 0;
}

.addPanelSubmit:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Пока запрос в пути — кнопка гаснет и не нажимается. */
.addPanelSubmit[disabled],
.addPanelSubmit[disabled]:hover {
    background: var(--bg-deep);
    color: var(--fg-muted);
    cursor: default;
    transform: none;
}




/* Экран просмотра панели — вид один в один с десктопом
 * (../desktop_app: qml/pages/PanelViewPage.qml, components/CellStatus.qml,
 * StatusPlate.qml, PanelLayouts.qml, CameraSearchOverlay.qml, BackButton.qml).
 *
 * Имя файла важно: сборщик (tools/build.sh) склеивает css по алфавиту, и
 * «ui-panelview.css» встаёт после main.css и theme.css, но перед ui.css —
 * то есть перебивает старые правила и не спорит с общими токенами.
 *
 * Правила старого оформления пока остаются в main.css/theme.css: их вынесут,
 * когда весь экран панели переедет сюда целиком (docs/desktop-look-port.md).
 * Поэтому местами приходится повышать специфичность — каждый такой случай
 * прокомментирован.
 */

/* ── Полотно экрана ─────────────────────────────────────────────────────
 * Фон вокруг ячеек — тот же --bg-deep, что и фон самой ячейки: иначе панель
 * на три камеры показывала бы чужой тон на месте недостающей четвёртой, и
 * сетка распадалась бы на куски.
 *
 * Обёртка позиционирована: без неё #camlist (position:absolute) считал
 * размеры от #wrapper, то есть от всего окна вместе с боковым меню, и левый
 * край сетки уезжал под навигацию.
 */
.panelView {
    position: relative;
    height: 100%;
    background: var(--bg-deep);
    overflow: hidden;
}

/* ── Сетка ячеек ────────────────────────────────────────────────────────
 * Раскладки — из PanelLayouts.qml. Номера типов трогать нельзя: по ним
 * панель хранится на сервере.
 *
 * Зазор даёт grid-gap, а не поля у ячеек: ровно 1 px цветом полотна.
 */
#camlist {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    height: auto;
    padding: 0;
    display: grid;
    gap: 1px;
    font-size: 14px;
    background: var(--bg-deep);
}

/* Старые правила раскладки (float + calc по классам .prime/.half/.s32…)
   считали размер сами. В сетке их надо снять — иначе к ячейке добавляются
   поля и проценты поверх grid. Селектор с классом бьёт «#camlist>div.prime». */
#camlist.panelGrid > div {
    position: relative;
    float: none;
    margin: 0;
    width: auto;
    height: auto;
    min-width: 0;
    min-height: 0;
    box-sizing: border-box;
    overflow: hidden;
    border-radius: 0;
    text-align: left;
}

/* Фон ячейки = фон полотна. theme.css в режиме полного кадра красит ячейку в
   --cctv-bg с !important (когда-то поля у вписанного видео выходили белыми) —
   перебиваем: поля должны быть того же тона, что и шов сетки. */
#camlist.panelGrid > div,
#camlist.panelGrid.panel-fit-contain > div {
    background: var(--bg-deep) !important;
}

#camlist.panelGrid > div > video.cam {
    cursor: pointer;
}

/* Раскладки по типам (PanelLayouts.gridFor / cellsFor).
   Типы 10 и 11 считаются в JS — у них сетка задаётся инлайном. */
#camlist.layout-1,
#camlist.layout-2,
#camlist.layout-3 {
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
}

/* Тип 2 — крупная ячейка 2×2 слева сверху; остальные раскладываются сами
   ровно так же, как в PanelLayouts: 3 → (2,0), 6 → (2,1), 7..9 → нижняя строка. */
#camlist.layout-2 > .prime {
    grid-column: 1 / span 2;
    grid-row: 1 / span 2;
}

/* Тип 3 — крупная 2×2 в середине слева; 6 → (2,1), 9 → (2,2) тоже сами. */
#camlist.layout-3 > .prime {
    grid-column: 1 / span 2;
    grid-row: 2 / span 2;
}

#camlist.layout-4 {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(2, 1fr);
}

#camlist.layout-5 {
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(2, 1fr);
}

#camlist.layout-6 {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(3, 1fr);
}

#camlist.layout-7 {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(2, 1fr);
}

#camlist.layout-8 {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(5, 1fr);
}

/* ── Плашка имени ───────────────────────────────────────────────────────
 * Полоса снизу ячейки: мягкое затемнение вместо сплошной серой ленты,
 * которая резала кадр поперёк. Подпись читается на любом кадре.
 */
#camlist .subname {
    position: absolute;
    left: 0 !important;      /* !important — таким его ставит theme.css */
    right: 0 !important;
    bottom: 0;
    top: auto;
    height: 46px;
    padding: 0 10px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    text-align: left;
    text-shadow: none;
    background: linear-gradient(to bottom,
        rgba(0, 0, 0, 0) 0%,
        rgba(0, 0, 0, .45) 45%,
        rgba(0, 0, 0, .72) 100%);
    pointer-events: none;
    z-index: 2;
}

/* Имя — 13 Medium, адрес — 11 приглушённый; обе строки в одну строку с
   многоточием: в узкой ячейке иначе ломается вёрстка плашки. */
#camlist .subname > .subnameTitle {
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    color: #ffffff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#camlist .subname > .subnameAddr {
    margin-top: 2px;
    padding-bottom: 4px;
    font-size: 11px;
    line-height: 13px;
    color: rgba(255, 255, 255, .72);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Статус ячейки (StatusPlate) ────────────────────────────────────────
 * Пилюля с радиусом height/2. Правило показа живёт в panelCellStatus:
 * пока висит «Нет сигнала», «Ожидание сигнала» не возвращается.
 *
 * Селекторы внутри #camlist: та же разметка обслуживает одиночную камеру
 * (#loader), а её оформление — не этот экран.
 */
#camlist .cellStatus {
    padding: 7px 13px;
    gap: 5px;
    border-radius: 999px;
    background: rgba(41, 43, 51, .85);
    border: 1px solid rgba(255, 255, 255, .18);
    box-shadow: none;
    transition: background-color 180ms linear, border-color 180ms linear;
}

#camlist .cellStatus.nosignal {
    padding: 7px 13px;
    background: rgba(199, 51, 51, .92);
    border-color: rgba(255, 255, 255, .25);
    box-shadow: none;
}

#camlist .cellStatus > .txt {
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    color: #ffffff;
}

#camlist .cellStatus > .dots {
    margin-left: 0;
    gap: 3px;
}

/* Период 1200 мс: точка светлеет 200 мс, гаснет 200 мс, остальное — пауза.
   Место под все три занято всегда, меняется только яркость, иначе плашка
   дёргалась бы по ширине на каждом шаге. */
#camlist .cellStatus > .dots > i {
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: #ffffff;
    opacity: .25;
    animation: panelCellDot 1200ms linear infinite;
}

#camlist .cellStatus > .dots > i:nth-child(2) {
    animation-delay: 200ms;
}

#camlist .cellStatus > .dots > i:nth-child(3) {
    animation-delay: 400ms;
}

@keyframes panelCellDot {
    0%      { opacity: .25; }
    16.667% { opacity: 1; }
    33.333% { opacity: .25; }
    100%    { opacity: .25; }
}

/* ── Пустая ячейка ──────────────────────────────────────────────────────
 * Раньше в каждой пустой ячейке висел крест с подписью — на панели 4×4 это
 * шестнадцать одинаковых призывов, и сетка превращалась в трафарет. Теперь
 * тихий плюс, а предложение появляется только под курсором.
 */
#camlist .btnAddToPanel {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    transform: none;   /* main.css центрует его сдвигом на -50% */
    width: auto;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--fg-muted);
    font-size: 14px;
    cursor: pointer;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

#camlist > div:hover > .btnAddToPanel {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

#camlist .btnAddToPanel > .addGlyph {
    display: block;
    opacity: .55;
    transition: opacity var(--t-fast) linear;
}

#camlist > div:hover > .btnAddToPanel > .addGlyph {
    opacity: 1;
}

/* Подпись — только под курсором: там, куда человек и целится. */
#camlist .btnAddToPanel > .addLabel {
    opacity: 0;
    transition: opacity var(--t-fast) linear;
}

#camlist > div:hover > .btnAddToPanel > .addLabel {
    opacity: 1;
}

/* ── Перетаскивание ячеек ───────────────────────────────────────────────
 * Притушена сама ячейка целиком (вместе с плашкой имени), а не одно видео:
 * иначе подпись оставалась яркой и «отклеивалась» от кадра.
 */
#camlist > div.cam-dragging {
    opacity: .4;
}

/* Рамка цели — внутрь ячейки, чтобы не съедать соседний шов. */
#camlist > div.cam-drop-target {
    outline: 3px solid var(--accent);
    outline-offset: -3px;
}

.cam-drag-ghost {
    position: fixed;
    z-index: 9999;
    pointer-events: none;
    width: 200px;
    height: 150px;
    border: 2px solid var(--accent);
    border-radius: 0;
    box-shadow: none;
    opacity: .9;
    background-color: var(--bg-deep);
}

/* ── Кнопка «назад» ─────────────────────────────────────────────────────
 * Вариант «поверх видео» из BackButton.qml: подложка нужна потому, что под
 * стрелкой кадр — на белой стене или снегу она без круга исчезает.
 */
#backbutton {
    position: absolute;
    top: 12px;
    left: 12px;
    z-index: 10;
    width: 40px;
    height: 40px;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 20px;
    background: rgba(0, 0, 0, .55);
    box-shadow: none;
    color: #ffffff;
    line-height: normal;
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

#backbutton:hover {
    background: rgba(0, 0, 0, .78);
}

/* ── Оверлей выбора камер ───────────────────────────────────────────────
 * Был узкий белый прямоугольник с полем-подчёркиванием и списком строк.
 * Теперь тот же язык, что на поиске: карточки с настоящим кадром, а номер
 * на выбранной показывает, в каком порядке камеры встанут в ячейки.
 */
#camSearcher {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    padding: 0;
    transform: none;   /* main.css центрует его сдвигом на -50% */
    display: none;
    align-items: center;
    justify-content: center;
    border-radius: 0;
    z-index: 102;
    /* theme.css красит #camSearcher селектором с темой — специфичность выше
       нашей, поэтому фон и тень перебиваем явно. Сам оверлей — только
       затемнение, цвет живёт на диалоге. */
    background: rgba(0, 0, 0, .45) !important;
    box-shadow: none !important;
    color: var(--fg) !important;
}

#camSearcher.active {
    display: flex;
}

.pickDialog {
    position: relative;
    width: min(1000px, 100vw - 80px);
    height: min(720px, 100vh - 80px);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--bg);
    overflow: hidden;
}

.pickHead {
    flex: none;
    height: 76px;
    display: flex;
    align-items: center;
    padding: 0 20px 0 28px;
}

.pickTitle {
    flex: 1 1 auto;
    font-size: 22px;
    font-weight: 500;
    color: var(--fg);
}

#closePanelCamSearch {
    position: static;
    flex: none;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--fg-muted);
    font-size: 0;
    cursor: pointer;
    transition: color var(--t-fast) linear;
}

#closePanelCamSearch:hover {
    color: var(--fg);
}

/* Поле поиска — как на странице поиска. */
.pickField {
    flex: none;
    height: 46px;
    margin: 0 28px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    padding: 0 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg);
    transition: border-color var(--t-fast) linear;
}

html[data-theme="dark"] .pickField {
    background: var(--bg-elev);
}

.pickField:focus-within {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);   /* рамка 2 px без скачка раскладки */
}

/* main.css красит все span внутри #camSearcher под старый заголовок диалога
   (25 px, bold, display:block) — поэтому селекторы с id, а не по классу. */
#camSearcher .pickGlass {
    flex: none;
    display: block;
    margin-right: 12px;
    font-size: 0;
    font-weight: 400;
    color: var(--fg-muted);
}

/* Два id подряд — чтобы перебить и main.css (#filter), и покраску темы. */
#camSearcher #filter {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 16px;
    color: var(--fg);
    outline: 0;
}

#camSearcher #filter::placeholder {
    color: var(--fg-muted);
    opacity: 1;
}

/* Выдача — сетка плиток с целевой шириной 220 (auto-fill даёт ровно тот же
   расчёт колонок, что и Flow в десктопе). */
#camSearcher #filtResult {
    position: static;
    flex: 1 1 auto;
    min-height: 0;
    margin: 16px 28px 12px;
    padding: 0 0 8px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    align-content: start;
    gap: 14px;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Пустое состояние и «показаны первые N» занимают всю ширину сетки. */
#camSearcher #filtResult > .pickEmpty {
    grid-column: 1 / -1;
    border: 0;   /* main.css подчёркивает каждую строку выдачи — здесь это не строка */
    padding: 80px 20px 0;
    text-align: center;
    font-size: 15px;
    color: var(--fg-muted);
}

#camSearcher #filtResult > .pickCard {
    position: relative;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--fg);
    text-align: left;
    user-select: none;
    cursor: pointer;
}

#camSearcher #filtResult > .pickCard:hover {
    background: transparent;
}

/* Подложка наведения выходит за карточку на 6 px — как в CameraCard. */
#camSearcher #filtResult > .pickCard::before {
    content: "";
    position: absolute;
    top: -6px;
    right: -6px;
    bottom: -6px;
    left: -6px;
    border-radius: 12px;
    background: transparent;
    transition: background-color var(--t-fast) linear;
}

#camSearcher #filtResult > .pickCard:hover::before {
    background: var(--nav-hover-bg);
}

#camSearcher #filtResult > .pickCard.picked::before {
    background: var(--nav-active-bg);
}

#camSearcher .pickThumb {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    background-color: var(--bg-elev);
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    overflow: hidden;
}

html[data-theme="dark"] #camSearcher .pickThumb {
    background-color: var(--bg-deep);
}

/* Подпись под кадром занимает ровно 46 px — одна мера на все карточки. */
#camSearcher .pickCaption {
    position: relative;
    height: 46px;
    padding-top: 8px;
    box-sizing: border-box;
    overflow: hidden;
}

#camSearcher .pickName {
    font-size: 14px;
    line-height: 17px;
    color: var(--fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#camSearcher .pickAddr {
    margin-top: 2px;
    font-size: 12px;
    line-height: 15px;
    color: var(--fg-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Номер выбора: выбор — это ещё и очередь, камеры встают в свободные ячейки
   именно в этом порядке. */
#camSearcher .addNumber {
    position: absolute;
    top: 8px;
    right: 8px;
    left: auto;
    width: 26px;
    height: 26px;
    border-radius: 13px;
    background: var(--accent);
    color: var(--accent-fg);
    font-size: 13px;
    font-weight: 500;
    line-height: 26px;
    text-align: center;
}

.pickFoot {
    position: relative;
    flex: none;
    height: 76px;
    box-sizing: border-box;   /* линия сверху входит в 76, а не добавляется к ним */
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 28px;
    border-top: 1px solid var(--border);
}

#camSearcher #total_selected_wrap {
    position: static;
    bottom: auto;
    font-size: 14px;
    color: var(--fg);
}

#camSearcher #total_selected,
#camSearcher #total_free {
    display: inline;
    font-size: inherit;
    font-weight: 400;
}

#camSearcher .pickTrunc {
    margin-top: 2px;
    font-size: 12px;
    color: var(--fg-muted);
}

#camSearcher #addField {
    position: static;
    width: auto;
    padding: 0;
    text-align: right;
}

#camSearcher #add {
    width: 150px;
    height: 42px;
    padding: 0;
    border: 0;
    border-radius: 10px;
    background: var(--accent);
    font-family: inherit;
    font-size: 15px;
    font-weight: 500;
    color: var(--accent-fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, transform 90ms var(--ease);
}

#camSearcher #add:hover {
    background: var(--accent-hover);
}

#camSearcher #add:active {
    transform: scale(.97);
}

#camSearcher #add[disabled] {
    opacity: .45;
    cursor: default;
}




/* Плеер, панель архива и экспорт — по образцу десктопа
 * (qml/components/CameraPlayer.qml, ArchiveBar.qml, ExportDialog.qml).
 *
 * Хром поверх кадра не зависит от темы: под ним всегда видео, поэтому здесь
 * используется слой --overlay-* из ui.css, а не --bg/--fg.
 */

/* ── Кнопка выхода ──────────────────────────────────────────────────────
 * Одна кнопка «назад» на всех экранах: шеврон слева сверху. Крестика справа
 * (прежний #closeCam) больше нет — это правило десктопа, и путать выход со
 * «закрыть окно» не нужно.
 */
#closeCam,
#closeCamEx {
    position: fixed !important;
    top: 14px;
    left: 16px;
    right: auto;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 20px;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: 0;
    cursor: pointer;
    z-index: 1002;
    transition: background-color var(--t-fast) linear;
}

#closeCam:hover,
#closeCamEx:hover {
    background: rgba(0, 0, 0, .78);
}

/* ── Круглые кнопки поверх кадра ────────────────────────────────────────
 * В живом режиме — светлая кнопка с тенью (VButton), в архиве — тёмная
 * плашка (ABtn): там под ней полоса скрима, и светлый круг выбивался бы.
 */
#buttonPanel .videoButton {
    width: 50px;
    height: 50px;
    max-width: none;
    max-height: none;
    margin: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: #fff;
    color: var(--fg);
    box-shadow: 0 2px 10px rgba(0, 0, 0, .45);
    font-size: 0;
    line-height: normal;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear,
                opacity var(--t-fast) linear, transform 90ms var(--ease);
}

html[data-theme="dark"] #buttonPanel .videoButton {
    background: var(--bg-elev);
}

#buttonPanel .videoButton:active {
    transform: scale(.97);
}

/* Поверх кадра кнопка приглушена, пока не включена: в десктопе у VButton
   opacity 0.5, и сплошные белые круги на видео выглядели бы тяжелее. */
#buttonPanel .videoButton {
    opacity: .5;
}

#buttonPanel .videoButton:hover {
    opacity: .85;
}

/* Включённое состояние — заливка акцентом (в десктопе active-кнопка). */
#buttonPanel .videoButton.btnactive,
#buttonPanel .videoButton.active {
    background: var(--accent);
    color: var(--accent-fg);
    opacity: 1;
}

/* Недоступная кнопка не прячется, а гаснет — место в ряду сохраняется. */
#buttonPanel .videoButton.unactive,
#buttonPanel .videoButton.disabled {
    opacity: .5;
    cursor: default;
}

#buttonPanel .videoButton .icon {
    display: block;
}

#buttonPanel .videoButton i {
    position: static;
    transform: none;
    width: auto;
    font-size: 17px;
    font-style: normal;
    font-weight: 500;
}

/* Индикатор скорости — тот же круг, но с текстом ×N. */
#buttonPanel .videoButton.speedBtn {
    font-size: 17px;
}

/* ── Раскладка кнопок ───────────────────────────────────────────────────
 * Живой режим: слева снизу — съёмка, зум, архив; справа снизу — звук,
 * избранное, PiP, полный экран. Один сплошной ряд по центру, как было
 * раньше, в десктопе не встречается.
 */
#buttonPanel {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    transform: translateY(-100%);
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 0 11px 11px;
    box-sizing: border-box;
    font-size: 0;
}

/* Правая группа: в десктопе она читается «звук → избранное → PiP → на весь
   экран», а в разметке кнопки идут в обратном порядке. Выстраиваем порядком
   флекса, чтобы не переставлять шаблон (на id завязаны обработчики).
   Настройки — кнопка, которой в десктопе нет; ставим её первой. */
#buttonPanel > .videoButton.right { order: 9; }
#buttonPanel > #btnGetSettings   { order: 2; }
#buttonPanel > #btnSound         { order: 3; }
#buttonPanel > #btnFavorite      { order: 4; }
#buttonPanel > #btnPip           { order: 5; }
#buttonPanel > #btnFullscreen    { order: 6; }

/* Распорка между левой и правой группой: слева съёмка/зум/архив и транспорт,
   справа звук, избранное, PiP и полный экран. */
#buttonPanel > #normalList,
#buttonPanel > #exportList {
    margin-right: auto;
}

#normalList,
#exportList {
    display: inline-block;
}

/* ── Панель архива ──────────────────────────────────────────────────────
 * Высота 148: ряд кнопок 48 сверху (отступ 6), ниже полоса записи и ось.
 * Фон — не сплошная серая плашка, а градиентный скрим: под ним кадр.
 */
#fullness {
    height: 148px;
    bottom: -148px;
    background: linear-gradient(to bottom,
        rgba(15, 18, 20, 0) 0%,
        rgba(15, 18, 20, .62) 32%,
        var(--overlay-scrim) 100%);
}

#fullness.active {
    bottom: 0;
}

/* В архиве кнопки уезжают внутрь панели, к её верхнему краю. */
#fullness.active #buttonPanel {
    position: absolute;
    top: 6px;
    transform: none;
    padding: 0 12px;
}

#fullness.active .videoButton {
    opacity: 1;
    width: 48px;
    height: 48px;
    margin: 4px;
    background: var(--overlay-panel);
    color: var(--overlay-fg);
    box-shadow: none;
}

#fullness.active .videoButton.btnactive,
#fullness.active .videoButton.active,
#fullness.active #btnControl:not(.played) {
    background: var(--overlay-accent);
    color: var(--overlay-accent-fg);
}

#fullness.active .videoButton.unactive,
#fullness.active .videoButton.disabled {
    opacity: .4;
}

/* Полоса времени: vis-timeline рисуется прямо в #fullness (так её создаёт
   proeye.js), поэтому позиционируем её корень. */
#fullness .vis-timeline {
    position: absolute;
    left: 14px;
    right: 14px;
    top: 62px;
    height: 78px;
    border: 0;
    background: transparent;
}

/* ── Цвета таймлайна ────────────────────────────────────────────────────
 * Единственное цветное место в интерфейсе: запись — синий градиент,
 * движение — малиновый поверх неё. Плейхед белый: красный на метках
 * движения не читался бы.
 */
#fullness .vis-panel.vis-center,
#fullness .vis-panel.vis-left,
#fullness .vis-panel.vis-right,
#fullness .vis-panel.vis-top,
#fullness .vis-panel.vis-bottom {
    border-color: transparent;
}

#fullness .vis-itemset {
    background: rgba(0, 0, 0, .18);
}

#fullness .vis-item.vis-background.negative {
    background: linear-gradient(to bottom, var(--rec-from), var(--rec-to));
}

#fullness .vis-item.vis-background.positive {
    background: var(--motion);
}

#fullness .vis-item.vis-background.exportinterval {
    background: rgba(47, 143, 208, .30);
}

#fullness .vis-time-axis .vis-grid.vis-minor {
    border-color: rgba(255, 255, 255, .14);
}

#fullness .vis-time-axis .vis-grid.vis-major {
    border-color: rgba(255, 255, 255, .28);
}

#fullness .vis-time-axis .vis-text {
    color: var(--overlay-fg);
    font-family: Roboto, sans-serif;
    font-size: 13px;
    padding-top: 2px;
}

#fullness .vis-time-axis .vis-text.vis-major {
    font-size: 15px;
    font-weight: 700;
}

#fullness .vis-custom-time {
    background: #fff;
    width: 2px;
}

#fullness .vis-custom-time.archiveStart,
#fullness .vis-custom-time.archiveEnd {
    background: #2f8fd0;
    width: 2px;
}

/* ── Зум-пад ────────────────────────────────────────────────────────────
 * Плашка 296×168 с круглыми кнопками 48 — как в десктопе; раньше это был
 * ряд мелких квадратов.
 */
#joystick {
    width: 296px;
    height: 168px;
    border-radius: 14px;
    background: var(--overlay-panel);
    /* Прежняя плашка была 250×120 с прозрачной рамкой 10 px и полем 5 —
       из-за них пад получался на 20 px шире и кнопки уезжали. */
    border: 0;
    padding: 0;
    box-sizing: border-box;
}

#joystick div {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 24px;
    background: var(--overlay-btn);
    color: var(--overlay-fg);
    font-size: 15px;
    transition: background-color var(--t-fast) linear;
}

#joystick div:hover {
    background: var(--overlay-btn-hi);
}

/* Координаты кнопок — из ZoomPad десктопа. bottom/right и translateY(-50%)
   из прежней раскладки сбрасываем, иначе боковые кнопки висят на 24 px выше,
   а «Сброс» держит свою ширину 110 через !important. */
#joystick #joystickup,
#joystick #joystickleft,
#joystick #joystickright,
#joystick #joystickdown,
#joystick #joystickminus,
#joystick #joystickplus,
#joystick #joystickreset {
    position: absolute;
    right: auto;
    bottom: auto;
    transform: none;
}

#joystick #joystickup    { left: 58px;  top: 18px; }
#joystick #joystickleft  { left: 18px;  top: 60px; }
#joystick #joystickright { left: 98px;  top: 60px; }
#joystick #joystickdown  { left: 58px;  top: 102px; }
#joystick #joystickminus { left: 166px; top: 18px; }
#joystick #joystickplus  { left: 224px; top: 18px; }
#joystick #joystickreset { left: 166px; top: 102px; width: 106px !important; }

/* ── Подписи поверх кадра ───────────────────────────────────────────────
 * Имя камеры и часы — в правом нижнем углу НАД рядом кнопок. Оба лежат
 * внутри #fullness, а он в живом режиме уехал за нижний край экрана на свою
 * высоту (148) — поэтому отступы считаем от него: в десктопе колонка стоит на
 * 78 px от низа в живом режиме и на 166 в архиве.
 */
#namebar,
#timebar {
    right: 18px;
    color: #fff;
    text-shadow: 0 0 3px rgba(0, 0, 0, .6), 0 1px 2px rgba(0, 0, 0, .6);
    background: transparent;
    text-align: right;
    pointer-events: none;
}

#namebar {
    bottom: 244px;       /* 148 (панель за экраном) + 96 */
    font-size: 14px;
}

#timebar {
    bottom: 226px;       /* 148 + 78 */
    font-size: 13px;
}

#fullness.active #namebar {
    bottom: 184px;
}

#fullness.active #timebar {
    bottom: 166px;
}

/* ── Экспорт ────────────────────────────────────────────────────────────
 * Прогресс — по центру кадра: заголовок, полоса 320×8 и «Отмена».
 */
#exportFon {
    background: rgba(0, 0, 0, .55);
}

#progress {
    width: 320px;
}

#progress #text {
    font-size: 18px;
    color: #fff;
}

#progressBar {
    height: 8px;
    border-radius: 4px;
    background: #fff;
}

#progress .track,
#progress .bar {
    border-radius: 4px;
}

#exportRange {
    color: var(--overlay-fg);
    font-size: 13px;
}

#buttonPanel .videoButton.markBtn .bracket {
    font-size: 20px;
    font-weight: 500;
}




/* Экран поиска — по образцу десктопа (../desktop_app/qml/pages/SearchPage.qml).
 *
 * Отдельный файл, а не блок в ui.css: экраны переносятся параллельно, и
 * общий файл на всех превратился бы в постоянный конфликт правок. Сборщик
 * (tools/build.sh) склеивает css по алфавиту, поэтому ui-search.css идёт
 * после main.css и theme.css (перебивает их) и перед ui.css — на токены и
 * на .pageHeader оттуда он не влияет.
 *
 * Своих цветов здесь нет: только токены из ui.css.
 */

/* ── Страница ───────────────────────────────────────────────────────────
 * В десктопе это колонка x:40, width: page.width − 80, spacing: 22 под
 * шапкой высотой 84. Снизу 80 — запас прокрутки (Flickable contentHeight).
 */
.srchPage {
    display: flex;
    flex-direction: column;
    gap: 22px;
    padding: 0 var(--page-pad) 80px;
    box-sizing: border-box;
}

/* ── Поле поиска ────────────────────────────────────────────────────────
 * Ширина колонкой, а не во всю страницу: строка поиска на два метра экрана
 * не помогает искать, она только отрывает каретку от результатов.
 */
.srchField {
    position: relative;
    width: min(720px, 100%);
    height: 48px;
    box-sizing: border-box;   /* рамка внутрь: поле ровно 48, как в десктопе */
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg);
    transition: border-color var(--t-fast) linear;
}

html[data-theme="dark"] .srchField {
    background: var(--bg-elev);
}

/* Рамка в фокусе — 2 px. Вторым пикселем служит внутренняя тень: смена
   border-width сдвигала бы содержимое поля на пиксель. */
.srchField:focus-within {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
}

/* Отступы внутри поля считаются от ВНЕШНЕГО края, как анchors в QML, а
   absolute — от внутреннего: рамка рисуется внутрь. Отсюда везде −1. */
.srchGlass {
    position: absolute;
    top: 50%;
    left: 15px;
    transform: translateY(-50%);
    display: block;
    width: 18px;
    height: 18px;
    color: var(--fg-muted);
    pointer-events: none;
}

.srchField input {
    width: 100%;
    height: 100%;
    margin: 0;
    /* 16 (поле) + 18 (лупа) + 12 (отступ до текста) = 46 слева, минус рамка;
       справа место под крестик: 10 + 26 + 8. */
    padding: 0 43px 0 45px;
    box-sizing: border-box;
    border: 0;
    border-radius: 12px;
    background: transparent;
    font-family: inherit;
    font-size: 16px;
    font-weight: 400;
    color: var(--fg);
    outline: 0;
    box-shadow: none;
}

.srchField input::placeholder {
    color: var(--fg-muted);
    opacity: 1;
}

.srchClear {
    position: absolute;
    top: 50%;
    right: 9px;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: none;            /* показывается, только когда есть что стирать */
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 13px;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: color var(--t-fast) linear;
}

.srchClear:hover {
    color: var(--fg);
}

/* ── Заголовок секции ───────────────────────────────────────────────────
 * 17 Medium + счётчик 14 приглушённым по базовой линии.
 */
.srchSecHead {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.srchSecTitle {
    font-size: 17px;
    font-weight: 500;
    color: var(--fg);
}

.srchSecCount {
    font-size: 14px;
    font-weight: 400;
    color: var(--fg-muted);
}

/* «Очистить» в шапке секции прижимается к правому краю. */
.srchSecHead .srchLink {
    margin-left: auto;
}

/* Ссылка-действие: «Очистить», «Показать все адреса — N». */
.srchLink {
    padding: 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 14px;
    color: var(--link);
    text-decoration: underline;
    cursor: pointer;
}

/* ── Стартовый экран ────────────────────────────────────────────────────
 * Без запроса страница не пустая: последние запросы, свои камеры, камеры в
 * доме и адреса. Секции идут с тем же шагом 22, что и всё на странице.
 */
.srchStart,
.srchOut {
    display: flex;
    flex-direction: column;
}

.srchStart {
    gap: 22px;
}

/* Выдача: счётчик и группы по адресу — шаг 20. */
.srchOut {
    gap: 20px;
}

.srchSec {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.srchSec_hist {
    gap: 10px;
}

.srchSec_addr {
    gap: 8px;
}

.srchHint,
.srchCount {
    font-size: 13px;
    color: var(--fg-muted);
}

.srchEmptyHelp {
    font-size: 14px;
    color: var(--fg-muted);
}

/* ── Чипы истории ───────────────────────────────────────────────────────
 * В десктопе ширина чипа = ширина текста + 26 (или + 46 с крестиком):
 * 13 слева, 13 справа, а у удаляемого справа 33 — место под крестик 12 с
 * отступом 10.
 */
.srchChips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.srchChip {
    position: relative;
    height: 32px;
    display: inline-flex;
    align-items: center;
    padding: 0 33px 0 13px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: transparent;
    font-family: inherit;
    font-size: 13px;
    font-weight: 400;
    line-height: 1;
    color: var(--fg-muted);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

.srchChip:hover {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

/* Зона нажатия крестика — последние 26 px ширины, как в десктопе. */
.srchChipDel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 26px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 9px;   /* 10 от внешнего края минус рамка чипа */
    box-sizing: border-box;
    color: inherit;
}

/* ── Сетка плиток ───────────────────────────────────────────────────────
 * Целевая ширина плитки 250, зазор 16. auto-fill с minmax даёт ровно тот же
 * подсчёт колонок, что floor((width + spacing) / (250 + spacing)) в QML.
 */
.srchGrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 16px;
}

.srchTile {
    position: relative;
    min-width: 0;
    cursor: pointer;
}

/* Подложка наведения — с запасом 6 вокруг плитки, чтобы кадр не упирался
   в её край. */
.srchTile::before {
    content: "";
    position: absolute;
    top: -6px;
    right: -6px;
    bottom: -6px;
    left: -6px;
    border-radius: 12px;
    background: transparent;
    transition: background-color var(--t-fast) linear;
}

.srchTile:hover::before,
.srchTile:focus-visible::before {
    background: var(--nav-hover-bg);
}

.srchTile:focus {
    outline: 0;
}

.srchTileShot {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: 10px;
    background: var(--bg-elev);
}

html[data-theme="dark"] .srchTileShot {
    background: var(--bg-deep);
}

.srchTileShot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Подпись под кадром ровно 46: 8 + 18 + 2 + 18. Текст под картинкой, а не
   поверх неё: подпись на кадре всегда спорит с самим кадром. */
.srchTileName,
.srchTileAddr {
    position: relative;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.srchTileName {
    margin-top: 8px;
    font-size: 14px;
    line-height: 18px;
    color: var(--fg);
}

.srchTileAddr {
    margin-top: 2px;
    font-size: 12px;
    line-height: 18px;
    color: var(--fg-muted);
}

/* ── Строки адресов ─────────────────────────────────────────────────────
 * Колонка узкая (≈300): при широкой между адресом и числом камер зияет
 * пустота на пол-экрана.
 */
.srchAddrs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 6px;
}

.srchAddrRow {
    height: 40px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    box-sizing: border-box;
    border: 0;
    border-radius: 8px;
    background: transparent;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--t-fast) linear;
}

.srchAddrRow:hover {
    background: var(--nav-hover-bg);
}

.srchAddrIcon {
    display: block;
    flex: none;
    width: 16px;
    height: 16px;
    color: var(--fg-muted);
}

.srchAddrText {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
    color: var(--fg);
}

.srchAddrCount {
    flex: none;
    font-size: 13px;
    color: var(--fg-muted);
}

/* Контейнер ссылки-переключателя — 34 с отступом 14 слева, как в десктопе. */
.srchAddrMore {
    height: 34px;
    display: flex;
    align-items: center;
    padding-left: 14px;
}

/* ── Выдача ─────────────────────────────────────────────────────────── */
.srchGroup {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.srchGroupHead {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.srchGroupAddr {
    font-size: 17px;
    font-weight: 500;
    color: var(--fg);
}

.srchGroupCount {
    font-size: 14px;
    color: var(--fg-muted);
}

/* Метка конца выдачи: по ней наблюдатель понимает, что пора досыпать
   следующую партию плиток. Своей высоты у пустого блока нет, а нулевой
   IntersectionObserver не увидит. */
.srchMore {
    height: 1px;
}




/* Оформление по образцу десктоп-клиента (../desktop_app, qml/Theme.qml).
 *
 * Файл намеренно называется ui.css: сборщик (tools/build.sh, реплика
 * scripter.php) склеивает css по алфавиту, поэтому он идёт последним и
 * перебивает main.css и theme.css. По мере переоформления экранов
 * заменённые правила выносятся из main.css, а theme.css и login_form.css
 * в конце исчезнут — их роль забирают токены отсюда.
 *
 * Разбор и план — docs/desktop-look-port.md.
 */

/* ── Шрифт ──────────────────────────────────────────────────────────────
 * Roboto 400/500 (Apache-2.0). В main.css уже объявлены Light и Regular под
 * весами 100/300 — те объявления пока нужны старым экранам. Medium 500 в
 * репозитории не было: раньше интерфейс жирного начертания не знал.
 */
@font-face {
    font-family: Roboto;
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url(/assets/fonts/Roboto-Regular.ttf) format("truetype");
}

@font-face {
    font-family: Roboto;
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url(/assets/fonts/Roboto-Medium-cyrillic.woff2) format("woff2");
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
    font-family: Roboto;
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url(/assets/fonts/Roboto-Medium-latin.woff2) format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                   U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                   U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Токены ─────────────────────────────────────────────────────────────
 * Значения перенесены из qml/Theme.qml один в один. Акцент монохромный —
 * край шкалы, а не синий: фирменный синий спорил с синевой ночных кадров.
 */
:root {
    --bg: #ffffff;
    --bg-elev: #eef0f2;
    --bg-deep: #e4e6e9;
    --fg: #1c1e21;
    --fg-muted: #5b6167;
    --accent: #1c1e21;
    --accent-hover: #33373b;
    --accent-fg: #ffffff;
    --link: #1c1e21;
    --border: rgba(0, 0, 0, .10);
    --nav-active-bg: rgba(0, 0, 0, .07);
    --nav-hover-bg: rgba(0, 0, 0, .04);
    /* Подобран под контраст 8,6:1 — не заменять на --fg-muted. */
    --menu-inactive: #3f444a;

    /* Хром поверх видео не зависит от темы: под ним всегда кадр. */
    --overlay-bg: rgba(15, 18, 20, .97);
    --overlay-panel: rgba(31, 33, 36, .94);
    --overlay-btn: #33363b;
    --overlay-btn-hi: #4a4f54;
    --overlay-fg: #ffffff;
    --overlay-muted: rgba(255, 255, 255, .66);
    --overlay-border: rgba(255, 255, 255, .12);
    --overlay-scrim: rgba(15, 18, 20, .92);
    /* Включённая кнопка поверх кадра: чистый белый круг с тёмной иконкой.
       Не --accent: тот в тёмной теме сероват (#e9ebed), а над видео нужен
       именно белый, как в ArchiveBar десктопа. */
    --overlay-accent: #ffffff;
    --overlay-accent-fg: #17191c;

    --ok: rgba(70, 175, 90, .92);
    --err: rgba(200, 60, 60, .92);
    --info: rgba(40, 40, 40, .88);

    /* Цветное осталось ровно там, где цвет несёт смысл. */
    --rec-from: #3a99d9;
    --rec-to: #2e81b7;
    --motion: #ff005d;

    --nav-width: 248px;
    --nav-width-collapsed: 76px;
    --page-pad: 40px;
    --header-h: 84px;

    /* Единственное смягчение во всём интерфейсе — OutCubic. */
    --ease: cubic-bezier(.215, .61, .355, 1);
    --t-fast: 120ms;
    --t-move: 160ms;
}

html[data-theme="dark"] {
    --bg: #17191c;
    --bg-elev: #1f2225;
    --bg-deep: #101214;
    --fg: #e9ebed;
    --fg-muted: #a0a6ac;
    --accent: #e9ebed;
    --accent-hover: #ffffff;
    --accent-fg: #17191c;
    --link: #e9ebed;
    --border: rgba(255, 255, 255, .10);
    --nav-active-bg: rgba(255, 255, 255, .09);
    --nav-hover-bg: rgba(255, 255, 255, .05);
    --menu-inactive: #a0a6ac;
}

/* ── База ───────────────────────────────────────────────────────────────── */
body {
    font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    font-weight: 400;
    color: var(--fg);
    background: var(--bg);
}

.icon {
    display: block;
    flex: none;
}

/* ── Оболочка ───────────────────────────────────────────────────────────
 * Раньше меню было полосой внизу (#wrapper{bottom:47px}), теперь это столбец
 * слева, как в десктопе. Правила старой полосы из main.css удалены.
 */
#wrapper {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

#conttbl {
    display: flex;
    height: 100%;
    width: 100%;
    overflow: hidden;
}

#nav {
    position: relative;
    right: auto;
    left: auto;
    bottom: auto;
    z-index: 5;
    /* Выделять подписи в меню нечего: в десктопе это не текст, а пункты. */
    user-select: none;
    -webkit-user-select: none;
    flex: none;
    width: var(--nav-width);
    display: flex;
    flex-direction: column;
    background: var(--bg-elev);
    border-right: 1px solid var(--border);
    box-shadow: none;
    transition: width var(--t-move) var(--ease);
}

html.nav-collapsed #nav {
    width: var(--nav-width-collapsed);
}

#content {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    height: 100%;
    overflow: auto;
    background: var(--bg);
}

/* Логотип: развёрнутый — полный знак слева, свёрнутый — монограмма по центру.
 * Фирменный знак не перекрашивается под тему: это не наше дело.
 */
#navHead {
    position: relative;
    flex: none;
    height: 92px;
}

#navLogo {
    position: absolute;
    top: 22px;
    left: 20px;
    display: block;
    line-height: 0;
    transition: opacity var(--t-fast) linear;
}

#navLogo img {
    display: block;
}

/* Специфичность не ниже, чем у #navLogo img выше, иначе монограмма покажется
   вместе с полным знаком. */
#navLogo #navLogoMark {
    display: none;
}

html.nav-collapsed #navLogo {
    top: 26px;
    left: 50%;
    transform: translateX(-50%);
}

html.nav-collapsed #navLogo #navLogoFull {
    display: none;
}

html.nav-collapsed #navLogo #navLogoMark {
    display: block;
}

#navCollapse {
    position: absolute;
    top: 32px;
    right: 14px;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

#navCollapse:hover {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

#navCollapse .icon {
    transition: transform var(--t-move) var(--ease);
}

html.nav-collapsed #navCollapse {
    top: 70px;
    right: auto;
    left: 50%;
    transform: translateX(-50%);
}

html.nav-collapsed #navCollapse .icon {
    transform: rotate(180deg);
}

/* ── Пункты меню ───────────────────────────────────────────────────────── */
#vmenu {
    position: relative;
    z-index: auto;
    flex: 1 1 auto;
    width: auto;
    min-height: 0;
    /* Отступ от блока логотипа: 4 развёрнуто, 20 свёрнуто — в свёрнутом виде
       ниже логотипа стоит кнопка разворачивания, и без воздуха первый пункт
       к ней прилипает (SideBar.qml: itemsArea.topMargin). */
    padding-top: 4px;
    overflow-x: hidden;
    overflow-y: auto;
}

html.nav-collapsed #vmenu {
    padding-top: 20px;
}

#vmenu ul {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: auto;
    /* Во всю высоту — иначе «Настройки» не уедут вниз (margin-top:auto). */
    min-height: 100%;
    margin: 0;
    padding: 0 0 20px;
    list-style: none;
    box-sizing: border-box;
}

#vmenu li {
    display: block;
    width: auto;
    position: static;
}

/* «Настройки» — служебный пункт, а не раздел с камерами: отделён воздухом и
   прижат вниз (SideBar.qml: bottomMargin 20, над ним зазор 8). */
#vmenu li.navBottom {
    margin-top: auto;
    padding-top: 8px;
}

#vmenu a {
    position: relative;
    display: flex;
    align-items: center;
    height: 46px;
    margin: 0 13px 0 12px;
    padding: 0 12px 0 16px;
    border-radius: 10px;
    line-height: normal;
    font-size: 15px;
    font-weight: 400;
    color: var(--menu-inactive);
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--t-fast) linear, color var(--t-fast) linear;
}

#vmenu a:hover {
    background: var(--nav-hover-bg);
    color: var(--fg);
}

#vmenu li.activelink {
    border-top: 0;
}

/* Подложку красим ТОЛЬКО на самом пункте. Раньше здесь стоял ещё и `a *`,
   и полупрозрачный фон ложился вторым слоем под иконку и под подпись —
   на пункте проступали два тёмных прямоугольника. */
#vmenu li.activelink a {
    background: var(--nav-active-bg);
    color: var(--fg);
}

#vmenu li.activelink a * {
    background: transparent;
    color: var(--fg);
}

#vmenu li.activelink a .navLabel {
    font-weight: 500;
}

#vmenu .navIcon {
    display: flex;
    flex: none;
    width: 21px;
    height: 21px;
    /* У неактивного пункта иконка приглушённее подписи — так в десктопе
       (иконка fgMuted, подпись menuInactiveText). */
    color: var(--fg-muted);
}

#vmenu a:hover .navIcon,
#vmenu li.activelink .navIcon {
    color: var(--fg);
}

#vmenu .navLabel {
    margin-left: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: opacity var(--t-fast) linear;
}

html.nav-collapsed #vmenu a {
    justify-content: center;
    padding: 0;
}

html.nav-collapsed #vmenu .navLabel {
    display: none;
}

/* ── Вход ───────────────────────────────────────────────────────────────
 * Карточка по центру пустой страницы: ни фоновых картинок, ни градиентов.
 * Прежняя вёрстка задавала размеры в vw, и на широком мониторе карточка
 * росла вместе с окном; здесь всё в пикселях, как в десктопе.
 */
.loginPage {
    min-height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    box-sizing: border-box;
    background: var(--bg);
}

.loginCard {
    width: 400px;
    max-width: 100%;
    padding: 36px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 18px;
    background: var(--bg);
    text-align: center;
}

html[data-theme="dark"] .loginCard {
    background: var(--bg-elev);
}

.loginLogo {
    display: block;
    width: 168px;
    height: 52px;
    margin: 0 auto;
}

.loginTitle {
    margin-top: 24px;
    font-size: 16px;
    font-weight: 500;
    color: var(--fg);
}

.loginCard form {
    margin: 0;
    padding: 0;
}

.loginField {
    position: relative;
    display: block;
    height: 52px;
    box-sizing: border-box;   /* рамка внутрь: в десктопе поле ровно 52 */
    margin-top: 24px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg);
    transition: border-color var(--t-fast) linear;
}

html[data-theme="dark"] .loginField {
    background: var(--bg-deep);
}

.loginField + .loginField {
    margin-top: 10px;
}

.loginField:focus-within {
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);   /* рамка 2 px без скачка раскладки */
}

.loginField input {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0 16px;
    box-sizing: border-box;
    border: 0;
    border-radius: 12px;
    background: transparent;
    font-family: inherit;
    font-size: 15px;
    color: var(--fg);
    outline: 0;
}

.loginField_pass input {
    padding-right: 44px;
}

.loginField input::placeholder {
    color: var(--fg-muted);
    opacity: 1;
}

.loginEye {
    position: absolute;
    top: 50%;
    right: 14px;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: color var(--t-fast) linear;
}

.loginEye[data-checked="true"],
.loginEye:hover {
    color: var(--fg);
}

.loginRow {
    height: 20px;
    margin-top: 14px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}

.loginLink {
    font-size: 13px;
    color: var(--fg-muted);
    text-decoration: underline;
    transition: color var(--t-fast) linear;
}

.loginLink:hover {
    color: var(--fg);
}

/* Место под ошибку держится всегда — иначе карточка прыгала бы. */
.loginError {
    min-height: 32px;
    margin-top: 12px;
    font-size: 13px;
    line-height: 16px;
    color: var(--err);
}

.loginButton {
    width: 100%;
    height: 48px;
    display: block;
    padding: 0;
    border: 0;
    border-radius: 12px;
    background: var(--accent);
    font-family: inherit;
    font-size: 15px;
    font-weight: 500;
    color: var(--accent-fg);
    cursor: pointer;
    transition: background-color var(--t-fast) linear, transform 90ms var(--ease);
}

.loginButton:hover {
    background: var(--accent-hover);
}

/* Кольцо фокуса браузера синее — единственное цветное пятно на экране.
   Оставляем подсветку только для клавиатуры и в цвете палитры. */
.loginButton:focus {
    outline: 0;
}

.loginButton:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.loginButton:active {
    transform: scale(.97);
}

.loginButton[disabled] {
    opacity: .6;
    cursor: default;
}

.loginFoot {
    margin-top: 18px;
    font-size: 13px;
    color: var(--fg-muted);
}

/* ── Шапка раздела ──────────────────────────────────────────────────────
 * Одна геометрия на все разделы: высота 84, заголовок 26 Medium, поле 40.
 * Слот справа занят только на «Панелях» кнопкой «Новая панель».
 */
.pageHeader {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: var(--header-h);
    padding: 0 var(--page-pad);
}

.pageHeader h1 {
    margin: 0;
    font-size: 26px;
    font-weight: 500;
    color: var(--fg);
}


