:root {
  --brand: #2f6fed;
  --sidebar-width: 250px;
}

/* Волнистый синий фон — оригинальный welcome_background.svg из pgAdmin 4
   (PostgreSQL License — копирование/использование разрешено), взят с диска
   из установленного pgAdmin (web/pgadmin/misc/workspaces/static/img/).
   У самого pgAdmin он в CSS используется как no-repeat/center БЕЗ растяжения
   (background-size не задан, т.е. auto — натуральный размер 800x282) —
   "cover" тут исказил бы пропорции волн, поэтому используем "contain"
   (вписываем целиком, без обрезки и без искажения, по аналогии с оригиналом,
   адаптированной под фон на весь экран, а не маленькую панель, как в
   pgAdmin). background-attachment: fixed — при скролле длинных таблиц волны
   не "едут" вместе с контентом. Карточки/таблицы/сайдбар поверх него все с
   непрозрачным фоном (см. .surface-card, .sidebar, .topbar ниже) —
   читаемость не страдает. */
body {
  background-color: #0c0f14;
  background-image: url('/assets/wave-bg.svg');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  background-attachment: fixed;
}

/* --- App shell: sidebar + content --- */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  /* "Стекло" — полупрозрачный фон + небольшое размытие (легче, чем у
     карточек ниже, чтобы меню оставалось четко читаемым, а не "мутным"). */
  background: rgba(22, 27, 34, 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-right: 1px solid rgba(255, 255, 255, .06);
  color: #cbd2d9;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 20px;
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.sidebar-nav {
  display: flex;
  flex-direction: column;
  padding: 12px 8px;
  gap: 2px;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: #cbd2d9;
  text-decoration: none;
  font-size: 14px;
}
.sidebar-link:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.sidebar-link.active { background: var(--brand); color: #fff; }
.sidebar-sublink { padding-left: 30px; font-size: 13px; }
.sidebar-group-label { padding: 10px 12px 2px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }

.app-content {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .06);
  /* Та же "стеклянная" логика, что у .sidebar — топбар визуально часть меню. */
  background: rgba(22, 27, 34, 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar .spacer { flex: 1; }

@media (max-width: 991.98px) {
  .sidebar {
    position: fixed;
    left: -100%;
    z-index: 1040;
    transition: left .2s ease;
  }
  .sidebar.sidebar-open { left: 0; }
}

.page-main {
  max-width: 1180px;
  margin: 0 auto;
  padding: 24px 16px 48px;
  width: 100%;
}

.page-title {
  font-weight: 600;
  margin-bottom: 1.25rem;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* --- Login pages --- */
/* Фон уже задан глобально на body (см. начало файла) — здесь только раскладка. */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.login-card {
  width: 100%;
  max-width: 380px;
  border: none;
  border-radius: 16px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}
.login-card .card-body {
  padding: 2.25rem;
}
.login-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin: 0 auto 1rem;
}

/* Спиннер загрузки 3D-вьювера (GaussianSplats3D) генерирует свои стили на
   лету с цветом #07e8d6 (бирюзовый) прямо в JS — классы у него с числовым
   суффиксом, который меняется при каждом новом вьювере (spinner0, spinner1,
   ...), точечно через id не перебить. Кольцо-индикатор — единственный
   элемент, у которого класс начинается на "spinner" и НЕ содержит
   "Container" (контейнеры/подложка — это spinnerOuterContainerN,
   spinnerContainerPrimaryN, spinnerContainerMinN), поэтому переопределяем
   по этому признаку, специфичность выше, чем у их .spinnerN { ... }.
   ВАЖНО: ":not([class*='-'])" — у классов Bootstrap (spinner-border,
   spinner-grow, используются в LAS-вьювере) есть дефис, а у
   GaussianSplats3D — нет (просто "spinnerN"); без этого исключения
   правило ниже заливало бы Bootstrap-спиннер сплошным фоном вместо
   вращающегося кольца (был виден просто залитый круг без анимации). */
[class^="spinner"]:not([class*="Container"]):not([class*="-"]) {
  background: var(--brand) !important;
}

/* Серая подложка-квадрат вокруг спиннера (spinnerContainerPrimaryN —
   "развёрнутый" режим, spinnerContainerMinN — нижняя плашка) — тот же
   LoadingSpinner.js, background-color: rgba(128,128,128,.75) + рамка
   #666666 захардкожены инлайн-стилем. Убираем и то, и то. */
[class*="spinnerContainerPrimary"],
[class*="spinnerContainerMin"] {
  background-color: transparent !important;
  border: none !important;
}

/* --- Индикаторы загрузки (прогресс-бар выгрузки файлов тура) — фирменный
   синий, а не дефолтный/случайно зелёный --- */
.progress-bar { background-color: var(--brand) !important; }

/* --- Status pills --- */
.status-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 4px; font-size: 12px; font-weight: 600; color: #fff; }
.status-pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.status-online  { background: #1b4d1f; } /* тёмно-зелёный */
.status-offline { background: #6b1226; } /* бордовый */
.status-unknown { background: #8a94a6; }

/* --- Окно 3D-вьювера тура: не на весь экран, а доля размера окна
   браузера, по центру — и тот же "стеклянный" фон, что у карточек на
   остальных страницах (а не сплошной непрозрачный, как было раньше при
   modal-fullscreen). За пределами модалки остаётся видна обычная страница
   с волнистым фоном, как везде в кабинете. 90% — по запросу пользователя
   (было 75%, мало места под 3D + Settings Panel). Центрирование — классом
   modal-dialog-centered на самом .modal-dialog (см. map.php), здесь только
   размер; margin сюда добавлять не нужно — он мешает flex-центрированию
   bootstrap, отсюда и был баг с нецентрированной модалкой на мобильном. */
.tour-viewer-dialog {
  width: 90vw;
  max-width: 90vw;
  height: 90vh;
}
.tour-viewer-dialog .modal-content {
  height: 100%;
  background: rgba(27, 32, 40, 0.6);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(255, 255, 255, .06);
}
/* Мобильный override для .tour-viewer-dialog перенесён в блок
   "@media (max-width: 575.98px)" ниже вместе с остальными xs-правилами. */

/* --- Map --- */
.map-card { border: none; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 18px rgba(15, 23, 42, .06); }
#map { height: 70vh; min-height: 420px; }
.map-card.map-card-sm #map { height: 280px; min-height: 280px; }
.legend { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; padding: 10px 16px; background: var(--bs-card-bg, var(--bs-body-bg)); border-top: 1px solid var(--bs-border-color); }
.legend-note { margin-left: auto; color: #6b7280; font-size: 13px; }
.station-marker span { display: block; width: 16px; height: 16px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 3px rgba(0,0,0,.5); }

/* --- Cards / tables shared --- */
/* Карточки — тоже "стекло", но более мутное/размытое, чем меню (.sidebar/
   .topbar выше) — больше blur, чтобы блоки выглядели подложкой, а не просто
   тонировкой. Правим сам .card, а не только .surface-card, чтобы эффект был
   на всех карточках (map-card, login-card и т.д.), не задавая его на каждой
   по отдельности. */
.card {
  background: rgba(27, 32, 40, 0.6);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(255, 255, 255, .06);
}
.surface-card { border: none; border-radius: 16px; box-shadow: 0 4px 18px rgba(15, 23, 42, .06); }
/* .table-responsive ставит overflow-x:auto — по спецификации CSS это
   неявно превращает И overflow-y в auto (если для оси, отличной от
   overflow-x, явно не указано что-то своё), из-за чего контекстное меню
   действий тура обрезалось по вертикали этим же контейнером, едва
   показывая первый пункт. tours.php добавляет этот класс рядом —
   принудительно держим overflow-y видимым, горизонтальный скролл (для
   узких экранов) при этом не теряется. */
.table-responsive.overflow-y-visible { overflow-y: visible; }
.table-clean th { font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: #6b7280; border-top: none; }
.table-clean td { vertical-align: middle; }
/* Строки таблицы — без СВОЕГО фона, чтобы сквозь них было видно тот же
   "стеклянный" блюр карточки (.card выше), а не плоский цвет Bootstrap
   (--bs-table-bg/--bs-table-striped-bg и т.п.) поверх него — иначе на
   тёмной теме получается видимый шов между размытой карточкой и плоской
   таблицей внутри неё. Селектор бьёт собственную специфичность Bootstrap
   у ячеек (.table > :not(caption) > * > *), просто transparent не
   перекрыл бы её. class="table-hover" не используется (см. tours.php),
   поэтому подсветка при наведении ниже — наша же лёгкая накладка, а не
   переопределение чужой.
*/
.table-clean,
.table-clean > :not(caption) > * > * {
  background-color: transparent !important;
}
.table-clean > tbody > tr:hover > * {
  background-color: rgba(255, 255, 255, .04) !important;
}

/* Поля форм — тот же принцип: полупрозрачный однородный фон вместо
   сплошного Bootstrap-цвета, чтобы выглядеть частью той же "стеклянной"
   карточки, а не отдельными непрозрачными блоками на ней. */
.form-control,
.form-select,
textarea.form-control {
  background-color: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .12);
  color: #e5e7eb;
}
.form-control:focus,
.form-select:focus {
  background-color: rgba(255, 255, 255, .08);
  border-color: var(--brand);
  color: #fff;
  box-shadow: 0 0 0 .2rem rgba(47, 111, 237, .25);
}
.form-control::placeholder { color: rgba(229, 231, 235, .45); }
.form-control:disabled, .form-select:disabled { background-color: rgba(255, 255, 255, .03); }
/* Раскрытый список <select> — браузер рисует его как НАТИВНЫЙ попап, а не
   часть страницы: на него не действует backdrop-filter/блюр карточки под
   ним, поэтому полупрозрачный rgba(255,255,255,.05) у .form-select выше
   (рассчитанный на просвечивающий тёмный фон страницы) в самом попапе
   выглядел почти белым. <option> нужен СВОЙ непрозрачный тёмный фон. */
.form-select option {
  background-color: #1b2028;
  color: #e5e7eb;
}

/* === Мобильная оптимизация === */

/* Тёмная шторка за открытым сайдбаром на мобильных — закрывает по тапу */
#sidebarBackdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .5);
  z-index: 1039;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#sidebarBackdrop.show { display: block; }

@media (max-width: 575.98px) {
  /* Меньше внутренних отступов на малых экранах */
  .page-main { padding: 12px 10px 28px; }

  /* Карта: min-height слишком велик для коротких телефонов (~568 px высоты) */
  #map { height: 55vh; min-height: 260px; }

  /* Плеер тура — полноэкранный на xs */
  .tour-viewer-dialog {
    width: 100vw;
    max-width: 100vw;
    /* svh учитывает адресную строку браузера, которая убирается при скролле */
    height: 100svh;
    margin: 0;
  }
  .tour-viewer-dialog .modal-content { border-radius: 0; }

  /* Панель слоёв в плеере: 300px слишком широко для 360 px экрана */
  #tourLayersPanel { width: calc(100vw - 24px) !important; }

  /* Подсказка управления мышью: ограничить ширину */
  #tourMouseHelp { max-width: calc(100vw - 48px) !important; }
}

@media (max-width: 767.98px) {
  /* Топбар: меньше горизонтальный отступ и gap */
  .topbar { padding: 8px 12px; gap: 4px; }

  /* Заголовок страницы */
  .page-title { font-size: 1rem; gap: 6px; margin-bottom: 1rem; }

  /* Кнопки в ячейках таблицы — удобный размер для касания */
  .table td .btn-sm { min-width: 32px; min-height: 34px; padding: 4px 6px; }

  /* Кнопки формы RINEX — переносить на новую строку, а не обрезать */
  .rinex-action-row { flex-wrap: wrap; row-gap: 8px !important; }

  /* my_tours: скрыть колонку "Описание" — редактирование удобно только с ПК */
  .my-tours-desc-col { display: none !important; }

  /* Логин: чуть меньше padding карточки */
  .login-card .card-body { padding: 1.75rem; }
}
