/* Карта поездок — оформление.
   Светлая и тёмная темы на одном наборе переменных: цвета объявлены один раз,
   разметка про тему ничего не знает. Карта занимает основную площадь,
   слева — фильтруемый список. Сезоны имеют собственные цвета и используются
   одинаково в списке, на карте и в круговом календаре, чтобы взгляд связывал
   их без легенды. */

/* Палитра. По умолчанию — светлая тема; тёмная включается системной
   настройкой либо вручную переключателем в шапке (атрибут data-theme
   на <html> перебивает системную настройку в обе стороны). */
:root {
  color-scheme: light;

  --bg: #eef1f6;
  --bg-panel: #ffffff;
  --bg-raise: #f4f6fa;
  --bg-input: #ffffff;
  --bg-select: #e6f2f2;
  --line: #d5dde8;
  --line-soft: #e4e9f1;
  --line-strong: #b3c0d2;
  --btn-hover-bg: #e9edf4;

  --text: #1a2130;
  --text-dim: #5a6880;
  /* Приглушённый текст: метки полей, страна на карточке, подписи источников.
     Прежний #8492a8 давал на приподнятом фоне 2.9:1 — ниже порога 4.5:1
     для мелкого текста. Иерархия сохраняется: тише --text, но читаемо. */
  --text-faint: #636e7e;

  --visited: #10827f;
  --visited-hover: #0c6d6a;
  --planned: #b8761b;
  --danger: #c4413c;
  --idle: #94a3b8;
  --on-accent: #ffffff;
  /* Чернила для оранжевой плашки. Одно значение на обе темы: --planning-ring
     светлый и там и там, и белый текст давал на нём 2.3:1 — нечитаемо. */
  --on-planning: #1c1205;

  /* Оценка локации: последовательная шкала одного тона. Фиолетовый не занят
     ни состояниями, ни сезонами, поэтому не путается с ними на карте. */
  --rate-1: #b39ddb;
  --rate-2: #7e57c2;
  --rate-3: #4527a0;

  /* Маршруты красятся по состоянию своего места, а не по оценке: след ведёт
     туда, куда ведёт, и ступени оценки о нём ничего не говорят.

     Три цвета и строгий порядок старшинства — цвет у линии один, а состояний
     у места два независимых, и они могут совпасть на одном месте:
     оранжевый (планирую) > чёрный (был) > серый (всё остальное).

     Оранжевый взят тот же, что у каймы планов на метке: одно и то же
     состояние не должно быть на карте двух разных цветов. Серый — тот же
     --idle, которым помечено «больше не существует». */
  --route-planned: #e2620f;
  --route-visited: #10141c;
  --route-other: #94a3b8;

  /* Кайма планов у локации. Отдельно от --planned: тот остаётся янтарным
     цветом ромба территории, а кайме нужен собственный оранжевый. */
  --planning-ring: #e2620f;

  --winter: #3a7dc4;
  --spring: #3c975c;
  --summer: #bd8a1f;
  --autumn: #c15b3d;

  --map-ocean: #d9e5f0;
  --country-fill: #fbfcfe;
  --country-stroke: #b9c6d6;
  --marker-halo: #ffffff;
  --marker-outline: #1a2130;
  --attrib-bg: rgba(255, 255, 255, 0.82);

  --tick: #c6d0de;
  --tick-strong: #a3b1c5;
  --lane-guide: rgba(26, 33, 48, 0.04);
  --arc-label: #ffffff;

  --shadow-strong: rgba(26, 33, 48, 0.16);
  --shadow-soft: rgba(26, 33, 48, 0.14);

  /* Значки ссылок. Заливка цветом сервиса, буква белая: на двадцати пикселях
     цветная буква на светлом фоне читается хуже, чем белая на цветном.
     Проверено: буква к заливке не ниже 5:1, заливка к фону карточки — 4.8:1. */
  --link-g: #1667d2;
  --link-ya: #c42b00;
  --link-w: #4a4f53;
  --link-o: #3f7a33;
  --link-ink: #ffffff;


  --radius: 10px;
  --radius-sm: 7px;
  --topbar-h: 60px;
  --sidebar-w: 370px;
  --cards-w: 340px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* Тёмная тема: системная настройка — если пользователь не выбрал светлую явно. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0d1017;
    --bg-panel: #141924;
    --bg-raise: #1b2230;
    --bg-input: #10151f;
    --bg-select: #1e2836;
    --line: #263041;
    --line-soft: #1c2432;
    --line-strong: #33405a;
    --btn-hover-bg: #232c3d;

    --text: #e8edf5;
    --text-dim: #94a2b8;
    --text-faint: #778298;

    --visited: #5bc0be;
    --visited-hover: #6fd0ce;
    --planned: #e0a458;
    --danger: #e5615e;
    --idle: #64748b;
    --on-accent: #06231f;

    --rate-1: #6b52b8;
    --rate-2: #9575cd;
    --rate-3: #d1c4e9;

    /* Чёрная линия на тёмной карте (--country-fill здесь #1a2231) не видна
       вовсе. Роль у этого цвета — наибольшая различимость на подложке, и в
       тёмной теме её играют светлые чернила, а не чёрные. */
    --route-planned: #ff8a3d;
    --route-visited: #e8edf5;
    --route-other: #64748b;

    --planning-ring: #ff8a3d;

    --winter: #6aa9e9;
    --spring: #6ec98a;
    --summer: #e8b44a;
    --autumn: #e07a5f;

    --map-ocean: #0a0d13;
    --country-fill: #1a2231;
    --country-stroke: #2b3548;
    --marker-halo: #0d1017;
    --marker-outline: #ffffff;
    --attrib-bg: rgba(13, 16, 23, 0.8);

    --tick: #2a344a;
    --tick-strong: #3b4863;
    --lane-guide: rgba(255, 255, 255, 0.028);
    --arc-label: #0d1017;

    --shadow-strong: rgba(0, 0, 0, 0.45);
    --shadow-soft: rgba(0, 0, 0, 0.5);

    /* На тёмном те же цвета стали бы пятнами: заливка светлеет, буква темнеет. */
    --link-g: #6fa8f0;
    --link-ya: #ff9270;
    --link-w: #a3acb6;
    --link-o: #86c477;
    --link-ink: #0d1017;

  }
}

/* …и та же тёмная тема, выбранная переключателем вручную. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0d1017;
  --bg-panel: #141924;
  --bg-raise: #1b2230;
  --bg-input: #10151f;
  --bg-select: #1e2836;
  --line: #263041;
  --line-soft: #1c2432;
  --line-strong: #33405a;
  --btn-hover-bg: #232c3d;

  --text: #e8edf5;
  --text-dim: #94a2b8;
  --text-faint: #778298;

  --visited: #5bc0be;
  --visited-hover: #6fd0ce;
  --planned: #e0a458;
  --danger: #e5615e;
  --idle: #64748b;
  --on-accent: #06231f;

  --rate-1: #6b52b8;
  --rate-2: #9575cd;
  --rate-3: #d1c4e9;

  --route-planned: #ff8a3d;
  --route-visited: #e8edf5;
  --route-other: #64748b;

  --planning-ring: #ff8a3d;

  --winter: #6aa9e9;
  --spring: #6ec98a;
  --summer: #e8b44a;
  --autumn: #e07a5f;

  --map-ocean: #0a0d13;
  --country-fill: #1a2231;
  --country-stroke: #2b3548;
  --marker-halo: #0d1017;
  --marker-outline: #ffffff;
  --attrib-bg: rgba(13, 16, 23, 0.8);

  --tick: #2a344a;
  --tick-strong: #3b4863;
  --lane-guide: rgba(255, 255, 255, 0.028);
  --arc-label: #0d1017;

  --shadow-strong: rgba(0, 0, 0, 0.45);
  --shadow-soft: rgba(0, 0, 0, 0.5);

  /* На тёмном те же цвета стали бы пятнами: заливка светлеет, буква темнеет. */
  --link-g: #6fa8f0;
  --link-ya: #ff9270;
  --link-w: #a3acb6;
  --link-o: #86c477;
  --link-ink: #0d1017;

}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
}

h2, h3 { margin: 0; font-weight: 600; }
code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--bg-input);
  padding: 1px 5px;
  border-radius: 4px;
}
.muted { color: var(--text-dim); }

.hint {
  margin: 6px 0 0;
  color: var(--text-faint);
  font-size: 12px;
  line-height: 1.45;
}

/* Строго после .hint: специфичность у них одинаковая, и правило, стоящее
   выше, проигрывает — предупреждение оставалось серым. */
.hint--warn { color: var(--planned); }

/* Отказ, а не предупреждение: тем же цветом, что и кайма негодного поля. */
.hint--error { color: var(--danger); }

/* ── верхняя панель ─────────────────────────────────────────────────────── */

.topbar {
  display: flex;
  align-items: center;
  gap: 20px;
  height: var(--topbar-h);
  flex: 0 0 var(--topbar-h);
  padding: 0 18px;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.brand__mark {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--planned);
  position: relative;
}

.brand__mark::after {
  content: '';
  position: absolute;
  top: -4px;
  left: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--visited);
}

.topbar__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/*
  Совсем узкий экран: 320 px — это iPhone SE первых лет и любой телефон,
  раскрытый в половину экрана.

  Здесь шапка перестаёт помещаться: название плюс пять кнопок просят 385 px, и
  документ раздвигается — страница начинает ездить вбок. Убираем НАЗВАНИЕ, а
  не кнопки: значок рядом остаётся, и по нему видно, куда попал, а кнопки —
  единственный способ что-то сделать.

  Заодно разрешаем шапке сжимать отступы: восемь пикселей между пятью
  кнопками — это сорок пикселей, восьмая часть такого экрана.
*/
@media (max-width: 400px) {
  /* Шапке дано переноситься на две строки. Уместить всё в одну не выходит:
     пять кнопок просят 357 px при окне в 320, и документ начинал ездить вбок.
     Спрятать часть кнопок было бы хуже — они единственный способ что-то
     сделать; свернуть их в значки тоже, подписи на телефоне нужнее всего.

     Высота при этом перестаёт быть постоянной, а от неё отсчитывается панель
     редактирования (.drawer, position: fixed). Настоящую высоту измеряет и
     кладёт в эту же переменную watchTopbarHeight в app.js — здесь только
     разумное значение на те мгновения, пока скрипт не отработал. */
  :root { --topbar-h: 96px; }

  .topbar {
    flex-wrap: wrap;
    align-content: center;
    height: auto;
    min-height: var(--topbar-h);
    flex: 0 0 auto;
    gap: 6px 8px;
    padding: 8px 10px;
  }

  .topbar__actions { margin-left: 0; gap: 4px; flex-wrap: wrap; }
  .brand__name { display: none; }
}

/* ── где сейчас правки ──────────────────────────────────────────────────── */

/* Признак состояния согласования с сервером. Нарочно не кнопка по виду:
   это прежде всего надпись, хотя по ней и открывается окно Data. */
/* ── экран входа ────────────────────────────────────────────────────────── */

/*
  Перекрывает собой весь сайт, а не прячет его части по одной: пока вход не
  подтверждён, показывать нечего вовсе — данных в браузере больше не лежит.

  Фон непрозрачный. Полупрозрачный поверх карты выглядел бы нарядно, но карта
  под ним пустая, и сквозь неё видно ровно ничего.

  z-index выше ВСЕГО, что рисует сайт и Leaflet. Стоял 60 — ниже слоёв карты
  (400) и её контролов (1000), — и экран входа разъезжался: поверх него шли
  контуры стран, легенда, кнопка слоёв, масштаб. Поймать это нажатием нельзя:
  слои карты помечены pointer-events:none, и elementFromPoint показывает под
  ними форму входа, будто всё в порядке. Видно только глазом — и проверка в
  t12 теперь тоже смотрит, а не щупает.
*/
.signin {
  position: fixed;
  inset: 0;
  z-index: 1250;
  display: grid;
  place-items: center;
  padding: 20px;
  background: var(--bg);
}

.signin[hidden] { display: none; }

.signin__box {
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 26px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 12px);
}

.signin__box .field { display: flex; flex-direction: column; gap: 5px; }
.signin__box .field > span { font-size: 12px; color: var(--text-dim); }

.signin__error {
  margin: 0;
  min-height: 1.2em;
  font-size: 12px;
  color: var(--danger);
}

.brand--big { gap: 10px; margin-bottom: 4px; font-size: 15px; }

/* Кнопка выхода: значок плюс слово, на узком экране — один значок. Шапка и
   без того тесная: четыре кнопки, переключатель темы и название. */
.signout { display: inline-flex; align-items: center; gap: 6px; }

@media (max-width: 820px) {
  .signout__text { display: none; }
}

/* Ссылка на исходный файл в строке маршрута. Это <a>, а не кнопка, поэтому
   выравнивание приходится задавать самим: у ссылки нет ни line-height кнопки,
   ни её вертикального центрирования. */
.route-row__file {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  text-decoration: none;
  font-weight: 600;
}

/* ── строки сводки в разделе «Данные» ───────────────────────────────────── */

.data-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}

.data-row:last-child { border-bottom: none; }
.data-row > span { color: var(--text-dim); }
.data-row > b { font-weight: 600; text-align: right; }

/* ── кнопки и поля ──────────────────────────────────────────────────────── */

.btn {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--bg-raise);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  padding: 7px 13px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  white-space: nowrap;
}

.btn:hover { background: var(--btn-hover-bg); border-color: var(--line-strong); }
.btn:active { transform: translateY(1px); }

.btn--primary {
  background: var(--visited);
  border-color: var(--visited);
  color: var(--on-accent);
  font-weight: 600;
}
.btn--primary:hover { background: var(--visited-hover); border-color: var(--visited-hover); }

.btn--ghost { background: transparent; }
.btn--ghost:hover { background: var(--bg-raise); }

/* Оттенки берём из самого --danger, а не подбираем константами: иначе они
   верны ровно в одной теме, а во второй ховер уезжает в чужой цвет. */
.btn--danger { color: var(--danger); border-color: var(--line); }
.btn--danger:hover { background: var(--bg-raise); border-color: var(--danger); }
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .btn--danger { border-color: color-mix(in srgb, var(--danger) 38%, transparent); }
  .btn--danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }
}
.btn--danger:disabled { color: var(--text-faint); border-color: var(--line-soft); }

.file-btn { display: inline-flex; align-items: center; }

.btn--icon {
  padding: 7px 10px;
  line-height: 0;
  min-width: 36px;
  color: var(--text-dim);
}

.btn--icon:hover { color: var(--text); }

.input {
  width: 100%;
  background: var(--bg-input);
  border: 1px solid var(--line);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
}

/* ── меню точки по правому щелчку ───────────────────────────────────────── */

.map-menu {
  position: absolute;
  z-index: 1200;
  min-width: 230px;
  padding: 5px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 32px var(--shadow-strong);
  font-size: 12px;
}

.map-menu__caption {
  padding: 5px 8px 3px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-faint);
}

.map-menu__item {
  display: block;
  width: 100%;
  padding: 5px 8px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

/* Два класса подряд не случайно: внутри карты действует леафлетовское
   `.leaflet-container a`, оно специфичнее одиночного класса, и ссылки на
   чужие карты становились синими вопреки теме. */
.map-menu .map-menu__item { color: var(--text); }
.map-menu__item:hover { background: var(--bg-raise); }
.map-menu__value { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.map-menu__hint {
  display: block;
  margin-top: 1px;
  font-size: 10px;
  color: var(--text-faint);
}

.map-menu__sep { margin: 4px 0; border-top: 1px solid var(--line-soft); }

/* Номер масштаба между кнопками зума. */
.leaflet-control-zoom-display {
  height: 22px;
  line-height: 22px;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
  background: var(--bg-panel);
  border-bottom: 1px solid var(--line-soft);
}

/* Линейка расстояний над кнопками зума.

   Ширину задаёт сам Leaflet, инлайном, и трогать её нельзя: ширина полоски и
   есть измеренное расстояние, в этом весь смысл. Здесь только цвета, шрифт и
   форма скобки. */
.leaflet-control-scale {
  margin-bottom: 8px !important;
}

.leaflet-control-scale-line {
  /* Скобка, а не плашка: боковые чёрточки — это засечки по краям отрезка,
     нижняя — сама линейка. Углов не скругляем нарочно, хотя все остальные
     панели карты скруглены: скруглённая засечка перестаёт показывать, где
     кончается отрезок, а ширина здесь и есть измеренная величина. */
  border: 1px solid var(--line-strong);
  border-top: none;
  border-radius: 0;
  background: var(--bg-panel);
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 16px;
  padding: 1px 5px 2px;
  text-align: center;
  text-shadow: none;
  box-shadow: 0 1px 5px var(--shadow-soft);
}

.popup__row { margin-top: 7px; }

/* ── панель слоёв ───────────────────────────────────────────────────────── */

.layers {
  background: var(--bg-panel);
  border-radius: var(--radius-sm);
  box-shadow: 0 1px 5px var(--shadow-soft);
  overflow: hidden;
}

.layers__toggle {
  display: block;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: var(--bg-panel);
  color: var(--text-dim);
  cursor: pointer;
}

.layers__toggle:hover { background: var(--bg-raise); color: var(--text); }

.layers__body {
  min-width: 190px;
  max-width: 260px;
  padding: 8px 10px 10px;
  border-top: 1px solid var(--line-soft);
}

.layers__group + .layers__group {
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--line-soft);
}

.layers__row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 0;
  font-size: 13px;
  cursor: pointer;
}

.layers__title { flex: 1; min-width: 0; }

/* Пометка у накладки, которая закрывает подложку: без неё человек гадает,
   почему смена подложки под ней ничего не меняет. */
.layers__note {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-faint);
  white-space: nowrap;
}

.layers__config {
  margin-top: 9px;
  width: 100%;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.layers__config:hover { background: var(--bg-raise); color: var(--text); }

/* Контур покрытия локального слоя. */
.coverage {
  stroke: var(--planning-ring);
  fill: var(--planning-ring);
  cursor: pointer;
}

/* ── окно слоёв ─────────────────────────────────────────────────────────── */

.dialog__section {
  margin: 18px 0 8px;
  font-size: 13px;
  font-weight: 600;
}

.layer-config { display: flex; flex-direction: column; }

.layer-config__row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 13px;
}

.layer-config__pick {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.layer-config__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.layer-config__marks { color: var(--text-faint); font-size: 11px; white-space: nowrap; }

.custom-layer .field + .field { margin-top: 10px; }
.custom-layer .row .field + .field { margin-top: 0; }

.field--check {
  display: flex;
  align-items: center;
  gap: 6px;
  align-self: flex-end;
  padding-bottom: 8px;
  font-size: 13px;
  white-space: nowrap;
}

/* ── координаты ─────────────────────────────────────────────────────────── */

.copy-wrap { position: relative; display: inline-flex; }

/* Меню показывает сами записи точки, а не их названия: выбирать по
   «ddd°mm.mmm′» значит держать форматы в голове, по готовой строке — читать. */
.copy-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 262px;
  padding: 4px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 28px var(--shadow-strong);
}

/* Запись и её название — в столбик: пара в градусах, минутах и секундах не
   помещается в строку рядом с подписью, а перенос посреди координаты читается
   как две разные. */
.copy-menu__item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: 7px 9px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.copy-menu__item:hover { background: var(--bg-raise); }
.copy-menu__value { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.copy-menu__label { color: var(--text-faint); font-size: 11px; white-space: nowrap; }

/* ── выгрузка списка ────────────────────────────────────────────────────── */

.export-wrap { position: relative; display: inline-flex; }

/* Та же раскладка, что у меню форматов координат: расширение и строкой ниже —
   куда оно годится. Читать «.gpx — навигаторы и часы» проще, чем помнить. */
.export-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 290px;
  padding: 4px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 28px var(--shadow-strong);
}

.export-menu__item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  width: 100%;
  padding: 7px 9px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.export-menu__item:hover { background: var(--bg-raise); }
.export-menu__value { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.export-menu__label { color: var(--text-faint); font-size: 11px; }

.coords-choice {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 7px;
}

.coords-choice__label { font-size: 12px; color: var(--text-faint); }
.coords-choice__option { font-size: 12px; padding: 4px 9px; }
.coords-choice__option.is-active {
  border-color: var(--visited);
  background: var(--bg-select);
}

/* Найденная поиском точка. Нарочно не карточка: это ещё не место в наборе,
   а ответ на вопрос «где это». */
.coord-hits { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }

/* Сетка, а не строка: запись в градусах и минутах длиннее колонки карточек,
   и в одной строке с кнопкой она ломалась бы посреди координаты. */
.coord-hit {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 3px 9px;
  padding: 9px 11px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg-raise);
  cursor: pointer;
}

.coord-hit:hover { border-color: var(--visited); }

.coord-hit__mark {
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 2px solid var(--visited);
}

.coord-hit__text {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.coord-hit__sub {
  grid-column: 2 / -1;
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text-faint);
}

/* Негодное значение остаётся в поле: стереть введённое — значит заставить
   набирать заново, не показав, что именно было не так. */
.input.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 18%, transparent);
}

.input:focus {
  outline: none;
  border-color: var(--visited);
  box-shadow: 0 0 0 2px rgba(91, 192, 190, 0.16);
}

textarea.input { resize: vertical; min-height: 60px; }
select.input { cursor: pointer; }

.field { display: block; }
.field + .field { margin-top: 12px; }

.field__label {
  display: block;
  margin-bottom: 5px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-faint);
}

.row { display: flex; gap: 8px; align-items: flex-end; }
.row > .field { flex: 1; margin-top: 0; }
.row--wrap { flex-wrap: wrap; margin-top: 10px; }

.checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
}

.segmented {
  display: inline-flex;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 2px;
  gap: 2px;
}

.segmented button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 13px;
  padding: 6px 12px;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
}

.segmented button:hover { color: var(--text); }
.segmented button.is-active { background: var(--bg-raise); color: var(--text); }
.segmented--small button { font-size: 12px; padding: 5px 10px; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  appearance: none;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  cursor: pointer;
}

.chip:hover { color: var(--text); border-color: var(--line-strong); }
.chip.is-active { color: var(--text); border-color: currentColor; }
.chip.season-winter.is-active { color: var(--winter); background: rgba(106, 169, 233, 0.14); }
.chip.season-spring.is-active { color: var(--spring); background: rgba(110, 201, 138, 0.14); }
.chip.season-summer.is-active { color: var(--summer); background: rgba(232, 180, 74, 0.14); }
.chip.season-autumn.is-active { color: var(--autumn); background: rgba(224, 122, 95, 0.14); }
.chip--tag.is-active { color: var(--visited); background: rgba(91, 192, 190, 0.12); }

/* Звёзды берут цвет ровно у маркеров на карте — одна звезда в фильтре и
   одна звезда на карте должны быть одного оттенка, иначе фильтр придётся
   сопоставлять с легендой в уме. */
.chip--rating { letter-spacing: 1px; }
.chip--rating.is-rated-1 { color: var(--rate-1); }
.chip--rating.is-rated-2 { color: var(--rate-2); }
.chip--rating.is-rated-3 { color: var(--rate-3); }

/* У активного подпись остаётся текстовой: первый оттенок бледный, и красить
   им буквы значило бы менять читаемость от кнопки к кнопке. Цвет уходит
   в рамку и подложку. */
.chip--rating.is-active { color: var(--text); border-color: currentColor; }
.chip--rating.is-rated-1.is-active { border-color: var(--rate-1); }
.chip--rating.is-rated-2.is-active { border-color: var(--rate-2); }
.chip--rating.is-rated-3.is-active { border-color: var(--rate-3); }

@supports (background: color-mix(in srgb, red 50%, transparent)) {
  .chip--rating.is-rated-1.is-active { background: color-mix(in srgb, var(--rate-1) 16%, transparent); }
  .chip--rating.is-rated-2.is-active { background: color-mix(in srgb, var(--rate-2) 16%, transparent); }
  .chip--rating.is-rated-3.is-active { background: color-mix(in srgb, var(--rate-3) 16%, transparent); }
}

/* ── общая раскладка ────────────────────────────────────────────────────── */

.layout {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr var(--cards-w);
}

.sidebar {
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Колонка сетки по умолчанию не сжимается ниже min-content содержимого, и на
     узком экране вся раскладка становилась шире окна. */
  min-width: 0;
  background: var(--bg-panel);
  border-right: 1px solid var(--line);
}

.cards {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  background: var(--bg-panel);
  border-left: 1px solid var(--line);
}

.cards .bulk { margin: 10px 10px 0; }

.filters {
  padding: 14px;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.filters .field { margin-top: 0; }

.filters__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
}

/* Колонка карточек — рельс: карточки лежат на нём по абсолютным смещениям,
   и в дереве живут только те, что видны (см. renderList в ui.js). Отсюда и
   block вместо flex: зазор между карточками теперь считает рельс, а не gap. */
.list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 10px;
  display: block;
}

.list__rail { position: relative; }

.list__rail > .card {
  position: absolute;
  left: 0;
  right: 0;
}

/* Единственное, что осталось в обычном потоке, — попадания по координатам и
   строка «ничего не нашлось». */
.list > .empty { margin-top: 10px; }

/* ── карточка локации ───────────────────────────────────────────────────── */

.card {
  position: relative;
  padding: 11px 12px 11px 15px;
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}

.card::before {
  content: '';
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--planned);
}

/* Полоска карточки повторяет цвет метки на карте: список и карта должны
   говорить об одном и том же одним и тем же цветом. */
.card.is-rated-1::before { background: var(--rate-1); }
.card.is-rated-2::before { background: var(--rate-2); }
.card.is-rated-3::before { background: var(--rate-3); }
.card.is-gone::before { background: var(--idle); }

/* Значок вида: кружок — Location, ромб — Territory, как на карте.
   Размер и цвет выбраны так, чтобы форма читалась без наведения: на 9px
   бледной линией круг и ромб в общем списке сливались в одну точку. */
.card__kind {
  flex: 0 0 auto;
  width: 11px;
  height: 11px;
  border: 1.5px solid var(--text-dim);
  border-radius: 50%;
}

/* Ромб повёрнут внутри той же коробки 11px: масштаб гасит прирост диагонали,
   поэтому у обоих видов одинаковый след в потоке и названия стоят вровень. */
.card--territory .card__kind {
  border-radius: 2px;
  transform: rotate(45deg) scale(0.82);
}

.card__rating { margin-left: auto; color: var(--rate-2); font-size: 11px; letter-spacing: 1px; }
.card__rating-off { color: var(--line); }

.tag--list { color: var(--visited); background: rgba(91, 192, 190, 0.12); }
.card:hover { border-color: var(--line-strong); }
.card.is-selected {
  border-color: var(--visited);
  background: var(--bg-select);
}

.card__top {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.card__name {
  font-weight: 600;
  font-size: 14px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card__territory {
  font-size: 12px;
  color: var(--text-faint);
  white-space: nowrap;
}

.card__windows {
  margin-top: 5px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.season-tag {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 4px;
  border: 1px solid transparent;
  white-space: nowrap;
}

.season-tag.season-winter { color: var(--winter); border-color: rgba(106, 169, 233, 0.35); background: rgba(106, 169, 233, 0.1); }
.season-tag.season-spring { color: var(--spring); border-color: rgba(110, 201, 138, 0.35); background: rgba(110, 201, 138, 0.1); }
.season-tag.season-summer { color: var(--summer); border-color: rgba(232, 180, 74, 0.35); background: rgba(232, 180, 74, 0.1); }
.season-tag.season-autumn { color: var(--autumn); border-color: rgba(224, 122, 95, 0.35); background: rgba(224, 122, 95, 0.1); }

.card__meta {
  margin-top: 6px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-dim);
}

.card__next.is-now { color: var(--visited); font-weight: 600; }

/* Значок ссылки. Один и тот же в форме и на карточке: человек ставит адрес
   в строку с буквой G — и ровно эту букву потом видит в списке. */
.link-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--line-strong);
  color: var(--link-ink);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  /* Буква прописная, и её отпечаток занимает верх строки: под ним остаётся
     пустое место для выносных элементов, которых у G, Я, W и O нет. Поэтому
     геометрически отцентрованная строка выглядит поднятой.
     Отступ сверху опускает её на половину своей величины. Полпикселя хватало,
     чтобы отпечаток встал ровно по центру круга, но на глаз буква всё равно
     читалась высоко — круг тяжелее книзу, и оптический центр в нём ниже
     геометрического. Здесь сдвиг полтора пикселя: 7 сверху, 5 снизу. */
  padding-top: 3px;
  user-select: none;
}

.link-badge--g { background: var(--link-g); }
.link-badge--ya { background: var(--link-ya); }
.link-badge--w { background: var(--link-w); }
.link-badge--o { background: var(--link-o); }

.links-row {
  margin-top: 7px;
  display: flex;
  gap: 6px;
}

/* Цвет буквы повторён здесь не зря: в леафлетовском popup действует его
   собственное `.leaflet-container a`, и оно специфичнее одиночного класса —
   буквы становились синими. Два класса подряд перебивают. */
.link-badge.is-link {
  color: var(--link-ink);
  text-decoration: none;
  transition: transform 0.12s;
}

.link-badge.is-link:hover { transform: scale(1.12); }
.link-badge.is-link:focus-visible {
  outline: 2px solid var(--visited);
  outline-offset: 2px;
}

/* В форме значок только подписывает строку — ни наведения, ни курсора-руки. */
.links-edit { display: flex; flex-direction: column; gap: 8px; }

.link-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.link-row .input { flex: 1; min-width: 0; }

.card__priority {
  margin-left: auto;
  letter-spacing: 1px;
  color: var(--planned);
  font-size: 11px;
}

.card__tags {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.tag {
  font-size: 11px;
  color: var(--text-faint);
  background: var(--bg-input);
  border-radius: 4px;
  padding: 2px 6px;
}

.empty {
  padding: 30px 16px;
  text-align: center;
  color: var(--text-faint);
  font-size: 13px;
}

/* ── сцена: карта и календарь ───────────────────────────────────────────── */

.stage {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.stage__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-panel);
}

.stage__tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

.stage__panel {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

#map {
  flex: 1;
  min-height: 0;
  background: var(--map-ocean);
}

/* Сводка внизу слева — над строкой источников, а не поверх неё: этот угол
   карты уже занят подписью Leaflet. */
.map-status {
  position: absolute;
  left: 10px;
  bottom: 28px;
  z-index: 500;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  pointer-events: none;
  /* Предел ставится здесь: у самой плашки ширина по содержимому, и процент
     внутри неё считался бы от неё же. Здесь же это ширина карты. */
  max-width: calc(100% - 20px);
}

.map-status__row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 12px;
  box-shadow: 0 4px 14px var(--shadow-strong);
  /* Строка длинная, а карта на узком экране узкая: перенос лучше, чем плашка,
     уехавшая за край. Точка при этом не должна сжиматься — у неё flex: 0 0. */
  max-width: 100%;
}

/* Точка отвечает на сам вопрос — будут дуги или заливка. Цвет тот же, что у
   соответствующих состояний в остальном интерфейсе. */
.map-status__row::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--visited);
  flex: 0 0 auto;
}
.map-status__row.is-dense::before { background: var(--planning-ring); }
.map-status__row.is-empty::before { background: var(--idle); }

.map-status__row--picked {
  background: var(--planning-ring);
  border-color: var(--planning-ring);
  color: var(--on-planning);
  font-weight: 600;
}
.map-status__row--picked::before { background: var(--on-planning); }

.pick-hint {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 500;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--visited);
  color: var(--on-accent);
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 6px 20px var(--shadow-strong);
}

/* ── Leaflet ────────────────────────────────────────────────────────────── */

.leaflet-container {
  background: var(--map-ocean);
  font: inherit;
}

.leaflet-container.is-picking { cursor: crosshair; }

/* Метки лежат на холсте, а холст не должен перехватывать указатель: иначе
   карта перестала бы таскаться. Что под курсором, решает pins.js по своей
   сетке, и он же вешает сюда класс — строго после .is-picking, чтобы над
   меткой курсор был «палец», а не перекрестье, как было у настоящих меток. */
.pin-canvas { pointer-events: none; }
.leaflet-container.is-over-pin { cursor: pointer; }

.country {
  fill: var(--country-fill);
  stroke: var(--country-stroke);
}

/* Здесь описана метка: форма отличает Territory от Location, цвет — состояние.
   На карте метки рисует холст (pins.js), но цвета он берёт из этих же
   переменных, а размеры и толщины повторяет по числам отсюда — так палитра
   остаётся в одном месте и меняется вместе с темой сайта. Сами правила нужны
   образцам в легенде и метке, которую ставит поиск по координатам. */
.pin-wrap { background: none; border: 0; }

.pin {
  display: block;
  width: 100%;
  height: 100%;
  position: relative;
  border: 2px solid var(--marker-halo);
  background: var(--idle);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  transition: transform 0.12s, box-shadow 0.12s;
  cursor: pointer;
}

.pin--location { border-radius: 50%; }
.pin--territory { border-radius: 3px; transform: rotate(45deg); }

/* Метка найденной поиском точки. Строго после .pin: специфичность у них
   одинаковая, и правило выше проиграло бы — кружок оставался серым.
   Пунктир отличает её от настоящих меток: это ещё не место в наборе. */
.pin--probe {
  border-radius: 50%;
  border: 2px dashed var(--visited);
  background: var(--marker-halo);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--visited) 28%, transparent);
  cursor: default;
}

/* Цвет по оценке, одинаково у обеих фигур: шкала начинается с единицы,
   «больше не существует» перебивает оценку серым. */
.pin.is-rated-1 { background: var(--rate-1); }
.pin.is-rated-2 { background: var(--rate-2); }
.pin.is-rated-3 { background: var(--rate-3); }
.pin.is-gone { background: var(--idle); }

/* Нейтральная заливка — только для образцов формы в легенде. */
.pin.is-neutral { background: var(--text-faint); }

/* Планы локации — кайма поверх заливки-оценки. Сделана через outline, а не
   box-shadow: тень у метки уже занята полым видом «без оценки» и подсветкой
   выделения, и они бы затирали друг друга. */
/* «Был здесь» — точка в центре. Заливка занята оценкой, кайма планами,
   поэтому третьему признаку достаётся середина метки. */
.pin.is-been::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  /* Треть внутренней площади метки: крупнее читается как дырка, а не точка. */
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: var(--marker-halo);
}

/* Цвет точки по умолчанию — под фон, и на насыщенных заливках он читается.
   На бледной единице и на сером «больше не существует» такая точка почти
   исчезает, поэтому там берётся противоположный тон. --marker-halo и --text
   меняются местами вместе с темой, так что правило работает в обеих. */
.pin.is-rated-1.is-been::after,
.pin.is-gone.is-been::after { background: var(--text); }

.pin.is-planning {
  outline: 4px solid var(--planning-ring);
  outline-offset: 0;
}

.pin.is-hover { box-shadow: 0 0 0 3px var(--marker-outline); }
.pin.is-selected {
  box-shadow: 0 0 0 3px var(--marker-outline), 0 0 12px var(--visited);
  z-index: 500;
}
.pin--location.is-selected { transform: scale(1.35); }
.pin--territory.is-selected { transform: rotate(45deg) scale(1.3); }

.leaflet-popup-content-wrapper {
  background: var(--bg-raise);
  color: var(--text);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  box-shadow: 0 10px 30px var(--shadow-soft);
}

.leaflet-popup-tip { background: var(--bg-raise); border: 1px solid var(--line); }
.leaflet-popup-content { margin: 12px 14px; min-width: 180px; }
.leaflet-popup-close-button { color: var(--text-faint) !important; }

.popup__title { font-weight: 600; font-size: 14px; }
.popup__territory { color: var(--text-faint); font-size: 12px; margin-top: 1px; }
.popup__meta { margin-top: 7px; font-size: 12px; color: var(--text-dim); }
.popup__next { margin-top: 3px; font-size: 12px; color: var(--visited); }
.popup__rating { margin-top: 4px; color: var(--planned); }
.popup__notes { margin-top: 7px; font-size: 12px; color: var(--text-dim); }
.popup__link { display: inline-block; margin-top: 7px; color: var(--visited); font-size: 12px; }

/* Кнопка «Open in…» выглядит так же, но класс у неё свой: одинаковый класс
   на двух разных действиях — верный способ однажды нажать не то. */
.popup__edit, .popup__action {
  display: block;
  margin-top: 10px;
  width: 100%;
  appearance: none;
  border: 1px solid var(--line);
  background: var(--bg-input);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  padding: 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.popup__edit:hover, .popup__action:hover { background: var(--btn-hover-bg); }

.leaflet-control-attribution {
  background: var(--attrib-bg) !important;
  color: var(--text-faint) !important;
  font-size: 10px !important;
}

.leaflet-control-attribution a { color: var(--text-dim) !important; }

.leaflet-bar a {
  background: var(--bg-raise) !important;
  color: var(--text) !important;
  border-color: var(--line) !important;
}

.leaflet-bar a:hover { background: var(--btn-hover-bg) !important; }

/* ── круговой календарь ─────────────────────────────────────────────────── */

.wheel-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  font-size: 13px;
}

.wheel-bar__year { font-weight: 600; font-size: 15px; min-width: 48px; text-align: center; }

.wheel-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 14px;
}

.wheel {
  width: 100%;
  height: 100%;
  max-height: 100%;
  max-width: min(100%, 860px);
}

.wheel-legend {
  display: flex;
  justify-content: center;
  gap: 14px;
  padding: 8px 14px 14px;
  font-size: 12px;
}

.legend-item::before {
  content: '';
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: baseline;
  background: currentColor;
}

.legend-item.season-winter { color: var(--winter); }
.legend-item.season-spring { color: var(--spring); }
.legend-item.season-summer { color: var(--summer); }
.legend-item.season-autumn { color: var(--autumn); }

.wheel-month-sector { fill: var(--bg-raise); }
.wheel-month-sector.season-winter { fill: rgba(106, 169, 233, 0.16); }
.wheel-month-sector.season-spring { fill: rgba(110, 201, 138, 0.16); }
.wheel-month-sector.season-summer { fill: rgba(232, 180, 74, 0.16); }
.wheel-month-sector.season-autumn { fill: rgba(224, 122, 95, 0.16); }

.wheel-month-divider { stroke: var(--line-soft); stroke-width: 1; }

.wheel-month-label {
  fill: var(--text-dim);
  font-size: 19px;
  font-weight: 600;
  text-anchor: middle;
  dominant-baseline: central;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.wheel-day-tick { stroke: var(--tick); stroke-width: 1; }
.wheel-day-tick.is-decade { stroke: var(--tick-strong); }
.wheel-day-tick.is-month { stroke: var(--text-faint); stroke-width: 1.6; }

.wheel-lane-guide { fill: none; stroke: var(--lane-guide); }

.wheel-arc {
  fill: none;
  stroke-linecap: butt;
  cursor: pointer;
  transition: opacity 0.15s;
}

.wheel-arc.season-winter { stroke: var(--winter); }
.wheel-arc.season-spring { stroke: var(--spring); }
.wheel-arc.season-summer { stroke: var(--summer); }
.wheel-arc.season-autumn { stroke: var(--autumn); }
/* Подсветку ставит JS, а не :hover: указатель ловит прозрачная дуга поверх
   видимой, и на саму видимую :hover уже не приходит. */
.wheel-arc.is-hover { filter: brightness(1.25); }

/* Зона попадания: невидима, но ловит указатель. pointer-events: stroke указан
   явно — при прозрачной обводке правило по умолчанию считает элемент
   незакрашенным и события мимо неё проходят. */
.wheel-hit {
  fill: none;
  stroke: transparent;
  pointer-events: stroke;
  cursor: pointer;
}
.wheel-arc.is-dimmed { opacity: 0.28; }
.wheel-arc.is-selected { filter: drop-shadow(0 0 7px currentColor) brightness(1.15); }

.wheel-arc-guide { fill: none; stroke: none; pointer-events: none; }

.wheel-arc-label {
  fill: var(--arc-label);
  font-weight: 600;
  pointer-events: none;
  dominant-baseline: central;
}

.wheel-arc-label.is-dimmed { opacity: 0.35; }

.wheel-today-line { stroke: var(--marker-outline); stroke-width: 1.6; stroke-dasharray: 5 4; opacity: 0.72; }
.wheel-today-dot { fill: var(--marker-outline); }

.wheel-hub-disc { fill: var(--bg-panel); stroke: var(--line); stroke-width: 1; }
.wheel-hub-year { fill: var(--text); font-size: 44px; font-weight: 700; text-anchor: middle; }
.wheel-hub-count { fill: var(--text-dim); font-size: 17px; text-anchor: middle; }
.wheel-hub-hint { fill: var(--text-faint); font-size: 13px; text-anchor: middle; }

/* ── панель редактирования ──────────────────────────────────────────────── */

/* Ящик открывается не у самого края, а левее колонки карточек: иначе он
   накрывал бы ровно тот список, из которого место и выбрали, и перейти к
   следующей карточке можно было бы только закрыв ящик. Перекрывает карту —
   её не жалко, координаты в форме и так видны. */
.drawer {
  position: fixed;
  /* Не заданная высота шапки, а измеренная: шапка переносится на вторую строку
     уже с 900 px, и число расходилось с правдой на два с лишним десятка
     пикселей — панель уезжала под шапку. Измеряет watchTopbarHeight в app.js;
     пока скрипт не отработал, годится и заданная. */
  top: var(--topbar-real, var(--topbar-h));
  right: var(--cards-w);
  bottom: 0;
  width: 400px;
  max-width: 100vw;
  z-index: 900;
  background: var(--bg-panel);
  border-left: 1px solid var(--line);
  box-shadow: -14px 0 40px var(--shadow-strong);
  border-right: 1px solid var(--line);
  display: flex;
}

/* Свои контролы Leaflet рисует на z-index 1000 и без этого лезет поверх
   ящика: кнопки масштаба вылезали на кнопку Delete. Тосты остаются выше —
   им и положено быть поверх всего, включая экран входа (1250). */
.drawer { z-index: 1100; }

.drawer__form { display: flex; flex-direction: column; width: 100%; min-height: 0; }

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px;
  border-bottom: 1px solid var(--line);
}

.drawer__head h2 { font-size: 15px; }

.drawer__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.drawer__body .field + .field { margin-top: 0; }

.drawer__foot {
  display: flex;
  gap: 8px;
  padding: 14px;
  border-top: 1px solid var(--line);
}

.drawer__foot .btn--primary { flex: 1; }

.form-section { display: flex; flex-direction: column; gap: 12px; }

.windows { display: flex; flex-direction: column; gap: 8px; }

.window-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) 52px auto minmax(0, 1fr) 52px auto;
  gap: 5px;
  align-items: center;
}

.window-row__label { font-size: 12px; color: var(--text-faint); }
.window-row .input { padding: 6px 8px; font-size: 12px; }

.window-row__remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 4px;
}

.window-row__remove:hover { color: var(--danger); }

/* ── диалог данных ──────────────────────────────────────────────────────── */

.dialog {
  width: min(560px, 94vw);
  max-height: 88vh;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--bg-panel);
  color: var(--text);
  overflow: hidden;
}

.dialog::backdrop { background: rgba(5, 7, 11, 0.7); }

.dialog__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 15px 16px;
  border-bottom: 1px solid var(--line);
}

.dialog__head h2 { font-size: 15px; }

.dialog__body {
  padding: 16px;
  overflow-y: auto;
  max-height: calc(88vh - 56px);
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.panel h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.7px; color: var(--text-dim); }

.snapshots { display: flex; flex-direction: column; gap: 6px; max-height: 230px; overflow-y: auto; }

.snapshot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  font-size: 12px;
}

.snapshot__when { color: var(--text); white-space: nowrap; }
.snapshot__label { color: var(--text-faint); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.snapshot .btn { padding: 4px 9px; font-size: 12px; }

/* ── временная шкала ────────────────────────────────────────────────────── */

.timeline {
  flex: 0 0 auto;
  padding: 8px 12px 6px;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--line);
  user-select: none;
}

.timeline__track {
  position: relative;
  height: 42px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-raise);
  overflow: hidden;
  cursor: crosshair;
  touch-action: none;   /* иначе жест уедет в прокрутку страницы, а не в выделение */
}

/* Плотность — подложка под всем остальным: она отвечает на вопрос «где вообще
   что-то есть», а не участвует в выборе. */
.timeline__density {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.timeline__density path { fill: var(--rate-1); opacity: 0.55; }

.timeline__months {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.timeline__month {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 1px solid var(--line-soft);
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.timeline__month:first-child { border-left: 0; }

/* Месяцы подкрашены сезоном — та же четвёрка цветов, что в фильтре и в круге. */
.timeline__month.season-winter { color: var(--winter); }
.timeline__month.season-spring { color: var(--spring); }
.timeline__month.season-summer { color: var(--summer); }
.timeline__month.season-autumn { color: var(--autumn); }

.timeline__selection {
  position: absolute;
  top: 0;
  bottom: 0;
  background: color-mix(in srgb, var(--planning-ring) 20%, transparent);
  border-left: 2px solid var(--planning-ring);
  border-right: 2px solid var(--planning-ring);
  pointer-events: none;
}

/* Ручки перехватывают события, сама полоса выделения — нет: клик внутри неё
   должен начинать новый отрезок, а не сдвигать старый. */
.timeline__grip {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 11px;
  pointer-events: auto;
  cursor: ew-resize;
}
.timeline__grip[data-edge="from"] { left: -6px; }
.timeline__grip[data-edge="to"] { right: -6px; }

.timeline__today {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 1px dashed var(--visited);
  pointer-events: none;
}

.timeline__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 5px;
  font-size: 12px;
  color: var(--text-faint);
}
.timeline__label { color: var(--text); }
.timeline__peak { margin-left: auto; font-size: 11px; }
.timeline__foot .btn { padding: 3px 9px; font-size: 12px; }
.timeline__track.has-range { cursor: crosshair; }

@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .timeline__selection { background: rgba(226, 98, 15, 0.2); }
}

/* ── массовые действия ──────────────────────────────────────────────────── */

.bulk {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.bulk__count { font-size: 13px; font-weight: 600; color: var(--text); }
.bulk__actions { display: flex; flex-wrap: wrap; gap: 6px; }
.bulk__actions .btn { padding: 5px 10px; font-size: 12px; }
.bulk .hint { margin: 0; }

/* Галочка живёт слева и раздвигает карточку только в режиме выделения,
   чтобы обычный список не платил за неё отступом. */
.list.is-selecting .card { padding-left: 36px; }

.card__check {
  display: none;
  position: absolute;
  left: 13px;
  top: 13px;
  width: 15px;
  height: 15px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg);
}

.list.is-selecting .card__check { display: block; }

.card.is-picked .card__check {
  background: var(--planning-ring);
  border-color: var(--planning-ring);
}

.card.is-picked .card__check::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.card.is-picked { border-color: var(--planning-ring); }

/* В режиме выделения карточка не открывается, и курсор не должен обещать обратное. */
.list.is-selecting .card { user-select: none; }

/* ── потолки размера ────────────────────────────────────────────────────── */

.limits { display: flex; flex-direction: column; gap: 4px; }
.limits:empty { display: none; }

.limits__head {
  margin: 12px 0 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.limits__head:first-child { margin-top: 4px; }

.limits__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 4px 10px;
  padding: 6px 10px;
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  font-size: 12px;
}

/* Самый строгий потолок и есть ответ на вопрос — его видно без чтения строк. */
.limits__row.is-strict { border-color: var(--planning-ring); }

.limits__label { color: var(--text); }
.limits__value { color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.limits__note { grid-column: 1 / -1; color: var(--text-faint); font-size: 11px; }
.limits__row.is-strict .limits__value::after { content: ' · strictest'; color: var(--planning-ring); }

.limits__bar {
  height: 6px;
  margin-top: 8px;
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  overflow: hidden;
}
/* Минимальная ширина: заполнение в доли процента должно быть видно полоской,
   а не пустотой, неотличимой от сломанной вёрстки. */
.limits__bar > span { display: block; height: 100%; min-width: 3px; background: var(--planning-ring); }

/* ── кольцо плотности ───────────────────────────────────────────────────── */

.wheel-density-base { fill: none; stroke: var(--line-soft); }

.wheel-density-area { fill: var(--rate-2); fill-opacity: 0.5; stroke: none; }

.wheel-density-line {
  fill: none;
  stroke: var(--rate-3);
  stroke-width: 2.5;
  stroke-opacity: 0.95;
  stroke-linejoin: round;
}

/* Кольцо целиком ловит наведение: отдельных дуг тут нет, и читать надо день
   под курсором, а не объект. */
.wheel-density-hit { fill: transparent; cursor: crosshair; }

/* ── плавающие даты ─────────────────────────────────────────────────────── */

/* Кругу тут отведена доля высоты, а не вся: под ним живёт форма, и панель
   прокручивается целиком. */
.wheel-wrap--floating { flex: 0 0 auto; height: min(52vh, 520px); }

.floating {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 14px 18px;
}

.floating__form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.floating__wide { flex: 2 1 220px; }
.floating__form .row > .field { flex: 1 1 140px; }
.floating__form .input--day { width: 74px; flex: 0 0 auto; }
.floating__form .hint { margin: 0; }

.floating__list { display: flex; flex-direction: column; gap: 6px; }

.floating__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  font-size: 13px;
}

/* Правимая запись подсвечена так же, как выделенное на карте: одна и та же
   мысль «вот это сейчас в работе». */
.floating__row.is-editing { border-color: var(--planning-ring); }

.floating__dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--text-faint);
}
.floating__dot.season-winter { background: var(--winter); }
.floating__dot.season-spring { background: var(--spring); }
.floating__dot.season-summer { background: var(--summer); }
.floating__dot.season-autumn { background: var(--autumn); }

.floating__name { flex: 1 1 auto; min-width: 0; color: var(--text); font-weight: 600; }
.floating__territory { margin-left: 8px; color: var(--text-faint); font-weight: 400; }
.floating__when { color: var(--text-dim); white-space: nowrap; }
.floating__row .btn { padding: 3px 9px; font-size: 12px; }

@media (max-width: 700px) {
  .floating__row { flex-wrap: wrap; }
  .floating__when { width: 100%; }
}

/* ── подсказка круга ────────────────────────────────────────────────────── */

.wheel-tip {
  position: fixed;
  z-index: 1150;
  max-width: 260px;
  padding: 8px 11px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 6px 20px var(--shadow-strong);
  font-size: 12px;
  /* Подсказка следует за указателем и не должна сама его перехватывать. */
  pointer-events: none;
}

.wheel-tip__name { font-weight: 600; font-size: 13px; color: var(--text); }
.wheel-tip__territory { color: var(--text-faint); }
.wheel-tip__window { color: var(--text-dim); }
.wheel-tip__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 3px;
  color: var(--text-faint);
}
/* Те же цвета, что у звёзд на карточке: рейтинг в подсказке и в списке должен
   выглядеть одинаково, иначе их приходится сверять глазами. */
.wheel-tip__stars { margin-left: auto; color: var(--rate-2); letter-spacing: 1px; }
.wheel-tip__off { color: var(--line); }

/* ── уведомления ────────────────────────────────────────────────────────── */

.toasts {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  /* Выше экрана входа (1250): сообщение об отказе должно быть видно и на нём. */
  z-index: 1300;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;
}

.toast {
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 13px;
  box-shadow: 0 8px 26px var(--shadow-soft);
  animation: toast-in 0.18s ease-out;
}

.toast--error { border-color: var(--danger); color: var(--danger); }
.toast--ok { border-color: var(--visited); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* ── звёзды, чипы связей, списки, выбор ─────────────────────────────────── */

.stars { display: flex; align-items: center; gap: 4px; }

.stars button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--line-strong);
  font-size: 20px;
  line-height: 1;
  padding: 2px;
  cursor: pointer;
  transition: color 0.12s;
}

.stars button.is-on { color: var(--planned); }
.stars button:hover { color: var(--planned); }

.chips--editable { align-items: center; }

.chip--filled {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 6px 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg-input);
  font-size: 12px;
  color: var(--text);
}

.chip__remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  font-size: 11px;
  line-height: 1;
  padding: 2px;
  cursor: pointer;
}

.chip__remove:hover { color: var(--danger); }

.chip--add {
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 16px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-style: dashed;
}

.stage__panel--scroll { overflow-y: auto; }

.lists-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px 4px;
}

.lists {
  padding: 10px 16px 20px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px;
  align-content: start;
}

.list-card {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
}

.list-card__head { display: flex; align-items: baseline; gap: 10px; }
.list-card__head h3 { font-size: 15px; flex: 1; min-width: 0; }
.list-card__head .btn { padding: 4px 9px; font-size: 12px; }
.list-card__head .muted { font-size: 12px; white-space: nowrap; }

.list-card__notes {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--text-dim);
  white-space: pre-wrap;
  word-break: break-word;
}

.list-card__notes a, .popup__notes a { color: var(--visited); }

.list-card__members { margin-top: 10px; display: flex; flex-direction: column; gap: 5px; }

.member {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 6px 9px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-raise);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.member:hover { border-color: var(--line-strong); }
.member__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member__territory { color: var(--text-faint); font-size: 12px; }

.member__kind {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
}

.member__kind--territory { border-radius: 2px; transform: rotate(45deg); }

.dialog--narrow { width: min(420px, 94vw); }

.picker {
  margin-top: 10px;
  max-height: 300px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.picker__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
}

.picker__row:hover { background: var(--bg-raise); }
.picker__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker__sub { color: var(--text-faint); font-size: 12px; white-space: nowrap; }

.segmented--wrap { flex-wrap: wrap; }

.popup__kind {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--text-faint);
  margin-bottom: 2px;
}

.popup__rating-off { color: var(--line); }

/* Окно перехода по координатам. Лежит в левом верхнем углу карты, над
   легендой: это поле ввода, и оно должно попадаться на глаза, а легенда —
   справка, к которой обращаются по надобности. */
.jumper {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 14px var(--shadow-soft);
  color: var(--text);
  max-width: 250px;
  overflow: hidden;
}

.jumper__row {
  display: flex;
  align-items: stretch;
}

.jumper__field {
  width: 168px;
  min-width: 0;
  padding: 6px 8px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.jumper__field:focus { outline: none; }
.jumper__field::placeholder { color: var(--text-faint); }

.jumper__go {
  flex: 0 0 auto;
  width: 30px;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--line-soft);
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.jumper__go:hover { background: var(--bg-raise); color: var(--text); }

.jumper__note {
  padding: 5px 8px 6px;
  border-top: 1px solid var(--line-soft);
  font-size: 11px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.jumper__note.is-bad { color: var(--danger); }

.jumper__ask {
  display: block;
  margin-bottom: 3px;
  color: var(--text-faint);
}

/* Два прочтения одной записи. Переход уже сделан к общепринятому, и оно
   помечено; вторая строка — кнопка, до которой один щелчок. Обе на виду:
   угаданного молча ответа тут быть не должно. */
.jumper__pick {
  display: block;
  width: 100%;
  padding: 3px 4px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  text-align: left;
  cursor: pointer;
}

.jumper__pick:hover { background: var(--bg-raise); }

.jumper__pick.is-on {
  background: var(--bg-select);
  font-weight: 600;
}

.jumper__pick.is-on .jumper__dms { font-weight: 400; }

.jumper__dms {
  display: block;
  color: var(--text-faint);
}

/* На узком экране поле ужимается: над ним ещё кнопки карты, а под ним
   легенда, и занимать половину ширины ради ввода координат ни к чему. */
@media (max-width: 560px) {
  .jumper { max-width: 190px; }
  .jumper__field { width: 128px; }
}

/* Легенда карты. Образцы — настоящие .pin, поэтому здесь только их размер. */
.legend {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 14px var(--shadow-soft);
  color: var(--text);
  font-size: 11px;
  max-width: 260px;
}

.legend summary {
  padding: 6px 10px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.legend summary::-webkit-details-marker { display: none; }

.legend summary::after {
  content: '▾';
  float: right;
  margin-left: 10px;
  color: var(--text-faint);
}

.legend[open] summary::after { content: '▴'; }

.legend__body {
  padding: 0 10px 9px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.legend__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 9px;
}

.legend__title {
  width: 100%;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-faint);
}

.legend__item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-dim);
  white-space: nowrap;
}

.legend .pin {
  width: 11px;
  height: 11px;
  flex: 0 0 auto;
  border-width: 1px;
  box-shadow: none;
  cursor: default;
}

.legend .pin.is-planning { outline-width: 2.5px; margin: 0 2px; }
.legend .pin.is-been::after { width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px; }
.legend .pin--territory { margin: 0 2px; }

/* Штатный переключатель слоёв Leaflet под тему сайта. */
.leaflet-control-layers {
  background: var(--bg-panel) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius-sm) !important;
  color: var(--text);
  box-shadow: 0 6px 20px var(--shadow-soft) !important;
}

.leaflet-control-layers-toggle {
  background-color: var(--bg-panel) !important;
  border-radius: var(--radius-sm) !important;
}

.leaflet-control-layers-expanded { padding: 10px 12px !important; font-size: 13px; }
.leaflet-control-layers-separator { border-top-color: var(--line) !important; }
.leaflet-control-layers label { margin-bottom: 3px; cursor: pointer; }

/* ── адаптив ────────────────────────────────────────────────────────────── */

/* Три колонки фиксированной ширины на ноутбучном экране оставляли карте
   меньше четырёхсот пикселей. Боковые ужимаются первыми — карта тут главная. */
@media (max-width: 1400px) {
  :root { --sidebar-w: 320px; --cards-w: 290px; }
}

@media (max-width: 1000px) {
  body { overflow-y: auto; }

  .layout {
    grid-template-columns: 1fr;
  }

  .sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    order: 2;
  }

  .list { max-height: none; overflow: visible; }

  .stage {
    order: 1;
    height: 70vh;
  }

  .cards {
    border-left: 0;
    border-top: 1px solid var(--line);
    order: 3;
  }

  .drawer { top: 0; right: 0; width: 100%; border-right: 0; }
  .topbar { flex-wrap: wrap; height: auto; padding: 10px 12px; gap: 10px; }
}

@media (max-width: 560px) {
  .stage__bar { flex-wrap: wrap; }
  .stage__tools { margin-left: 0; width: 100%; }
  .wheel-legend { flex-wrap: wrap; gap: 10px; }
}

/* ── Маршруты ──────────────────────────────────────────────────────────── */

.routes {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.route-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-raise);
}

/* Крапинка слева — тот же цвет, которым этот маршрут нарисован на карте,
   то есть состояние места (см. --route-* и toneOf в map.js). */
.route-row__swatch {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--route-other);
}
.route-row__swatch.is-planned { background: var(--route-planned); }
.route-row__swatch.is-visited { background: var(--route-visited); }
.route-row__swatch.is-other { background: var(--route-other); }

.route-row__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.route-row__meta {
  flex: 0 0 auto;
  color: var(--text-faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* На узком экране подпись уходит под название, а кнопки остаются в строке. */
@media (max-width: 560px) {
  .route-row { flex-wrap: wrap; }
  .route-row__name { flex: 1 1 100%; }
  .route-row__meta { flex: 1 1 auto; }
}

.card__routes {
  color: var(--route-other);
  font-variant-numeric: tabular-nums;
}
.card__routes.is-planned { color: var(--route-planned); }
.card__routes.is-visited { color: var(--route-visited); }
.card__routes.is-other { color: var(--route-other); }

/* Правила для самой линии маршрута здесь нет намеренно: линии рисуются на
   холсте, а не элементами SVG, и CSS до них не достаёт. Скругления на стыках
   задаёт Leaflet — lineCap и lineJoin у него по умолчанию round, что нам и
   нужно: длинный трек из прямых отрезков иначе топорщится углами на каждом
   повороте. Цвет и толщина задаются в map.js, при создании линии. */
