/* Ping · оформление по макету Claude Design.
 *
 * Тема ТОЛЬКО тёмная и это осознанно: обе страницы — карта, а светлая карта
 * ночью бьёт по глазам ровно в тот момент, когда человек чаще всего смотрит
 * «где он сейчас». Светлой темы в макете нет.
 *
 * 🔴 Шрифты свои, а не с fonts.googleapis.com: страницу по ссылке открывает
 *    чужой человек из мессенджера, и лишний DNS+TLS к чужому домену стоит
 *    дороже, чем 30 КБ со своего.
 * 🔴 У Instrument Sans (шрифт макета) НЕТ кириллицы — только latin/latin-ext.
 *    Русский текст уехал бы в системный шрифт и сломал вид. Поэтому кириллицу
 *    отдаёт Golos Text через unicode-range: англичанин видит ровно макет,
 *    русский — близкий по пропорциям гротеск, и оба под одним font-family.
 */

/* ── шрифты ───────────────────────────────────────────────────────────── */
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url('fonts/instrument-sans-400-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;
}
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url('fonts/instrument-sans-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
                 U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/golos-text-400-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/golos-text-500-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 600 700; font-display: swap;
  src: url('fonts/golos-text-600-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Ping Sans'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url('fonts/golos-text-400-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Ping Mono'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/ibm-plex-mono-400-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;
}
@font-face {
  font-family: 'Ping Mono'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('fonts/ibm-plex-mono-400-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Ping Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/ibm-plex-mono-500-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;
}
@font-face {
  font-family: 'Ping Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('fonts/ibm-plex-mono-500-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* ── палитра макета ───────────────────────────────────────────────────── */
:root {
  --bg:        #0b0c0e;   /* корпус приложения */
  --bg-map:    #0f1114;   /* полотно карты */
  --card:      #131519;
  --card-dim:  #101114;   /* карточка неживой ссылки */
  --line:      #23262b;
  --line-dim:  #1c1f23;
  --line-soft: #2a2e35;
  --rail:      #1d2126;

  --fg:        #e8eaed;
  --fg-2:      #c8ced5;
  --fg-3:      #8b9199;
  --fg-4:      #6d747d;
  --fg-5:      #565c64;

  --on:        #46e0a0;   /* акцент: запись идёт, ссылка жива, «рядом» */
  --on-ink:    #05130d;   /* текст на акценте */
  --on-hi:     #6ff0bb;
  --on-bg:     #0f1a15;
  --on-line:   #1f5a42;
  --on-card:   #0e1613;
  --on-chip:   #0f2a20;

  --bad:       #ff8f8f;
  --bad-hard:  #ff6b6b;
  --bad-bg:    #1d1214;
  --bad-card:  #141012;
  --bad-line:  #3a2328;
  --bad-line2: #4a2328;

  --warn:      #f0b45a;
  --warn-bg:   #191512;
  --warn-line: #3d3021;

  --info:      #7fb4ff;
  --info-bg:   #101418;
  --info-line: #243240;

  --surface:   #1a1d22;
  --surface-2: #0f1114;
  --sheet-veil: rgba(0, 0, 0, .55);

  --r-lg: 20px; --r-md: 16px; --r-sm: 13px; --r-xs: 10px;
  /* Нижняя граница экрана телефона: без этого панель вкладок уезжает под
     системную полосу жестов на iPhone. */
  /* 🔴 Имя свойства целиком: `safe-area-inset-b` браузеру неизвестно, и значение
     МОЛЧА падало в запасной 0 — нижняя панель ложилась прямо под полосу жестов. */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  height: 100%;
  background: var(--bg);
  color: var(--fg);
  font-family: 'Ping Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
}

body { font-size: 15px; line-height: 1.45; }

/* 🔴 Атрибут hidden ОБЯЗАН скрывать. Правило браузера [hidden]{display:none}
   слабее любого класса, а .btn, .seg и прочие задают display: flex — узел с
   hidden в разметке остаётся на экране, и JS, который им управляет, работает
   вхолостую: запасная кнопка «завести без отпечатка» висела у всех, хотя по
   коду показывалась только при отказе. */
[hidden] { display: none !important; }
.mono { font-family: 'Ping Mono', ui-monospace, 'SF Mono', Menlo, monospace; }

a { color: var(--on); text-decoration: none; }
a:hover { color: var(--on-hi); }

h1 { font-size: 26px; font-weight: 600; letter-spacing: -.4px; line-height: 1.15; }
h2 { font-size: 21px; font-weight: 600; }
p  { text-wrap: pretty; }

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: transparent; }
button:disabled { cursor: default; opacity: .55; }

/* ── кнопки ───────────────────────────────────────────────────────────── */
.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; height: 54px; border-radius: 15px;
  background: var(--on); color: var(--on-ink);
  font-size: 16px; font-weight: 600;
  transition: filter .15s, background .15s;
}
.btn:active { filter: brightness(.92); }
/* 🔴 Недоступная кнопка гасится ЦВЕТОМ, а не одной прозрачностью: залитая
   зелёным «Добавить» при 55% всё равно читалась как рабочая, человек жал её
   и решал, что сервис сломан. */
.btn:disabled { background: var(--surface); color: var(--fg-4); opacity: 1; }
.btn--quiet { background: var(--surface); color: var(--fg-2); }
.btn--ghost { background: transparent; color: var(--fg-3); height: 46px; font-weight: 500; }
.btn--line  { background: transparent; border: 1px solid var(--line-soft); color: var(--fg-2); }
.btn--bad   { background: var(--bad-hard); color: #1a0708; }
.btn--sm    { height: 44px; font-size: 14px; border-radius: 12px; }

/* Мелкое действие в карточке ссылки: «скопировать», «поделиться», «отозвать». */
.chip-btn {
  border: 1px solid var(--line-soft); border-radius: var(--r-xs);
  background: transparent; color: var(--fg-2);
  font-size: 13px; font-weight: 500; padding: 8px 12px;
}
.chip-btn--bad { border-color: var(--bad-line); color: var(--bad); }

/* ── карточки ─────────────────────────────────────────────────────────── */
.card {
  border-radius: var(--r-lg); background: var(--card);
  border: 1px solid var(--line); padding: 18px 20px;
}
.card--on   { background: var(--on-card); border-color: var(--on-line); }
.card--bad  { background: var(--bad-card); border-color: var(--bad-line); }
.card--warn { background: var(--warn-bg);  border-color: var(--warn-line); }
.card--info { background: var(--info-bg);  border-color: var(--info-line); }

.label { font-size: 13px; color: var(--fg-3); }
.muted { color: var(--fg-3); }
.dim   { color: var(--fg-4); }

/* ── переключатель ────────────────────────────────────────────────────── */
.sw {
  flex: none; display: flex; align-items: center; padding: 4px;
  width: 86px; height: 50px; border-radius: 25px; background: var(--line-soft);
  transition: background .2s;
}
.sw[aria-checked="true"] { background: var(--on); }
.sw i {
  width: 42px; height: 42px; border-radius: 50%; background: var(--fg-3);
  transition: transform .25s cubic-bezier(.3, 1.3, .5, 1), background .2s;
}
.sw[aria-checked="true"] i { background: var(--on-ink); transform: translateX(36px); }
.sw--sm { width: 52px; height: 30px; padding: 3px; }
.sw--sm i { width: 24px; height: 24px; }
.sw--sm[aria-checked="true"] i { transform: translateX(22px); }

/* ── сегменты (интервал 15/30/60, срок ссылки) ────────────────────────── */
.seg { display: flex; gap: 8px; }
.seg button {
  flex: 1; height: 46px; border-radius: var(--r-sm);
  border: 1px solid var(--line-soft); background: var(--surface-2);
  color: var(--fg-3); font-size: 15px; font-weight: 500;
  transition: border-color .15s, color .15s, background .15s;
}
.seg button[aria-pressed="true"] {
  border-color: var(--on); background: var(--on-bg); color: var(--on);
}
/* Пять радиусов в один ряд на 390 px не влезают читаемо — вторая строка вместо
   мелкого шрифта: «20 км» должно оставаться «20 км», а не «20 к…». */
.seg--wrap { flex-wrap: wrap; margin-top: 8px; }
.seg--wrap button { flex: 1 0 calc(33.333% - 6px); height: 40px; font-size: 13.5px; }

/* ── поля ─────────────────────────────────────────────────────────────── */
.field {
  width: 100%; height: 48px; border-radius: var(--r-sm);
  border: 1px solid var(--line-soft); background: var(--surface-2);
  color: var(--fg); padding: 0 14px; font-size: 15px;
}
.field::placeholder { color: var(--fg-4); }
.field:focus { outline: none; border-color: var(--on); }

/* ── всплывающая подсказка ────────────────────────────────────────────── */
.toast {
  /* Подсказка стоит НАД листами: «скопировано» и «спрашивают, где вы» приходят
     как раз тогда, когда лист открыт, и спрятать их за ним нельзя. */
  position: fixed; left: 20px; right: 20px; z-index: 1100;
  bottom: calc(96px + var(--safe-b));
  border-radius: 14px; background: var(--surface); border: 1px solid var(--line-soft);
  padding: 13px 16px; font-size: 14px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
  animation: ping-rise .2s ease-out;
}
.toast[hidden] { display: none; }

@keyframes ping-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes ping-pulse {
  0%   { transform: scale(1);   opacity: .55; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* Пульс вокруг последней позиции: он и отличает «здесь сейчас» от прошлых
   отметок. Человеку, который просил «не мигать», система это и выключит. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ── состояние-заглушка (пусто, ошибка, 410) ──────────────────────────── */
.blank {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 34px; gap: 8px; flex: 1;
}
.blank__mark { width: 48px; height: 48px; border-radius: 50%; border: 1px solid var(--line-soft); margin-bottom: 8px; }
.blank__mark--bad { border-color: var(--bad-line2); }
.blank h2 { font-size: 21px; }
.blank p { font-size: 14.5px; color: var(--fg-3); max-width: 280px; }
.blank code { font-family: 'Ping Mono', monospace; font-size: 11.5px; color: var(--fg-5); }

/* ── карта ────────────────────────────────────────────────────────────── */
.map { position: absolute; inset: 0; background: var(--bg-map); }

/* Leaflet поверх тёмного полотна: светлые умолчания библиотеки выбиваются. */
.leaflet-container { background: var(--bg-map); font: inherit; outline: none; }

/* 🔴 Тёмная карта делается ЗДЕСЬ, из обычных светлых тайлов OpenStreetMap.
 * Готовые тёмные стили (CARTO dark_all, Stadia alidade_smooth_dark) рисуют по
 * тем же данным OSM, но требуют ключ: CARTO печатает поверх картинки
 * «API KEY REQUIRED», Stadia отвечает 401. Инверсия с поворотом тона на 180°
 * возвращает воде синий, а зелени зелёный — иначе река стала бы оранжевой.
 * Фильтр висит только на слое тайлов: маршрут, отметки и подписи в других
 * панелях Leaflet и остаются в цветах макета. */
.leaflet-tile-pane {
  filter: invert(1) hue-rotate(180deg) brightness(.62) contrast(1.06) saturate(.38);
}
.leaflet-control-attribution {
  background: rgba(11, 12, 14, .74) !important;
  color: var(--fg-5) !important;
  font-family: 'Ping Mono', monospace; font-size: 10px;
  padding: 2px 6px;
}
.leaflet-control-attribution a { color: var(--fg-4) !important; }
.leaflet-control-zoom { display: none; }
/* Кнопки масштаба (видны только на большом экране) — в цветах макета, а не
   белыми квадратами библиотеки поверх тёмной карты. */
.leaflet-bar a, .leaflet-bar a:hover {
  background: var(--card); color: var(--fg-2); border-bottom-color: var(--line);
}
.leaflet-bar a:hover { color: var(--on); }
.leaflet-bar, .leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--card); color: var(--fg); border: 1px solid var(--line);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

/* Отметка остановки: кружок с числом и подпись со временем. */
.stop { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.stop__dot {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--on); background: var(--bg-map);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Ping Mono', monospace; font-size: 11px; color: var(--on);
}
.stop__time {
  font-family: 'Ping Mono', monospace; font-size: 10.5px; color: var(--fg-2);
  background: rgba(15, 17, 20, .92); padding: 3px 6px; border-radius: 6px; white-space: nowrap;
}
/* Подпись устройства у его точки: у человека их несколько, и без имени гость
   видит просто несколько кружков и не понимает, какой из них что. */
.devtag {
  display: flex; align-items: center; gap: 6px; white-space: nowrap;
  transform: translate(-50%, -26px);
  background: rgba(15, 17, 20, .92); border: 1px solid var(--line-soft);
  border-radius: 8px; padding: 3px 8px;
}
.devtag i { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.devtag b { font-size: 11.5px; font-weight: 600; color: var(--fg-2); }

.here { width: 14px; height: 14px; border-radius: 50%; background: var(--on); }
.here__ring {
  position: absolute; inset: 0; border-radius: 50%; background: var(--on);
  animation: ping-pulse 2.4s ease-out infinite;
}
.scrubber-dot {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--fg); border: 3px solid var(--bg-map);
}
