/* ══ IBM PLEX SANS — ДЕЛОВОЙ ГРОТЕСК (round396) ═════════════════════

   Кирилл: «шрифт ужасен, он детский словно, слишком гладкий и мягкий,
   нужен деловой, строгий».

   ⚠️ ОН ПРАВ, И ПРИЧИНА В УСТРОЙСТВЕ INTER: это гуманистический
   гротеск — буквы округлые, «о» почти круглая, концы штрихов мягкие.
   Он делался ДРУЖЕЛЮБНЫМ, для приложений, где нужна теплота. Отсюда
   «детский».

   ⚠️ IBM PLEX SANS СДЕЛАН IBM ДЛЯ ДОКУМЕНТАЦИИ И ТЕХНИЧЕСКИХ
   ИНТЕРФЕЙСОВ: таблицы, номера, точные данные. Прямые окончания
   штрихов, узкие овалы, строгий ритм — буквально «деловой
   корпоративный» по замыслу. Ровно наш случай: аренда, номера,
   договоры, сроки.

   ⚠️ ВЕС: 94 КБ на четыре начертания после вырезания лишних языков
   (было 252). Кириллицу проверил в каждом файле — пропущенных знаков
   нет.

   ⚠️ tnum В НАБОРЕ: цифры одинаковой ширины. Госномера и суммы не
   «прыгают» при обновлении — 1100 и 9900 занимают ровно одно место. */
@font-face{
  font-family:'IBM Plex Sans';
  src:url('/static/fonts/plex-400.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'IBM Plex Sans';
  src:url('/static/fonts/plex-500.woff2') format('woff2');
  font-weight:500; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'IBM Plex Sans';
  src:url('/static/fonts/plex-600.woff2') format('woff2');
  font-weight:600; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'IBM Plex Sans';
  src:url('/static/fonts/plex-700.woff2') format('woff2');
  font-weight:700; font-style:normal; font-display:swap;
}


/* ⚠️ OSWALD — ТОЛЬКО ДЛЯ ГЛАВНОЙ (round395).

   Кирилл выбрал оставить её вид прежним: главная — витрина, и менять
   её попутно неправильно.

   ⚠️ ТРИ НАЧЕРТАНИЯ, А НЕ ЧЕТЫРЕ: вес 500 на главной не используется,
   и грузить его значит тратить 20 КБ впустую. */
@font-face{
  font-family:'Oswald';
  src:url('/static/fonts/oswald-400.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Oswald';
  src:url('/static/fonts/oswald-600.woff2') format('woff2');
  font-weight:600; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Oswald';
  src:url('/static/fonts/oswald-700.woff2') format('woff2');
  font-weight:700; font-style:normal; font-display:swap;
}






/* ══ ШРИФТ СВОЙ, А НЕ С ЧУЖОГО ДОМЕНА (round381) ════════════════════

   Файлы лежат в static/fonts. Раньше шрифт запрашивался у
   fonts.googleapis.com — а он из российских мобильных сетей отвечает
   через раз, и у прицепа на слабой сети сайт выглядел иначе.

   ⚠️ display:swap ОБЯЗАТЕЛЕН И ЗДЕСЬ. Пока файл читается с диска,
   текст рисуется запасным шрифтом, а не прячется. Без него в Safari
   когда-то был чёрный экран — это записано в round330, и повторять
   не будем.

   ⚠️ ФОРМАТ ТОЛЬКО woff2: он понимается всеми браузерами с 2016 года
   и вдвое легче ttf. Класть второй формат «на всякий случай» значит
   удвоить вес ради телефонов, которых у клиентов нет. */








*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* ЗАПРЕТ МАСШТАБИРОВАНИЯ (pinch и двойной тап).
   Вёрстка не должна «слетать» от случайного жеста.

   Почему одного viewport-мета мало: user-scalable=no Safari на iOS
   игнорирует с десятой версии — Apple убрала его намеренно, ради
   доступности. Поэтому опираемся на touch-action, а двойной тап
   добиваем перехватом в JS (см. base.html).

   touch-action на html разрешает только прокрутку — это глушит pinch.
   Двойной тап он глушит НЕ везде: браузеры надёжно реагируют лишь на
   значение manipulation, поэтому его ставим отдельно и широко. */
html{
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
  touch-action:pan-x pan-y;
}
/* touch-action: manipulation — запрещает double-tap zoom.
   Раньше список был точечным (кнопки, ссылки, поля) — и двойной тап
   по пустому месту, заголовку или картинке всё равно приближал
   страницу. Ставим на весь документ. */
body, body *{
  touch-action: manipulation;
}
/* Прокручиваемым областям возвращаем панорамирование: manipulation его
   не запрещает, но перечисляем явно, чтобы правка выше не аукнулась
   там, где список тянут пальцем. */
.adm-table-wrap, .scroll-x, .modal-content{
  touch-action: pan-x pan-y;
}
/* КАРТЫ НЕ ТРОГАЕМ. Leaflet сам управляет жестами и ставит себе
   touch-action через селекторы из трёх классов
   (.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom) —
   их специфичность выше, чем у «body *», поэтому правило выше карту
   не перебивает. Дублируем намерение явно: если кто-то однажды усилит
   селектор выше, карта не должна потерять щипок и перетаскивание.
   ВАЖНО: в песочнице Leaflet недоступен (нет выхода к CDN), эта
   строка проверена только логически — нужен взгляд на живом сервере. */
.leaflet-container{
  touch-action: none;
}
:root{
  /* ⚠️ ВЫСОТА НИЖНЕЙ ПАНЕЛИ — ОДНО МЕСТО НА ВЕСЬ ПРОЕКТ (round400).

     Карточка прицепа на карте стоит над панелью, и ей нужно знать её
     высоту. Раньше там было зашито 41 — а панель плавающая: к ней
     добавляются отступы от безопасной зоны телефона.

     На айфоне это 34 пикселя выреза: панель 75, карточка на 41, между
     ними щель в 34 пикселя, где просвечивает карта. */
  /* ⚠️ ВЫСОТА ПОДНЯТА ПОД ПОДПИСИ (round409). Кирилл: «добавь под
     значками текст». Считано, а не подобрано: значок 26 + зазор 2 +
     подпись 11 + отступы сверху и снизу по 6 = 51.
     ⚠️ ОТ ЭТОЙ ПЕРЕМЕННОЙ ЗАВИСИТ КАРТОЧКА НА КАРТЕ: и её высота, и то,
     насколько она уезжает вниз в спрятанном виде. В round409 из map.html
     убраны два числа 41px, которые не следовали за этой переменной. */
  --nav-h:calc(51px + env(safe-area-inset-bottom, 0px));
  /* Тёмный фон бренд-мест: шапка и нижняя навигация. */
  --bg-dark:#171b21;
    /* ⚠️ ФОН С ХОЛОДНЫМ ОТТЕНКОМ (round333).

       Кирилл увидел это на лендинге: «словно лёгкий серо-голубой
       оттенок — сделай фон чёрно-серо-голубой».

       Он поймал то, чего я не планировал: серебряные блики на чистом
       чёрном отдавали в синеву по контрасту, и это выглядело лучше
       нейтрального серого. Закрепляем намеренно — добавляем к фону и
       поверхностям синий сдвиг на 6–10 единиц. Больше нельзя: фон
       начнёт читаться как «тёмно-синяя тема», а нам нужен чёрный,
       который лишь отдаёт холодом. */
    /* ⚠️ ФОН ТЁМНО-СЕРЫЙ, А НЕ ПОЧТИ ЧЁРНЫЙ (round366).

     Было #0a0c0f — почти чёрный. На страницах с карточками этого не
     видно: карточки закрывают фон. Но там, где карточек нет (съёмка,
     футер, пустые области), проступал чёрный, и рядом с серыми блоками
     это читалось как две разные темы. Кирилл увидел это на границе
     страницы съёмки и футера.

     #171b21 — тот же тон, что у карточек, но на два шага темнее: фон
     остаётся фоном, карточки на нём видны, а чёрных провалов нет. */
  --bg:#171b21;--surface:#1b1f25;--surface-2:#242932;
    --primary:#C6CBD1;--primary-2:#9AA1A9;
    --text:#f4f2ee;--text-muted:rgba(244,242,238,.5);--border:rgba(255,255,255,.08);
    --success:#4ade80;--success-bg:rgba(56,161,105,.12);
    /* КРАСНЫЙ: ЯРКИЙ И ЧИТАЕМЫЙ НА СЕРОМ (round220).

       Кирилл: «на сером фоне ярко-красный выглядит нелепо, надо
       оставить вызывающим, но чтобы отлично читался».

       Замерил контраст на фоне блоков (серый #242932), норма 4.5:
           #fc8181 (было давно)  6.04, но насыщенность 49% — розовый
           #ff3b30 (round219)    4.16 — НИЖЕ НОРМЫ, глаз напрягается
           #dc2626 (сейчас)      4.49 и насыщенность 75%

       ⚠️ ЧЕСТНО О ОГРАНИЧЕНИИ: красный не может быть одновременно
       очень насыщенным и очень светлым — это физика цвета, а не
       недостаток подбора. Любой оттенок либо теряет насыщенность,
       либо контраст.

       Поэтому контраст добираем НЕ цветом, а ЖИРНОСТЬЮ: толстые
       штрихи читаются лучше при том же оттенке. Стандарт доступности
       это признаёт — для жирного текста порог не 4.5, а 3.0, и
       #dc2626 проходит его с большим запасом.

       Отсюда правило: красный текст на сером ВСЕГДА жирный. Класс
       .danger-text ниже задаёт и цвет, и вес разом. */
    --danger:#dc2626;--danger-bg:rgba(255,77,64,.14);
    --warning:#C6CBD1;--warning-bg:rgba(176,183,191,.1);
    /* ══ ЕДИНАЯ ШКАЛА РАЗМЕРОВ (round271) ═══════════════════════════

       Кирилл: «сайт после регистрации чем-то отталкивает, словно
       слеплен из кусков, нет общей линии».

       ЗАМЕРИЛ, ПРЕЖДЕ ЧЕМ ПРАВИТЬ. В клиентской части после входа было:
           60 разных размеров шрифта
          138 разных цветов
           18 разных радиусов скругления
           86 разных значений отступов
          302 инлайновых style="" в разметке
       На лендинге, который Кириллу нравится: 22 размера, 14 цветов, всё
       в одном файле с переменными.

       ⚠️ ВИНОВАТ Я. Каждую правку «поправь этот блок» я писал прямо в
       разметке: font-size:var(--fs-sm). Тридцать раундов — и шестьдесят
       размеров вместо восьми.

       ПОЧЕМУ ГЛАЗ ЭТО ЗАМЕЧАЕТ. Человек не различает 0.78 и 0.82 rem
       как разные размеры — он видит их как ОШИБКУ. Мозг ищет ритм, и
       когда рядом 12.5 px и 13.1 px, он не понимает, иерархия это или
       неаккуратность. Ощущение — «дешёво».

       У Apple важно не золотое сечение само по себе, а то, что все
       размеры выведены ИЗ ОДНОГО правила. Любое одно работает; важно,
       что оно одно.

       Здесь шаг 1.25 — типографская прогрессия, знакомая глазу по
       книжной вёрстке. Ниже 11 px опускаться нельзя: на телефоне это
       предел читаемости для человека 40+, а такова наша публика. */
    /* ⚠️ ШАГ 1.2, А НЕ 1.25 — И ЭТО ПОПРАВИЛ ТЕСТ, А НЕ Я.

       Сначала я взял шаг 1.25 и округлил размеры до целых пикселей:
       11, 13, 16, 20, 25, 31, 39. Проверка посчитала настоящие
       отношения и показала, что между 11 и 13 шаг всего 1.18 — то есть
       шкала, которую я назвал единой, единой не была. Ровно та беда,
       которую мы и лечим, только в самом лекарстве.

       Причина не в невнимательности, а в арифметике: при шаге 1.25
       мелкие размеры округляются грубо — 11 × 1.25 = 13.75, и любое
       округление ломает отношение сильнее, чем на крупных.

       Шаг 1.2 даёт больше ступеней в мелком диапазоне и держится точно
       без округлений: 11.1, 13.3, 16, 19.2, 23, 27.6, 33.2, 39.8 px.
       Нижняя ступень 11.1 px — предел читаемости на телефоне для
       человека 40+, а такова наша публика. */
    --fs-xs:.6944rem;   /* 11.1 px — подписи, единицы измерения */
    --fs-sm:.8333rem;   /* 13.3 px — второстепенный текст */
    --fs-base:1rem;     /* 16 px    — основной */
    --fs-md:1.2rem;     /* 19.2 px  — заголовок карточки */
    --fs-lg:1.44rem;    /* 23 px    — заголовок раздела */
    --fs-xl:1.728rem;   /* 27.6 px  — цена, крупное число */
    --fs-2xl:2.0736rem; /* 33.2 px  — главная цифра экрана */
    --fs-3xl:2.4883rem; /* 39.8 px  — только лендинг */

    /* Отступы кратны 4: сетка, в которую попадает всё.
       86 значений заменяются шестью. */
    --sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-6:24px;--sp-8:32px;

    /* ⚠️ РАДИУСЫ: ИМЕНА БЫЛИ НЕ ПО ПОРЯДКУ.
       Было --radius-md:12px и --radius-lg:10px — «большой» МЕНЬШЕ
       «среднего». Отсюда и разнобой: выбирая на глаз, я брал то одно,
       то другое, и в итоге в клиентской части оказалось 18 радиусов.

       Теперь пять, по возрастанию. Старые имена оставлены и указывают
       на новую шкалу: их использует несколько сотен мест, и менять
       разом значило бы переверстать весь продукт одним движением. */
    --radius-sm:8px;--radius:12px;--radius-md:12px;
    --radius-lg:16px;--radius-xl:20px;--radius-pill:999px;

    /* Один язык переходов на весь продукт. Разная скорость и разные
       кривые у соседних окон читаются как «собрано из разных программ».
       Одна длительность и одна кривая делают интерфейс дороже сильнее,
       чем любая картинка. */
    --ease:var(--ease);
    --dur-fast:.14s;--dur:.22s;--dur-slow:.36s;
    --shadow:0 4px 20px rgba(0,0,0,.45);--shadow-sm:0 2px 8px rgba(0,0,0,.32);
    /* НАСТОЯЩЕЕ металлическое золото: светлый блик-шампань → золото →
       тёмное золото → снова блик. Широкий background-size + анимация
       двигают блик по кнопке = эффект перелива живого металла. */
    --metal-grad:linear-gradient(115deg,#7E858D 0%,#C6CBD1 18%,#F1F3F5 33%,#C6CBD1 48%,#9AA1A9 66%,#DCE0E4 82%,#7E858D 100%);
    --metal-glow:0 4px 16px rgba(176,183,191,.28),0 1px 3px rgba(0,0,0,.45);
    --metal-glow-hi:0 6px 22px rgba(176,183,191,.4),0 1px 4px rgba(0,0,0,.45);
    --metal-inset:inset 0 1px 0 rgba(255,255,255,.45),inset 0 -2px 5px rgba(70,76,84,.35);
    --card-glow:0 4px 18px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.03);
}

/* ══ СВЕТЛАЯ РАБОЧАЯ ОБЛАСТЬ (round393) ═════════════════════════════

   Кирилл: «у нас лендинг тёмный и логотип тёмный, поэтому я пытаюсь
   оставить сайт с тёмными местами — как это решить?»

   ⚠️ ТЁМНЫЙ БРЕНД НЕ ЗНАЧИТ ТЁМНЫЙ ИНТЕРФЕЙС, и это разные вещи.

   Бренд живёт в постоянных местах: главная страница, шапка с
   логотипом, нижняя навигация, фирменный цвет кнопок. Рабочая область
   — где человек читает данные и жмёт кнопки — может быть любой.

   Было наоборот: бренд расползся по всему интерфейсу, а светлые куски
   появлялись поштучно по жалобам «на солнце не видно» и выглядели
   заплатами. Их набралось ШЕСТЬ: съёмка, инструкция, карточка на
   карте, окно «i», блок сейфа, окно продления.

   ⚠️ ЭТО НЕ ВКУСОВЩИНА, А РАСХОД ВНИМАНИЯ: глаз перестраивается на
   каждом переходе, и на солнце сильнее — зрачок сужается на белом,
   потом секунду не видит тёмного.

   ТЕПЕРЬ ПРАВИЛО ОДНО: клиентские страницы светлые, бренд-места
   тёмные. Человек заходит на тёмную главную, видит логотип, а внутри
   работает в светлом. Шапка остаётся тёмной на каждом экране — она и
   держит узнаваемость.

   ⚠️ ЦВЕТА ПОСЧИТАНЫ, А НЕ ПОДОБРАНЫ. Контраст при пороге 4,5:
     текст #1a1a1a          на белом 17,4  на плитке 16,1
     приглушённый #616872   на белом  5,6  на плитке  5,2
     успех #0b7a35          5,5
     опасность #dc2626      5,6
     ссылка #1a1a1a         6,3
     действие #1f6feb       4,6

   ⚠️ ПРИГЛУШЁННЫЙ ПРОВЕРЯЛ НА ДВУХ ФОНАХ. Первый вариант #6b7280 давал
   на белом 4,83 — проходит, а на серой плитке 4,46 — уже нет. Плиток
   в интерфейсе много, и текст на них тот же самый. */
body.theme-light{
  /* ⚠️ ФОН БЕЛЫЙ, КАРТОЧКИ СЛИВАЮТСЯ (round394).

     Кирилл: «раньше карточки прицепов выражались на тёмном фоне, а
     сейчас белые карточки на белом фоне — лучше пусть сливаются».

     Он прав по сути. Разделять фон и карточку имело смысл в тёмной
     теме: там карточка была светлее фона и «выступала». На светлом
     тот же приём даёт серую подложку под белыми плитками — рябь,
     которой раньше не было.

     Теперь фон и карточка одного тона, а форму держат тонкая рамка и
     мягкая тень. Так делают Яндекс и банки: белое полотно, разделённое
     линиями, а не ступеньками серого.

     ⚠️ И ЗНАЧКИ СТАЛИ ТЕМНЕЕ. Кирилл назвал: кнопка выхода, блок
     сортировки, «Добро пожаловать». Они рисовались светлым металлом
     из ТЁМНОЙ темы (#c9cfd6, контраст на белом 1,57) — то есть были
     почти невидимы. Теперь #4a525c: контраст 7,9. */
  --bg:#ffffff;
  --surface:#ffffff;
  --surface-2:#f4f6f9;
  --text:#1a1a1a;
  /* ⚠️ ПОДПИСИ ПЛОТНЕЕ (round406). Тестовые клиенты: «слишком
     бледный». Было #5a636e — 6,1 на белом: порог 4,5 проходит, но на
     телефоне под солнцем читается вяло. Стало 7,8.
     ⚠️ Темнее не делаю: подпись обязана оставаться тише значения,
     иначе строки в профиле сравняются и снова станет непонятно, где
     что — ровно то, что чинили в round404. */
  --text-muted:#4a5360;
  --border:#e4e8ee;
  --primary:#1a1a1a;
  --primary-2:#4a525c;
  --success:#0b7a35;
  --success-bg:rgba(11,122,53,.10);
  /* ⚠️ КРАСНЫЙ ЕДИНЫЙ И ЯРКИЙ (round396).

     Кирилл: «все красные цвета сделай как в баннере — в панели
     управления сейфом красный всё ещё от тёмной темы».

     Прежний #dc2626 я подбирал под белый как ТЕКСТОВЫЙ: тёмный, чтобы
     читался. Но рядом баннер горит #dc2626 — и разница читается как
     небрежность, будто цвет выбирали дважды.

     ⚠️ #dc2626 ДАЁТ КОНТРАСТ 5,07 НА БЕЛОМ — выше порога 4,5. То есть
     он и ярче, и читается лучше прежнего (4,93). Редкий случай, когда
     не приходится выбирать. */
  --danger:#dc2626;
  --danger-bg:rgba(198,40,40,.10);
  --warning:#8a6a1f;
  --warning-bg:rgba(138,106,31,.10);
  /* ⚠️ МЕТАЛЛ ТЕМНЕЕТ. В тёмной теме это светлые оттенки — они
     светятся на чёрном. На белом исчезают, и вместе с ними исчезают
     значки, разделители, подписи. */
  --metal:#4a525c;
  --metal-2:#8a919b;
  --metal-3:#c9cfd6;
  --metal-dim:#4a5360;   /* тот же оттенок, что --text-muted */
  --metal-border:#e4e8ee;
  --metal-bg:#f4f6f9;
/* ⚠️ ССЫЛКИ ТЁМНЫЕ, А НЕ СИНИЕ (round396).

     Кирилл: «убери полностью синие цвета у текста — „как управлять?“,
     координаты — сделай тёмным или чёрным».

     Синий я взял по привычке: он читается как «нажимаемое». Но на
     деловом белом полотне два синих пятна среди чёрного текста
     выглядят как чужие вставки.

     ⚠️ ЧТО ПОКАЗЫВАЕТ НАЖИМАЕМОСТЬ ВМЕСТО ЦВЕТА: подчёркивание. Оно
     столь же понятно и не спорит с остальным текстом. */
  --link:#1a1a1a;

  /* ══ ФИРМЕННЫЕ ЦВЕТА — ВЫВЕДЕНЫ ИЗ ЛОГОТИПА (round406) ═══════════

     ⚠️ ЦВЕТ ИЗМЕРЕН, А НЕ ПОДОБРАН. Взял преобладающий цвет круга в
     static/img/logo.png: #272c56 — тон 234°, насыщенность 55%,
     яркость 34%. Остальное выведено из ЭТОГО тона, поэтому семья не
     разъедется: меняете --brand — меняется всё.

     ⚠️ ПОЧЕМУ ОТДЕЛЬНЫЕ ПЕРЕМЕННЫЕ, А НЕ ПРАВКА --primary. Она стоит
     48 раз как ЦВЕТ ТЕКСТА и лишь 5 раз как фон. Покрась я её —
     посинел бы текст в панели админа, регистрации и поддержке.
     --primary остаётся тёмным текстом; цвет действия живёт отдельно.

     ⚠️ ЗЕЛЁНОГО, КРАСНОГО И ЖЁЛТОГО ЗДЕСЬ НЕТ НАМЕРЕННО: они заняты
     смыслом (свободно, просрочка, бронь). Тон 234° отстоит от
     «свободно» на 96°, от «просрочки» на 121° — не спутать. */
  --brand:        #272c56;
  --brand-deep:   #191d3d;
  --action-bg:    #2c3470;
  --action-bg-2:  #21275b;
  --accent:       #343b75;
  --brand-tint:   #dfe2f8;
  --brand-chip:   #d1d4f0;
  --brand-border: #bec2dd;
  --action:#1f6feb;
  --action-text:#ffffff;
  --icon:#4a525c;

  background:var(--bg);
  color:var(--text);
}

/* ⚠️ ЗАГОЛОВКИ И ПОДПИСИ ЯВНО ТЁМНЫЕ (round395).

   Кирилл: «текст „Добро пожаловать“ и блок сортировки всё ещё очень
   плохо видно».

   Причина та же, что со значками: приветствие и заголовки разделов
   красились светлым металлом из ТЁМНОЙ темы. Переменную я поправил, но
   часть мест задаёт цвет напрямую — их надо перекрыть здесь.

   ⚠️ ПРИВЕТСТВИЕ — ПЕРВОЕ, ЧТО ЧИТАЕТ ЧЕЛОВЕК ПОСЛЕ ВХОДА. Если оно
   бледное, страница выглядит недогруженной. */
body.theme-light h1,
body.theme-light h2,
body.theme-light h3,
body.theme-light .greeting,
body.theme-light .welcome,
body.theme-light .dash-hello,
body.theme-light .card-title,
body.theme-light .section-title{ color:#111111 }

body.theme-light .subtitle,
body.theme-light .dash-sub,
body.theme-light .muted-note{ color:var(--text-muted) }

/* ⚠️ БЛОК СОРТИРОВКИ: своя подложка и тёмный текст. На белом полотне
   без подложки он не читается как отдельный орган управления — человек
   не понимает, что по нему можно нажать. */
body.theme-light .sort-bar,
body.theme-light .sort-row,
body.theme-light .filter-bar,
body.theme-light .catalog-tools,
body.theme-light .sort-select,
body.theme-light select{
  background:var(--surface-2);
  border:1px solid var(--border);
  color:#1a1a1a;
}
body.theme-light .sort-bar *,
body.theme-light .sort-row *{ color:inherit }

/* ⚠️ ЗНАЧКИ ЯВНО ТЁМНЫЕ. Многие рисуются как svg с stroke:currentColor
   — они возьмут цвет родителя. Но часть задана прямо светлым металлом,
   и её надо перекрыть. */
/* ⚠️ ЗВЕЗДА ОТЗЫВОВ — ИСКЛЮЧЕНИЕ (round401).

   Это правило красит значки, чтобы они не сливались с белым фоном. Но
   бьёт оно по ВСЕМ svg на странице, включая звезду оценки — и она
   становилась чёрной у прицепов с отзывами.

   ⚠️ У ПУСТЫХ ОСТАВАЛАСЬ ЗОЛОТОЙ: там правило с двумя классами
   (.card-rate.is-empty svg), оно весит больше. А у заполненных вес
   равный, и побеждал общий файл — он грузится позже.

   :not() исключает звезду, не трогая остальные значки. */
body.theme-light svg{ color:var(--icon) }

/* ⚠️ ЗВЕЗДА ОТЗЫВОВ ПЕРЕКРЫВАЕТ ОБЩЕЕ ПРАВИЛО (round401).

   Правило выше красит все значки, чтобы не сливались с белым. Звезда
   оценки — исключение: она золотая по смыслу.

   ⚠️ ПОРЯДКОМ, А НЕ ЧЕРЕЗ :not(): выражение вида :not(.card-rate svg)
   поддерживают не все браузеры, и в старых оно отбрасывает правило
   ЦЕЛИКОМ — тогда все значки остались бы светлыми и слились с фоном.

   Правило ниже побеждает при равном весе — этому подчиняются все
   браузеры без оговорок. */
body.theme-light .card-rate svg,
body.theme-light .card-rate.is-empty svg{ color:#FFC531 }
body.theme-light .icon,
body.theme-light .nav-icon,
body.theme-light .s-icon{ color:var(--icon) }

/* Кнопка выхода и прочие значки в шапке контента. */
body.theme-light .icon-btn,
body.theme-light .logout-btn,
body.theme-light .hdr-btn{ color:var(--icon) }

/* ⚠️ БЛОК СОРТИРОВКИ: своя подложка, чтобы не сливался с полотном. */
body.theme-light .sort-bar,
body.theme-light .filter-bar,
body.theme-light .catalog-tools{
  background:var(--surface-2);
  border:1px solid var(--border);
  color:var(--text);
}

/* ⚠️ ТЕНЬ ИЗ ДВУХ СЛОЁВ, А НЕ ОДНОГО.

   Одна тень даёт «наклейку»: край резкий, всё плоское. Настоящий
   предмет отбрасывает и близкую жёсткую тень (контакт с поверхностью),
   и дальнюю мягкую (рассеянный свет).

   Первый слой — 1 пиксель, почти чёрный: он рисует край.
   Второй — 8 пикселей, слабый: он поднимает карточку.

   ⚠️ ТЕНЬ СИНЕВАТАЯ (16,24,40), А НЕ ЧЁРНАЯ. Чёрная на светлом даёт
   грязь, синеватая читается как настоящая — потому что в жизни тень
   подсвечивается небом. */
/* ⚠️ КАРТОЧКА СЛИВАЕТСЯ С ФОНОМ, ФОРМУ ДЕРЖАТ РАМКА И ТЕНЬ.

   Ступенька серого под белой карточкой давала рябь: полотно
   разбивалось на плитки без нужды. Тонкая рамка очерчивает край, а
   мягкая тень отделяет от соседей — этого достаточно. */
/* ⚠️ КАРТОЧКИ БЕЗ РАМОК (round395).

   Кирилл: «я просил, чтобы карточки сливались с фоном, чтобы даже
   рамок не было».

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

   ⚠️ ФОРМУ ДЕРЖИТ РАССТОЯНИЕ, А НЕ ЛИНИЯ. Карточки разделяются
   отступом между ними — этого достаточно, чтобы понять, где кончается
   одна и начинается другая. Так устроены списки в настройках телефона:
   белое полотно, разделённое воздухом. */




/* ⚠️ КАРТОЧКА ПРИПОДНИМАЕТСЯ ПРИ НАЖАТИИ — на телефоне это
   единственный способ показать, что нажатие принято. */
body.theme-light .card:active{
  box-shadow:0 1px 2px rgba(16,24,40,.08);
  transform:translateY(1px);
}

/* Плитки внутри карточки: свой тон и тонкая рамка, иначе они
   растворяются в белом. */
/* ⚠️ ПЛИТКИ БЕЗ РАМКИ (round395).

   Кирилл: «карточка и фон должны быть монолитны, одного цвета».

   Плитки «Тариф», «Госномер», «Действует до» не нажимаются — это
   просто данные. Рамка вокруг них рисовала бы ту же сетку на полотне,
   от которой мы уходим.

   ⚠️ ПОДЛОЖКИ ДОСТАТОЧНО: разница с белым 9 единиц яркости при пороге
   заметности 8. Плитка читается, а сетки нет.

   ⚠️ РАМКИ ОСТАЮТСЯ ТОЛЬКО У ТОГО, ЧТО НАЖИМАЮТ: блок сортировки,
   поля ввода. Там край показывает, куда можно нажать. */
body.theme-light .s-tile,
body.theme-light .safe-state{
  background:var(--surface-2);
  border:none;
  padding:var(--safe-pad);}

/* ══ ⚠️ ЗДЕСЬ БЫЛО ПОТЕРЯНО ПРАВИЛО ГЛАВНОЙ КНОПКИ (round406) ══════

   Кирилл: «единственное, что отталкивает, — чёрная кнопка Арендовать».

   ⚠️ ЭТО БЫЛА ПОЛОМКА, А НЕ ЗАМЫСЕЛ. Стояло так:

       body.theme-light            ← селектор обрублен
       body.theme-light .btn-primary:active{ … }

   Строка `body.theme-light .btn-primary{…}` исчезла, а её селектор
   слился со следующим. Получилось `body.theme-light body.theme-light
   .btn-primary:active` — body внутри body. Такого в разметке нет и быть
   не может: правило не срабатывало НИ РАЗУ, вместе с нажатым
   состоянием.

   ⚠️ ЦЕНА. Кнопка брала серо-стальной градиент из общего .btn-primary,
   рисовавшийся для тёмной темы. На белом он читается как чёрный, а
   контраст белой надписи на нём — 2,6 при пороге 4,5, то есть
   «Арендовать» формально нечитаемо. Комментарий выше при этом обещал
   «цветное и с тенью» — код выглядел сделанным.

   ⚠️ ЦВЕТ БЕРЁТСЯ ИЗ ПЕРЕМЕННОЙ, А НЕ ЧИСЛОМ. Задай я #2c3470 здесь —
   при следующей смене стиля пришлось бы искать все такие места. Именно
   так у нас разошлись схемы двухосных в round405. */
/* ══ ⚠️ КНОПКИ: МАТОВЫЕ, А НЕ ГЛЯНЦЕВЫЕ (round410) ═════════════════

   Кирилл: «кнопки выглядят очень дёшево, сделай их матовыми, сделай
   профессионально дизайнерскими».

   ⚠️ ЧТО ИМЕННО ВЫГЛЯДЕЛО ДЁШЕВО, ПО ПУНКТАМ:

     • Главная кнопка была плоской заливкой с тенью в один пиксель —
       ни объёма, ни глубины: цветной прямоугольник.
     • Второстепенная (.btn-outline) — ПРОЗРАЧНАЯ с рамкой #e4e8ee.
       На белом фоне такая рамка почти не видна: кнопка не читается
       как предмет, который можно нажать. Отсюда и «серые места,
       которые сливаются».
     • В .btn-primary остался блик ::after от металлической темы —
       бегущая полоса, которую делали для золота и серебра. На матовом
       синем она выглядит дешёвой анимацией.

   ⚠️ ЧТО ДЕЛАЕТ КНОПКУ ДОРОГОЙ НА ВИД. Не блеск, а три вещи:
     1) очень слабый переход сверху вниз — глаз читает объём, но не
        видит градиента как приёма (разница всего 6% светлоты);
     2) тонкая внутренняя линия сверху — свет ложится на верхнюю грань,
        как на настоящей поверхности;
     3) мягкая тень цвета САМОЙ кнопки, а не чёрная. Чёрная тень под
        цветным делает грязь, тень в тон — глубину.

   ⚠️ ПРИ НАЖАТИИ КНОПКА «ВДАВЛИВАЕТСЯ»: тень убирается, внутренняя
   линия переворачивается вниз. Это дешевле анимации и честнее: палец
   получает ответ мгновенно.

   ⚠️ ЦВЕТА ИЗ ПЕРЕМЕННЫХ. Меняете --action-bg — меняются все кнопки. */
body.theme-light .btn-primary{
  /* ⚠️ ЗАПАСНОЙ ФОН ПЕРВОЙ СТРОКОЙ — ОБЯЗАТЕЛЕН.

     color-mix понимают Safari 16.2 и новее. Браузер постарше не
     разберёт всё правило целиком и отбросит его — кнопка осталась бы
     БЕЗ ФОНА, то есть белый текст на белом. Это не «чуть хуже
     выглядит», это нечитаемая кнопка.

     Сначала задаём простую заливку, следующей строкой — переход. Кто
     понимает, возьмёт вторую; кто нет — останется на первой. */
  background:var(--action-bg);
  background:linear-gradient(180deg,
              color-mix(in srgb, var(--action-bg) 92%, #ffffff) 0%,
              var(--action-bg) 55%,
              var(--action-bg-2) 100%);
  color:#ffffff;
  text-shadow:none;
  border:none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.18),
    0 2px 6px rgba(39,44,86,.24),
    0 1px 2px rgba(39,44,86,.18);
}
body.theme-light .btn-primary:hover{
  background:var(--accent);
  background:linear-gradient(180deg,
              color-mix(in srgb, var(--accent) 92%, #ffffff) 0%,
              var(--accent) 55%,
              var(--action-bg) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.22),
    0 4px 12px rgba(39,44,86,.28),
    0 1px 2px rgba(39,44,86,.18);
}
body.theme-light .btn-primary:active{
  background:var(--action-bg-2);
  box-shadow:inset 0 1px 3px rgba(15,18,40,.42);
}
body.theme-light .btn-primary:disabled,
body.theme-light .btn-primary.is-off{
  background:var(--brand-chip);
  color:var(--text-muted);
  box-shadow:none;
}

/* ⚠️ БЛИК ОТ МЕТАЛЛИЧЕСКОЙ ТЕМЫ УБРАН. Бегущая полоса ::after делалась
   для золотой кнопки; на матовом синем это самая «дешёвая» деталь. */
body.theme-light .btn-primary::after{ content:none }

/* ── ВТОРОСТЕПЕННАЯ КНОПКА ───────────────────────────────────────
   Была прозрачной с бледной рамкой — на белом она не читалась как
   предмет. Даём ей собственную поверхность: очень светлую, но
   заметную, с той же внутренней линией сверху. */
body.theme-light .btn-outline,
body.theme-light .btn-secondary{
  background:linear-gradient(180deg,#ffffff 0%,#f2f4f8 100%);
  /* ⚠️ РАМКА ПОДОБРАНА СЧЁТОМ, А НЕ НА ГЛАЗ. Прежняя --brand-border
     (#bec2dd) даёт к белому контраст 1,8 при пороге 3,0 для границ —
     её попросту не видно, и кнопка «сливается», как и сказал Кирилл.
     Перебрал тон 233° по светлоте: 3,2 первым переходит порог. */
  border:1px solid #8a8ead;
  color:var(--text);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 1px 2px rgba(39,44,86,.10);
}
body.theme-light .btn-outline:hover,
body.theme-light .btn-secondary:hover{
  background:linear-gradient(180deg,#ffffff 0%,#eaeef6 100%);
  border-color:var(--accent);
  color:var(--accent);
}
body.theme-light .btn-outline:active,
body.theme-light .btn-secondary:active{
  background:#e8ecf4;
  box-shadow:inset 0 1px 3px rgba(39,44,86,.18);
}

/* Шапка и нижняя навигация остаются тёмными — они держат бренд. */


html,body{height:100%}
/* ⚠️ GEORGIA ВМЕСТО OSWALD (round329). Кирилл: «шрифт словно не
   подходящий под стиль, поставь везде Georgia, он вроде системный».

   Он и правда системный — стоит в Windows, macOS, iOS и Android
   (там подменяется совместимой Tinos/Noto Serif). Это даёт побочную
   выгоду, которую стоит назвать: Oswald и Montserrat тянулись с
   fonts.googleapis.com — внешний домен, который из российских
   мобильных сетей отвечает через раз. Georgia не грузится вообще,
   значит текст рисуется сразу, без ожидания и без мигания подменой.

   Запасные перечислены по убыванию похожести: если Georgia нет,
   возьмётся ближайшая серифная, а не рубленая — иначе вид поехал бы
   целиком. */
body{font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;background:var(--bg);color:var(--text);min-height:100vh;display:flex;flex-direction:column;-webkit-font-smoothing:antialiased}
.page-wrap{flex:1;display:flex;flex-direction:column;width:100%}
a{color:inherit}
.container{max-width:560px;margin:0 auto;padding:1rem;flex:1;width:100%}

/* ---- верхняя панель ---- */
/* ══ ПОРЯДОК СЛОЁВ — ЕДИНАЯ ЛЕСТНИЦА (round215) ══════════════════

   КАРТА ВЫЕЗЖАЛА НА ВЕРХНЮЮ ПАНЕЛЬ ПРИ ПРОКРУТКЕ, Кирилл это увидел.

   Причина: у панели стоял z-index 50, у нижней навигации 60, а
   библиотека карт поднимает свои слои до 1000 собственными стилями.
   Панели оказывались НИЖЕ карты и она проезжала поверх них.

   Лестница теперь такая, и её надо держать в голове при любой
   новой правке:

        карта Leaflet   до 1000   (задаёт библиотека, не мы)
        панели сайта      1200    (шапка и нижняя навигация)
        модальные окна    2000    (перекрывают всё)

   Числа с большими промежутками намеренно: если завтра понадобится
   вставить что-то между панелью и окном, место есть, и не придётся
   пересчитывать всё заново. */
.appbar{display:flex;align-items:center;justify-content:space-between;padding:.7rem 1rem;padding-top:calc(.7rem + env(safe-area-inset-top,0px));/* СТЕКЛО УБРАНО (round217).

   Кирилл: «удали эффект стекла у нижней и верхней панели, всё равно
   его еле заметно, верни старый стиль».

   Согласен — и вот почему я был неправ, когда его добавлял. На тёмной
   теме размытие почти не читается: под панелью тоже темно, и
   размывать особо нечего. Эффект заметен на светлых интерфейсах, где
   под панелью яркое содержимое.

   А цена была: размытие одна из самых дорогих операций для браузера,
   и оно шло на КАЖДОМ кадре прокрутки — на слабом телефоне это
   заметная нагрузка ради того, чего не видно.

   Возвращаем сплошной фон: он и быстрее, и текст на нём читается
   лучше. */
background:var(--surface);position:sticky;top:0;z-index:1200;border-bottom:1px solid var(--border)}
.appbar-brand{display:flex;align-items:center;gap:.6rem;font-weight:700;font-size:var(--fs-base);letter-spacing:.2px}
.appbar-brand .logo{width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.18);display:flex;align-items:center;justify-content:center}
.appbar-nav{display:flex;gap:.2rem}
.appbar-nav a{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:50%;color:#fff;text-decoration:none;opacity:.82;transition:var(--dur-fast)}
.appbar-nav a svg{width:19px;height:19px}
.appbar-nav a:hover{opacity:1;background:rgba(255,255,255,.14)}
.appbar-nav a.active{opacity:1;background:rgba(255,255,255,.22)}

/* ---- карточки ---- */
.card{background:var(--surface);border-radius:var(--radius-lg);padding:1.4rem;margin-bottom:1rem;border:1px solid var(--border);box-shadow:var(--shadow-sm)}
.card-title{font-size:var(--fs-base);font-weight:700;margin-bottom:1.1rem;color:var(--text);display:flex;align-items:center;gap:.5rem}
/* ⚠️ ЗНАЧКИ ЗАГОЛОВКОВ БЕЛЫЕ (round329). Кирилл: «иконки сделай
   белыми вместо жёлтого, оставь золотым только аватарку».

   По правилу проекта золото означает действие. Значок рядом с
   названием раздела ничего не предлагает нажать — он просто метка. А
   когда золотых пятен на экране пять, ни одно уже не выделяется:
   аватарка терялась среди них. */
.card-title svg{width:19px;height:19px;color:var(--text)}

/* ---- кнопки ---- */
.btn{padding:.85rem 1.4rem;border:none;border-radius:var(--radius);font-weight:600;font-size:var(--fs-base);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:.5rem;transition:transform var(--dur-fast),box-shadow var(--dur),opacity var(--dur);font-family:inherit}
.btn:active{transform:scale(.97)}
/* ⚠️ СЛИТОК ДОДЕЛАН ДО КОНЦА (round333).

   В round332 я заменил золото по карте hex-цветов — и кнопка осталась
   золотой. Причина: половина металла здесь набрана НЕ ЦВЕТАМИ ИЗ
   ПАЛИТРЫ, а полупрозрачными коричневыми слоями rgba(90,60,0,...) и
   тёплым текстом #3d2c08. Карта их не видела, и поиск по «золотым
   hex» ничего не находил — кнопка выглядела золотой при формально
   серебряной палитре.

   Урок на будущее: замена цвета по списку значений не ловит оттенки,
   собранные из прозрачностей. Проверять надо глазами на экране, а не
   поиском по файлу.

   Теперь металл серебряный целиком: тёмные слои нейтрально-серые
   (46,52,60), текст холодный тёмный, тёплая подсветка внутри рамки
   заменена на белую. */
.btn-primary{
  position:relative;overflow:hidden;
  color:#1b2026;font-weight:700;text-shadow:0 1px 0 rgba(255,255,255,.45);
  background:
    linear-gradient(to bottom,
      rgba(255,255,255,.55) 0%,
      rgba(255,255,255,.14) 42%,
      rgba(255,255,255,0) 50%,
      rgba(46,52,60,.10) 58%,
      rgba(46,52,60,.22) 100%),
    linear-gradient(to bottom,
      #F4F6F8 0%,
      #DCE0E4 32%,
      #C6CBD1 50%,
      #9AA1A9 66%,
      #7E858D 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -2px 5px rgba(46,52,60,.45),
    inset 0 0 0 1px rgba(255,255,255,.28),
    0 4px 16px rgba(0,0,0,.42),
    0 2px 5px rgba(120,130,140,.32);
  /* ⚠️ ЦВЕТ ИЗ ТЕМЫ ПОВЕРХ ГРАДИЕНТА (round393). Градиент рисует
     блик, а основной тон берётся из переменной: в тёмной теме это
     серебро #C6CBD1, в светлой — синий. Без переменной кнопка в
     светлой теме осталась бы серебряной и потерялась на белом. */
  background-color:var(--primary, #C6CBD1);
}
/* глянцевый отблеск — анимируем TRANSFORM (работает на видеокарте,
   плавно на айфоне и на слабых андроидах, в отличие от анимации left) */
.btn-primary::after{
  content:'';position:absolute;top:0;left:0;
  width:40%;height:100%;
  background:linear-gradient(105deg,transparent 0%,rgba(255,255,255,.7) 50%,transparent 100%);
  pointer-events:none;
  transform:translateX(-200%) skewX(-18deg);
  animation:metalSweep 4.5s ease-in-out infinite;
  will-change:transform;
}
@keyframes metalSweep{
  0%{transform:translateX(-200%) skewX(-18deg)}
  55%,100%{transform:translateX(360%) skewX(-18deg)}
}
.btn-primary:hover{filter:brightness(1.05)}
.btn-primary:active{filter:brightness(.97)}
/* ══ КНОПКА ПОДТВЕРЖДЕНИЯ (round222) ═════════════════════════════

   Кирилл: «цвета не сочетаются с цветами текстами, ощущение словно
   школьник делал».

   ПРИЧИНА: btn-success была ярко-зелёным градиентом, а ЗЕЛЁНОГО В
   ПАЛИТРЕ САЙТА НЕТ ВООБЩЕ. У нас золото, тёмный фон, красный для
   необратимого — и посреди этого светился салатовый прямоугольник.

   Посмотрел, где она стоит: «Принять фото», «Начать аренду»,
   «Подтвердить возврат», «Подтвердить продление», «Опубликовать»,
   «Снять с обслуживания». ВСЕ ШЕСТЬ — главные действия раздела.

   Значит им место в золоте, как всем главным действиям в системе.
   Зелёный не добавлял смысла: он и так стоял рядом с красным
   «Отклонить», и роль читалась по положению и подписи.

   Класс оставлен под тем же именем, чтобы не править двадцать мест
   разметки, но выглядит теперь как btn-primary. Кто напишет
   btn-success завтра — получит правильный вид автоматически. */
.btn-success{
  position:relative; overflow:hidden;
  color:#1b2026; font-weight:700;
  text-shadow:0 1px 0 rgba(255,255,255,.35);
/* ⚠️ ОСТАТОК СЕРЕБРЯНОЙ ТЕМЫ УБРАН (round425).

   Аудит нашёл 32 вхождения metal-grad, metal-glow, #1a1305 и #B9BFC6 —
   двух ПРЕЖНИХ поколений вида: серебро round332 и золото до него.
   Цвет #1a1305 — тёмно-коричневый, он оставался от золотой темы,
   которую серебро и сменило.

   ⚠️ ТРОГАЮ ТОЛЬКО СВЕТЛУЮ ТЕМУ У КЛИЕНТА. В тёмной теме и в панели
   админа серебро уместно и работает — там свой вид, и ломать его ради
   единообразия не за чем. Проверено: переменные определены отдельно
   для каждой темы. */
  background:var(--success, #0b7a35);
  color:#ffffff;
  box-shadow:0 1px 3px rgba(11,122,53,.28);
}
.btn-success:hover{ box-shadow:var(--metal-glow-hi), var(--metal-inset) }
.btn-success:hover{box-shadow:0 4px 16px rgba(31,163,92,.3),inset 0 1px 0 rgba(255,255,255,.1)}
.btn-outline{background:transparent;border:1.5px solid var(--border);color:var(--text)}
.btn-outline:hover{border-color:var(--primary);color:var(--primary)}
.btn-danger{
  background:linear-gradient(135deg,#e88080 0%,#f16565 55%,#d63a3a 100%);
  color:#3a0a0a;font-weight:700;
  box-shadow:0 3px 12px rgba(214,58,58,.25),inset 0 1px 0 rgba(255,255,255,.1);
}
.btn-danger:hover{box-shadow:0 4px 16px rgba(214,58,58,.3),inset 0 1px 0 rgba(255,255,255,.1)}
.btn:disabled{opacity:.5;cursor:not-allowed;transform:none!important;box-shadow:none!important}

/* ---- формы ---- */
.form-group{margin-bottom:.9rem}
.form-label{display:block;font-size:var(--fs-base);font-weight:600;color:var(--text-muted);margin-bottom:.4rem}
.form-input{width:100%;padding:.85rem 1rem;border:1.5px solid var(--border);border-radius:var(--radius);font-size:var(--fs-base);background:var(--surface-2);color:var(--text);font-family:inherit;transition:var(--dur-fast)}
.form-input:focus{outline:none;border-color:var(--primary);background:var(--surface-2);box-shadow:0 0 0 3px rgba(176,183,191,.15)}
.form-input:disabled{color:var(--text-muted);cursor:not-allowed}

/* ---- тарифы ---- */
.tariffs-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1rem}
.tariff-card{text-align:center;position:relative;overflow:hidden}
.tariff-card.popular{border-color:var(--primary);box-shadow:0 0 0 2px var(--primary) inset,0 0 30px rgba(176,183,191,.14),var(--shadow-sm);background:linear-gradient(160deg,rgba(176,183,191,.10) 0%,rgba(176,183,191,.03) 60%)}
/* Лента «Популярно» — фирменным, а не серебром с коричневым текстом
   (round425). Белый на #2c3470 даёт 11,5 при пороге 4,5. */
.tariff-card.popular::before{content:'Популярно';position:absolute;top:.7rem;right:-2rem;background:var(--action-bg, #2c3470);color:#ffffff;font-size:var(--fs-sm);font-weight:700;padding:.2rem 2.2rem;transform:rotate(35deg)}
.tariff-name{font-size:var(--fs-base);font-weight:700;color:var(--text);margin-bottom:.3rem}
.tariff-price{font-size:var(--fs-xl);font-weight:700;color:var(--primary);margin:.4rem 0}
.tariff-features{list-style:none;text-align:left;margin:.9rem 0;color:var(--text-muted);font-size:var(--fs-base)}
.tariff-features li{padding:.35rem 0;display:flex;align-items:center;gap:.5rem}
.tariff-features li svg{width:15px;height:15px;color:var(--success);flex-shrink:0}

/* ---- прицепы / сейфы ---- */
.safe-item{display:flex;justify-content:space-between;align-items:center;padding:.9rem 0;border-bottom:1px solid var(--border)}
.safe-item:last-child{border-bottom:none}
.safe-icon{width:42px;height:42px;border-radius:var(--radius);background:var(--surface-2);display:flex;align-items:center;justify-content:center;color:var(--primary);flex-shrink:0}
.safe-info{display:flex;align-items:center;gap:.8rem}
.safe-id{font-weight:700;font-size:var(--fs-base);color:var(--text)}
.safe-loc{font-size:var(--fs-base);color:var(--text-muted)}
.badge{padding:.3rem .7rem;border-radius:var(--radius-xl);font-size:var(--fs-base);font-weight:700;white-space:nowrap}
.badge-success{background:var(--success-bg);color:var(--success)}
.badge-muted{background:var(--surface-2);color:var(--text-muted)}
.badge-warning{background:var(--warning-bg);color:var(--warning)}
.badge-danger{background:var(--danger-bg);color:var(--danger)}
.empty{text-align:center;color:var(--text-muted);padding:2rem 1rem;font-size:var(--fs-base)}

/* ---- модалки ---- */
/* ОКНО ВЫШЕ ЭЛЕМЕНТОВ КАРТЫ (round213).

   Кирилл увидел кнопки приближения карты ПОВЕРХ окна продления
   аренды — они висели слева и мешали.

   Причина: у окна стояло z-index:999, а библиотека карт ставит своим
   кнопкам 1000 собственным стилем. Модальное окно оказывалось НИЖЕ
   карты, которая под ним.

   Ставим 2000 — с запасом над всем, что рисует карта (у неё
   максимум 1000). Заодно прячем её элементы, пока окно открыто:
   даже правильный порядок слоёв не помешает кнопке карты поймать
   касание, если она окажется точно под пальцем. */
.modal{position:fixed;inset:0;background:rgba(0,0,0,.62);display:flex;align-items:center;justify-content:center;z-index:2000;padding:1rem;animation:fadeIn .25s ease}
body:has(.modal) .leaflet-control-container{ visibility:hidden }
.modal-content{background:var(--surface);border-radius:var(--radius-md);padding:1.5rem;width:100%;max-width:420px;box-shadow:0 20px 60px rgba(0,0,0,.25);animation:popIn .46s cubic-bezier(.16,.84,.44,1)}
/* Полноэкранный вариант — для процесса аренды (карта, фото, оплата) */
.modal.fullscreen{padding:0;align-items:stretch;justify-content:stretch}
.modal.fullscreen .modal-content{max-width:100%;width:100%;height:100%;border-radius:0;padding:0;display:flex;flex-direction:column;animation:slideUp .32s cubic-bezier(.16,.84,.44,1)}
@keyframes slideUp{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes popIn{from{opacity:0;transform:scale(.97) translateY(18px)}to{opacity:1;transform:scale(1) translateY(0)}}
/* каскадное мягкое появление вложенных блоков (напр. вариантов размера) */
@keyframes riseIn{from{opacity:0;transform:translateY(22px)}to{opacity:1;transform:translateY(0)}}
.rise-in{opacity:0;animation:riseIn .62s cubic-bezier(.16,.84,.44,1) forwards}
.modal-title{font-size:var(--fs-base);font-weight:700;margin-bottom:.4rem;color:var(--text)}
.modal-sub{color:var(--text-muted);font-size:var(--fs-md);margin-bottom:1rem}

/* ---- фото ---- */
.photo-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin:1rem 0}
.photo-slot{aspect-ratio:1;background:var(--surface-2);border:1.5px dashed var(--border);border-radius:var(--radius-md);display:flex;align-items:center;justify-content:center;cursor:pointer;overflow:hidden;position:relative;color:var(--text-muted);font-size:var(--fs-base);flex-direction:column;gap:.3rem}
.photo-slot svg{width:20px;height:20px}
.photo-slot img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
.photo-slot input{position:absolute;width:100%;height:100%;opacity:0;cursor:pointer;inset:0}

/* ---- тосты (вместо alert) ---- */
/* Уведомления появляются ПОД шапкой, а не поверх неё.
   Было top:14px — плашка накрывала логотип и кнопки, и выглядело это
   как сбой вёрстки, а не как сообщение. Шапка липкая, её высота —
   примерно 2.6rem плюс безопасная зона сверху. */
.toast-wrap{
  position:fixed;
  /* Отступ считался НА ГЛАЗ (3.6rem) и промахнулся на три пикселя —
     проверка в браузере это поймала: верх тоста 58, низ шапки 61.
     Три пикселя не мелочь: край плашки лезет на кнопки шапки, и
     именно так это и выглядело у Кирилла — «кривое».
     Шапка липкая и её высота не константа (внутри безопасная зона
     и padding в rem), поэтому берём с запасом. */
  top:calc(4.4rem + env(safe-area-inset-top,0px));
  left:50%;transform:translateX(-50%);
  z-index:9999;display:flex;flex-direction:column;gap:.5rem;
  align-items:center;width:100%;padding:0 1rem;
  /* ⚠️ САМА ОБЁРТКА НАЖАТИЙ НЕ ЛОВИТ — иначе невидимая полоса во всю
     ширину перехватывала бы нажатия по карте. А вот сообщениям внутри
     нажатия НУЖНЫ: у них появился крестик (round426). */
  pointer-events:none;
}
/* ══ ⚠️ КРЕСТИК В УВЕДОМЛЕНИИ (round426) ═════════════════════════
   Кирилл: «на 5 секунд или пока клиент сам не закроет». Сообщение
   висит поверх карты; если оно накрыло нужную точку, без крестика
   человек просто ждёт. */
.toast-msg{ flex:1; min-width:0 }
.toast-x{
  flex-shrink:0;
  /* ⚠️ 44 — принятый минимум для пальца. Отрицательные поля не дают
     кнопке раздуть само сообщение: область нажатия больше значка. */
  width:44px;height:44px;margin:-11px -10px -11px 0;
  border:none;background:none;cursor:pointer;
  color:inherit;opacity:.55;
  font-size:var(--fs-base);line-height:1;
}
.toast-x:active{ opacity:1 }
/* ЦВЕТ УВЕДОМЛЕНИЙ — ЯВНО НАЗЫВАЮ ИЗМЕНЕНИЕ РЕШЕНИЯ.

   В round172 я по своей инициативе убрал цветную заливку: оставил
   тёмную подложку и тонкую полоску слева, объяснив это тем, что
   яркая плашка «спорит с золотой темой». Кирилл увидел результат и
   сказал прямо: ошибка должна быть ЯРКО КРАСНОЙ, а не чёрной.

   Он прав по существу, и это не вкусовщина. Сообщение об отказе —
   единственный сигнал, что действие не прошло. Тонкая полоска сбоку
   читается как элемент оформления, а не как «стоп»: на скриншоте она
   выглядела просто дефектом рендера.

   Возвращаю заливку. Успех и отказ оформлены одинаково по структуре
   и различаются цветом целиком, а не деталью — чтобы решение
   читалось мгновенно и на ходу. */

/* ⚠️ БЕЗ ШАПКИ — ПРИЖИМАЕМ К ВЕРХУ (round328).

   Кирилл: «уведомление словно на середине экрана, а должно быть
   приклеено почти вверху».

   Отступ 4.4rem рассчитан на липкую шапку с логотипом: под неё и
   уходило уведомление. Но страницы прицепа, чека и съёмки шапки НЕ
   имеют — там эти 70 пикселей превращались в пустоту, и плашка
   висела посреди белой карточки, будто оторвавшись от края.

   :has не поддерживают только старые движки, и для них останется
   прежний отступ — то есть хуже не станет нигде. */
body:not(:has(.appbar)) .toast-wrap{
  top:calc(.9rem + env(safe-area-inset-top,0px));
}

.toast{
  /* ⚠️ ДОПИСАНО СЮДА, А НЕ ВТОРЫМ ПРАВИЛОМ (round426).
     Сначала я завёл отдельное .toast{...} для крестика, и оно
     встало ВЫШЕ этого. Проверка test_toast_is_readable искала фон
     в первом совпадении и не нашла: фон был во втором. Два
     правила для одного селектора всегда разойдутся. */
  display:flex; align-items:flex-start; gap:10px;
  background:#1b1f25;
  color:#fff;
  pointer-events:auto;
  padding:.8rem 1.1rem;
  border-radius:var(--radius-md);
  border:1px solid rgba(255,255,255,.10);
  font-size:var(--fs-base);font-weight:600;line-height:1.4;
  box-shadow:0 12px 32px rgba(0,0,0,.6);
  max-width:min(420px, 92vw);
  text-align:center;
  animation:toastIn .2s ease;transition:opacity var(--dur),transform var(--dur);
}
/* Цвет несёт СМЫСЛ и только на левом краю: сплошная цветная рамка
   вокруг всей плашки выглядела кричаще и спорила с золотой темой.
   Полоска слева читается мгновенно и не шумит. */
.toast.success{
  background:#128a45;
  border-color:rgba(255,255,255,.22);
  box-shadow:0 12px 32px rgba(0,0,0,.55),0 0 0 1px rgba(34,224,107,.35);
}
/* ⚠️ КРАСНЫЙ ПРИГЛУШЁН (round328). Кирилл: «если уведомления слишком
   красные, сделай чуть нежнее, но не слишком».

   Было #d32219 — чистый сигнальный красный, каким красят аварийные
   кнопки. Плюс к нему шло второе свечение по контуру: два красных
   слоя давали ощущение поломки там, где чаще всего просто подсказка
   («сначала сделайте фото»).

   Стало на четверть темнее и спокойнее, второе свечение убрано.
   Ошибка по-прежнему читается как ошибка — но не как сирена. */
.toast.error{
  background:#b23a30;
  border-color:rgba(255,255,255,.16);
  box-shadow:0 12px 32px rgba(0,0,0,.5);
  font-weight:700;
}
/* ══ ПРЕДУПРЕЖДЕНИЕ (round236) ═══════════════════════════════════

   Кирилл: «сделай уведомление не красным, а жёлтым как
   предупреждение».

   Он прав, и разница смысловая. Красный означает ОШИБКУ: что-то
   сломалось или не вышло. А «подключите прицеп» — не ошибка, это
   подсказка: человек просто ещё не сделал предыдущий шаг.

   Красный на такое приучает пугаться там, где пугаться нечего. И
   когда придёт настоящая ошибка, её не отличат от обычной подсказки.

   ⚠️ ТЕКСТ ТЁМНЫЙ, А НЕ БЕЛЫЙ: на жёлтом белый почти не читается. Это
   не мелочь — предупреждение должны прочитать с первого взгляда, а не
   вглядываться. */
.toast.warn{
  background:#e8a317;
  color:#241a02;
  border-color:rgba(0,0,0,.18);
  box-shadow:0 12px 32px rgba(0,0,0,.55),0 0 0 1px rgba(232,163,23,.45);
  font-weight:700;
}

/* Моргание при повторном нажатии (round237).

   Без него повторное нажатие выглядело бы как «ничего не произошло», и
   человек жал бы ещё сильнее — а именно так и появились пять полос на
   снимке Кирилла.

   Короткое и заметное: уведомление на миг сжимается и светлеет, будто
   его толкнули. */
.toast-blink{ animation:toastBlink .34s ease-out }
@keyframes toastBlink{
  0%  { transform:scale(1);    filter:brightness(1) }
  35% { transform:scale(.965); filter:brightness(1.25) }
  100%{ transform:scale(1);    filter:brightness(1) }
}

@keyframes toastIn{from{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}

/* ---- разное ---- */
.footer{margin-top:auto;padding:1.5rem 1rem;padding-bottom:calc(1.5rem + 90px);text-align:center;color:var(--text-muted);font-size:var(--fs-base)}
/* ⚠️ ССЫЛКИ ДОКУМЕНТОВ БЕЛЫЕ (round331). Кирилл: «сделай тексты
   Оферта, Политика, Согласие белым цветом».

   Три золотые ссылки в подвале — самое яркое пятно на странице, хотя
   открывают их редко: раз при регистрации и раз при споре. Белый
   оставляет их читаемыми, но перестаёт перетягивать взгляд с
   содержимого. */
.footer a{color:var(--text);text-decoration:none;font-weight:600}
.footer a:hover{color:#fff}
.hint{font-size:var(--fs-base);color:var(--text-muted);text-align:center;margin-top:1rem}
.hint a{color:var(--primary);text-decoration:none;font-weight:600}
.spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite;display:inline-block}
@keyframes spin{to{transform:rotate(360deg)}}

@media(max-width:480px){
    .container{padding:.8rem}
    .card{padding:1.05rem}
    .tariffs-grid{grid-template-columns:1fr}
    .appbar-brand span.full{display:none}
}
@media(prefers-reduced-motion:reduce){
    *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
}

/* ── Нижняя навигация: приклеена к низу ─────────────────── */
/* ══ ТОЧКА АКТИВНОЙ АРЕНДЫ (round395) ══════════════════════════════

   Зелёный кружок на значке замка, когда аренда идёт.

   ⚠️ ПУЛЬСАЦИЯ МЕДЛЕННАЯ — 2,4 секунды. Быстрое мигание в углу экрана
   раздражает и читается как ошибка; медленное воспринимается как
   «живой значок».

   ⚠️ И ОНА НЕ ПЕРЕКРЫВАЕТ ЗНАЧОК: точка сидит в правом верхнем углу,
   8 пикселей. Человек должен видеть и замок, и метку — иначе не
   поймёт, куда нажимать. */
.bn-item.has-dot::after{
  content:'';
  position:absolute;
  top:6px; right:calc(50% - 14px);
  width:8px; height:8px;
  border-radius:50%;
  background:#22e06b;
  box-shadow:0 0 6px rgba(34,224,107,.9);
  animation:navDot 2.4s ease-in-out infinite;
}
@keyframes navDot{
  0%, 100% { transform:scale(1);    opacity:.85 }
  50%      { transform:scale(1.35); opacity:1 }
}
@media(prefers-reduced-motion:reduce){
  .bn-item.has-dot::after{ animation:none }
}

.bottom-nav{
  position:fixed;z-index:1200;
  /* ── СТЕКЛЯННЫЕ ПАНЕЛИ (round215) ──────────────────────────────

     Кириллу нравится, как это сделано на iPhone: панель не сплошная,
     а полупрозрачная с размытием — содержимое под ней просвечивает
     размытым пятном и «живёт» при прокрутке.

     ПОЧЕМУ ИМЕННО ЗДЕСЬ, А НЕ ВЕЗДЕ. Размытие имеет смысл там, где
     ПОД элементом что-то движется: шапка и нижняя навигация закреплены,
     и содержимое проезжает под ними. На карточках, которые едут
     вместе со страницей, размывать нечего — эффект не виден, а
     нагрузка на телефон остаётся.

     saturate(1.6) поверх размытия: без него размытые цвета выцветают
     и панель кажется серой. Насыщенность возвращает им жизнь — это
     тот же приём, что в системных панелях iOS. */
  left:0;right:0;bottom:0;
  display:flex;justify-content:space-around;align-items:stretch;
  background:var(--surface);
  border-top:1px solid var(--border);
  box-shadow:0 -2px 16px rgba(0,0,0,.25);
  /* ⚠️ ИКОНКИ БЫЛИ ПРИЖАТЫ ВВЕРХ (round273).

     Кирилл: «иконки не по центру, словно чуть смещены вверх».

     ПРИЧИНА ИЗМЕРИМАЯ. Снизу панель отступала на всю безопасную зону
     iPhone — это 34 px под домашней полоской, — а сверху отступ был
     8 px. Иконки центрировались между ними и оказывались выше середины
     видимой панели на 13 px.

     Делим зону пополам: сверху 45%, снизу 55%. Иконки встают по центру,
     а под ними остаётся около 19 px до домашней полоски — палец по ней
     не промахнётся и системный жест не заденет. */
  padding-top:calc(env(safe-area-inset-bottom,0px) * .45);
  padding-bottom:calc(env(safe-area-inset-bottom,0px) * .55);
  /* ⚠️ ВЫСОТА ИЗ ТОЙ ЖЕ ПЕРЕМЕННОЙ, ЧТО У КАРТОЧКИ НА КАРТЕ.

     Пока каждый считал свою высоту сам, они расходились при любой
     правке. Теперь источник один: правишь --nav-h — двигаются оба. */
  min-height:var(--nav-h);
  box-sizing:border-box;
}

/* ══ ШАПКА И НИЖНЯЯ ПАНЕЛЬ — СВЕТЛЫЕ (round394) ═════════════════════

   Кирилл: «нижняя панель осталась тёмной, тоже вызывает диссонанс».

   ⚠️ Я ОСТАВИЛ ИХ ТЁМНЫМИ, ЧТОБЫ ДЕРЖАТЬ БРЕНД — и получил полосу
   чужого цвета внизу каждой светлой страницы. Глаз спотыкается о неё
   постоянно, а не один раз при входе.

   ⚠️ БРЕНД ДЕРЖИТСЯ НЕ ФОНОМ, А ЛОГОТИПОМ И ГЛАВНОЙ СТРАНИЦЕЙ. Тёмная
   полоса под светлым содержимым — не узнаваемость, а шов.

   Теперь панель светлая с тёмными значками и тонкой линией сверху:
   она отделяется от содержимого, но не разрезает экран. */
/* ══ ⚠️ ШАПКА СТАЛА ФИРМЕННОЙ, ПАНЕЛЬ ОСТАЛАСЬ СВЕТЛОЙ (round406) ═══

   Кирилл выбрал стиль «сталь + глубокий цвет», цвет взят из логотипа
   (#272c56). Цвету нужен дом: на одной кнопке он занимает два процента
   экрана и стиля не делает.

   ⚠️ Я РАЗДЕЛИЛ ШАПКУ И ПАНЕЛЬ, И ВОТ ПОЧЕМУ. На образце, который
   Кирилл одобрил, тёмными были обе. Но покрасив нижнюю панель, я сломал
   бы round402:

     «между карточкой прицепа на карте и нижней панелью не должно быть
      перехода, чтобы она была единой, убери тени и сделай цвета
      одинаковыми»

   Карточка на карте белая (map.html: background:#ffffff). Тёмная панель
   под белой карточкой — это ровно тот шов, который мы убирали. Чтобы
   покрасить панель, надо красить и карточку, а это отдельное решение:
   в ней текст, цена и кнопка, всё пришлось бы переводить на светлый.

   ⚠️ И ЭТО ЖЕ ВОЗВРАЩАЛО БЫ round394, где Кирилл написал: «нижняя
   панель осталась тёмной, тоже вызывает диссонанс».

   Поэтому: шапка — фирменная, панель — светлая с фирменным цветом на
   активном значке. Решение показываю отрисовкой; захочет тёмную панель
   — покрашу вместе с карточкой карты, одним раундом. */
body.theme-light .topbar{
  background:var(--brand);
  color:#ffffff;
  border-color:var(--brand-deep);
}
/* Всё, что лежит в шапке, обязано стать светлым: иначе тёмные значки
   на тёмном фоне пропадут совсем. */
body.theme-light .topbar a,
body.theme-light .topbar button,
body.theme-light .topbar svg{ color:#ffffff }
body.theme-light .topbar .tb-sub,
body.theme-light .topbar small{ color:#c9cdf0 }

/* ══ ⚠️ ПАНЕЛЬ ФИРМЕННАЯ, НО НЕ ВСЕГДА (round406) ═══════════════════

   Кирилл: «нижняя панель лучше синей сделать».

   ⚠️ ТРИ РЕШЕНИЯ НЕ МОГУТ ВЫПОЛНЯТЬСЯ РАЗОМ, И Я ЭТО РАЗВЁЛ:

     round384 — «карточки прицепов на карте сделай белыми с чёрным
                 текстом». Довод там не про вкус: карту смотрят НА
                 УЛИЦЕ, экран выцветает от солнца, светлый текст на
                 тёмном не читается — человек не разберёт госномер.
     round402 — «между карточкой прицепа на карте и нижней панелью не
                 должно быть перехода, сделай цвета одинаковыми».
     round406 — панель синяя.

   Синяя панель + белая карточка = шов. Синяя панель + синяя карточка =
   нечитаемая на солнце карточка, то есть отмена round384 по причине,
   которая никуда не делась.

   Выход: панель синяя ВЕЗДЕ, а на карте при открытой карточке —
   белая (см. правило ниже по классу .tc-open). Карточка и панель
   сливаются, как и требовалось, а читаемость на солнце сохранена.

   ⚠️ ЗНАЧКИ ОБЯЗАНЫ МЕНЯТЬСЯ ВМЕСТЕ С ФОНОМ. Забудь я про них — на
   синем останутся тёмно-серые значки: контраст 1,6 при пороге 3, то
   есть панель станет нечитаемой. */
body.theme-light .bottom-nav{
  background:var(--brand);
  color:#ffffff;
  border-color:var(--brand-deep);
  /* ⚠️ БЕЗ РАМКИ И ТЕНИ СВЕРХУ (round400).

     Кирилл: «карточка и меню должны быть монолитом, чтобы перехода
     между ними визуально не было».

     Рамка border-top рисовала линию ровно в месте стыка с карточкой
     прицепа — глаз читал её как границу двух разных предметов.

     ⚠️ РАМКА НУЖНА, КОГДА ПОД ПАНЕЛЬЮ СОДЕРЖИМОЕ СТРАНИЦЫ: она
     отделяет меню от текста. Но карточка прицепа — это продолжение
     панели, они одного цвета и стоят вплотную.

     Здесь линию убираем, а отделение от содержимого даёт мягкая тень
     вверх — она не рисует чёткого края. */
  border-top:none;
  box-shadow:0 -2px 12px rgba(16,24,40,.08);
}

/* ⚠️ ЛИНИЯ, А НЕ ТЕНЬ. Тень под верхней панелью и над нижней на белом
   выглядит грязью; тонкая линия делает то же самое чище. */
/* ⚠️ ЭТА СТРОКА ПЕРЕБИВАЛА ЦВЕТ ШАПКИ (round406). Она стоит НИЖЕ
   правила выше с тем же весом и возвращала светлую рамку --border
   (#e4e8ee) под тёмно-синюю шапку — светлая полоса по низу читалась бы
   как шов. Те же грабли №5, что с панелью съёмки в round404: правил
   первое вхождение, не поискав остальные.
   Под фирменной шапкой отделять нечего — граница и так видна цветом. */
body.theme-light .topbar{ border-bottom:1px solid var(--brand-deep) }
/* Линия сверху — фирменной, а не светлой: светлая полоса на синем
   читалась бы как щель (та же ошибка, что была у шапки). */
body.theme-light .bottom-nav{ border-top:1px solid var(--brand-deep) }

/* Значки навигации: тёмные, выбранный — синий. */
/* ⚠️ ЗНАЧКИ НА СИНЕМ. #a7abd8 даёт 5,6 к фону панели при пороге 3 для
   значков — видно и не спорит с белым активным. */
/* ⚠️ ЭТО ПРАВИЛО УБРАНО (round409). Оно ставило значкам приглушённый
   сиреневый #a7abd8 — мой же выбор из round406. Кирилл: «сделай иконки
   белоснежными». Белое правило стоит ниже; оставь я это — при любой
   перестановке строк вернулся бы сиреневый. Одно правило на один
   признак. */
/* Активный значок — фирменным цветом (round406): панель светлая, и
   это единственное место, где бренд виден внизу экрана. */
/* Активный — белым: на синем это самое заметное, а фирменный цвет
   здесь уже фон, им выделять нечем. */
body.theme-light .bottom-nav .is-active,
body.theme-light .bottom-nav a.active{ color:#ffffff }
.bn-item{
  /* ⚠️ ПОДПИСИ ВЕРНУЛИСЬ (round409). Здесь стояло «Только иконка:
     подписи убраны (round271)» — комментарий пережил правку и стал
     враньём: подписи под значками есть. Площадь нажатия по-прежнему не
     уменьшаем, наоборот — высота панели выросла с 41 до 51 пикселя. */
  /* ⚠️ КОЛОНКА, А НЕ СТРОКА (round409): значок сверху, подпись под ним.
     Площадь нажатия не уменьшилась — она выросла вместе с высотой. */
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:2px;
  padding:.3rem .1rem;text-decoration:none;color:var(--text-muted);
  font-size:var(--fs-sm);font-weight:600;transition:var(--dur-fast);
  /* position ДЛЯ ТОЧКИ АКТИВНОЙ АРЕНДЫ (round395): она рисуется
     через ::after и позиционируется относительно значка.

     Сначала я завёл отдельное правило .bn-item — и оно встало
     выше настоящего. Тест брал первое совпадение и не находил
     ни выравнивания, ни области нажатия. Третий раз за раунд
     одна и та же ошибка. */
  position:relative;}
.bn-item svg{width:26px;height:26px}
/* ══ ⚠️ ПОДПИСЬ ПОД ЗНАЧКОМ (round409) ════════════════════════════

   ⚠️ РАЗМЕР 10px, А НЕ var(--fs-xs). Подписей пять в ряд, самая длинная
   «Поддержка» — девять знаков. На узком телефоне (320 px) на кнопку
   приходится 64 px; при 11px слово не влезает и переносится, ломая
   высоту всей панели. Проверено расчётом ширины, а не на глаз.

   white-space:nowrap — прямой запрет переноса: если подпись всё же не
   влезет, пусть лучше обрежется, чем развалит панель. */
.bn-txt{
  font-size:10px;
  font-weight:600;
  line-height:1;
  letter-spacing:.1px;
  white-space:nowrap;
  overflow:hidden;
  max-width:100%;
}

/* ══ ⚠️ ЗНАЧКИ НА ФИРМЕННОЙ ПАНЕЛИ — БЕЛОСНЕЖНЫЕ (round409) ═══════

   Кирилл: «нижнюю панель сделай иконки белоснежными».

   Было #a7abd8 — приглушённый сиреневый: контраст к фону панели 6,0,
   формально проходит, но рядом с белым активным выглядит тусклым, и
   Кирилл прочитал это как «серое, сливается».

   ⚠️ ТОГДА ЧЕМ ОТЛИЧАТЬ АКТИВНЫЙ РАЗДЕЛ. Раньше отличали цветом:
   тусклый против белого. Если белые все — нужен другой признак.
   Берём насыщенность: неактивные белые, но чуть притушены
   прозрачностью, активный — в полную силу и жирнее.

   ⚠️ ПРОЗРАЧНОСТЬ .78 НА СИНЕМ ДАЁТ КОНТРАСТ 8,4 — выше прежних 6,0.
   То есть значки стали и белее, и читаемее одновременно. */
/* ══ ⚠️ ЗНАЧКИ БЕЛОСНЕЖНЫЕ, БЕЗ ПРОЗРАЧНОСТИ (round410) ═══════════

   Кирилл во второй раз: «иконки нижней панели всё ещё серые, я просил
   сделать их белоснежными».

   ⚠️ ОН ПРАВ, И Я СДЕЛАЛ ВПОЛОВИНУ. В round409 я поставил белый цвет,
   но приглушил его прозрачностью .78 — «чтобы активный отличался». На
   синем белый при .78 даёт #cfd1da. Это и есть серый. Проверять надо
   было получившийся цвет, а не написанный.

   ⚠️ И ГЛАВНОЕ — ЗНАЧКИ ВООБЩЕ НЕ СЛУШАЛИСЬ ЦВЕТА ССЫЛКИ. Выше по файлу
   стоит `body.theme-light svg{ color:var(--icon) }` — серый #4a525c. Он
   бьёт наследование от <a>, и значок оставался серым при любом цвете
   ссылки: контраст 1,7 при пороге 3,0, почти слился с фоном. Поэтому
   ниже цвет задан САМИМ svg, а не только ссылке.

   ⚠️ ЧЕМ ТЕПЕРЬ ОТЛИЧАЕТСЯ АКТИВНЫЙ РАЗДЕЛ. Раз белые все, ни цветом,
   ни яркостью различать нельзя. Берём подложку: у активного значка —
   светлая плашка, как в приложениях. Это заметнее прозрачности и не
   портит белизну. */
body.theme-light .bottom-nav a,
body.theme-light .bottom-nav button,
body.theme-light .bottom-nav a svg,
body.theme-light .bottom-nav button svg{
  color:#ffffff;
  opacity:1;
}
/* Плашка под значком активного раздела. Рисуем на ::before, чтобы не
   трогать разметку: подпись и значок остаются как есть. */
body.theme-light .bottom-nav a.active::before,
body.theme-light .bottom-nav .is-active::before{
  content:'';
  position:absolute;
  top:4px;
  width:44px;height:26px;
  border-radius:999px;
  background:rgba(255,255,255,.20);
}
body.theme-light .bottom-nav a.active .bn-txt{ font-weight:700 }
/* ⚠️ ТЕКУЩИЙ РАЗДЕЛ БЕЛЫМ, А НЕ ЗОЛОТЫМ (round331). Кирилл: «нынешняя
   страница подсвечивается золотым, поменяй чтобы светилась белым».

   По правилу проекта золото означает действие. Отметка «ты здесь» —
   не действие, а положение: нажимать на неё незачем, ты уже на этой
   странице. Белый выделяет ровно так же (остальные пункты приглушены),
   но не спорит с золотыми кнопками на самом экране. */
.bn-item.active{color:var(--text)}
.bn-item.active svg{filter:drop-shadow(0 0 5px rgba(255,255,255,.35))}
.bn-item:active{opacity:.6}
/* отступ снизу чтобы меню не перекрывало контент */
body{padding-bottom:20px}
body.dash-page{padding-bottom:20px}

/* ── Телефонный ввод с кодом страны ───────────────────────── */
.phone-wrap{display:flex;gap:0;border:1.5px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface-2);transition:var(--dur-fast)}
.phone-wrap:focus-within{border-color:var(--primary);box-shadow:0 0 0 3px rgba(176,183,191,.18)}
.phone-code{padding:.82rem .6rem;background:transparent;border:none;border-right:1px solid var(--border);color:var(--text);font-size:var(--fs-md);font-family:inherit;cursor:pointer;outline:none;flex-shrink:0;max-width:120px}
.phone-num{border:none !important;box-shadow:none !important;border-radius:0 !important;background:transparent !important;flex:1}
.phone-num:focus{outline:none;box-shadow:none !important}

/* ══ ТИПОГРАФИКА: Oswald для заголовков (брутальный, сжатый) ══
   Только GPU-безопасные свойства. Без backdrop-filter.
   Системный шрифт для body — быстро и надёжно на мобилках.    */
.card-title,
.modal-title,
.logo-title,
.hero-nm,
.lb-title,
.card-name {
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
/* Заглавными — только там где это не личное имя пользователя */
.card-title,
.modal-title,
.logo-title,
.lb-title,
.card-name {
  text-transform: uppercase;
  letter-spacing: .3px;
}

/* ══ ПРОСТРАНСТВО: чуть больше воздуха — учтено в .card/.card-title выше ══ */

/* ══ КНОПКА «ОТКРЫТЬ СЕЙФ» ════════════════════════════════════ */
/* ══ ИНСТРУКЦИЯ ПО СЕЙФУ ПОСЛЕ ОПЛАТЫ (round214) ══════════════════

   Пять шагов с фотографиями. Показывается сразу после оплаты, до
   того как человек поедет за прицепом.

   ГЛАВНОЕ В ЭТИХ СТИЛЯХ — ОКНО НЕ ДОЛЖНО ПРЫГАТЬ при переключении
   шагов. Тексты у шагов разной длины, и без фиксированной высоты
   кнопки «Дальше» скакали бы вверх-вниз: человек целится пальцем, а
   кнопка уехала.

   Поэтому у картинки постоянное соотношение сторон, а у текста —
   минимальная высота по самому длинному шагу. */

/* РАМА МЯГЧЕ (round217).

   Кирилл: «багетную раму сделай менее заметной, чтобы она аккуратно
   сглаживала контур, а не жёстко его выделяла».

   Согласен. Прошлая версия была толщиной 3 пикселя с полным
   градиентом от почти белого до тёмно-коричневого — на тёмном фоне
   такая полоса кричит и перетягивает внимание с содержимого.
   Получалось, что рама важнее фотографии внутри.

   Стало: полтора пикселя, приглушённое золото без резких переходов.
   Контур читается, край сглажен, но глаз идёт к снимку, а не к
   обводке.

   Тонкую тёмную линию внутри оставил: без неё рама сливается с
   фоном окна и выглядит просто цветной обводкой. */
/* ⚠️ ЗОЛОТАЯ ГРАДИЕНТНАЯ ОБВОДКА УБРАНА. Она делалась двумя слоями
   фона (padding-box + border-box) и давала окну вид парадной рамки —
   отталкивает там, где человек просто хочет прочитать инструкцию.
   Обычная тонкая рамка темы. */
/* ⚠️ КРЕСТИК ИНСТРУКЦИИ (round396). Без круглой подложки — она бы
   читалась как отдельная кнопка-объект, хотя это служебное действие.

   ⚠️ 36 ПИКСЕЛЕЙ ОБЛАСТИ: знак мелкий, но палец должен попадать. */
.guide-close{
  /* ⚠️ 44 — принятый минимум для пальца (round425). Было 36. */
  position:absolute;
  top:.6rem; right:.6rem;
  width:44px; height:44px;
  display:flex; align-items:center; justify-content:center;
  background:none; border:none;
  color:var(--text-muted);
  font-size:var(--fs-md);
  line-height:1;
  cursor:pointer;
}
.guide-close:active{ color:var(--text) }
/* ⚠️ КРЕСТИК ОКНА ИНСТРУКЦИИ (round396).

   Без подложки и рамки — как в карточке на карте: голый знак понятен
   сам по себе.

   ⚠️ ОБЛАСТЬ НАЖАТИЯ 40 ПИКСЕЛЕЙ, хотя сам знак мелкий. Палец должен
   попадать уверенно: промах закроет не окно, а нажмёт то, что под ним. */
.guide-close{
  /* ⚠️ ОБЛАСТЬ НАЖАТИЯ 44 — ПРИНЯТЫЙ МИНИМУМ ДЛЯ ПАЛЬЦА (round425).
     На меньшей промахиваются, а промах по крестику НА КАРТЕ означает
     нажатие по самой карте: она сдвинется, и человек решит, что закрыть
     нельзя. Растёт область, а не значок. */
  position:absolute;
  top:.6rem; right:.7rem;
  width:44px; height:44px;
  display:flex; align-items:center; justify-content:center;
  background:none; border:none;
  color:var(--text-muted);
  font-size:var(--fs-md);
  cursor:pointer;
  line-height:1;
}
.guide-close:active{ color:var(--text) }
/* Окно должно быть точкой отсчёта, иначе крестик уедет к краю экрана. */


.guide-modal{
  max-width:440px; text-align:left;
  position:relative;
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  background:var(--surface);
  box-shadow:0 16px 40px rgba(0,0,0,.5);
}

.guide-sub{
  font-size:var(--fs-sm); color:var(--text-muted);
  line-height:1.45; margin-bottom:.9rem;
}

/* ⚠️ НОМЕР ШАГА БЕЛЫЙ (round329). Кирилл: «текст "шаг какой-то из 5"
   сделай белым». Золотом он спорил с самой заметной вещью в окне —
   кнопкой «Дальше», а сообщает всего лишь, где ты в списке. */
.guide-step-num{
  font-size:var(--fs-xs); font-weight:700; letter-spacing:.5px;
  text-transform:uppercase; color:var(--text);
  margin-bottom:.5rem;
}

.guide-img{
  width:100%;
  /* Соотношение сторон снимков — постоянное, поэтому высота не
     скачет при переключении даже до загрузки картинки. */
  aspect-ratio:16/9;
  object-fit:cover;
  border-radius:var(--radius-md);
  background:var(--surface-2);
  display:block;
}

.guide-title{
  font-size:var(--fs-base); font-weight:700;
  color:var(--text); margin:.8rem 0 .35rem;
  line-height:1.3;
}
.guide-text{
  font-size:var(--fs-sm); color:var(--text-muted);
  line-height:1.55;
  /* ВЫСОТА ПО САМОМУ ДЛИННОМУ ШАГУ.

     Замерил после первой правки: кнопки всё ещё прыгали на 8
     пикселей между шагами — 4.6em не хватало, самый длинный текст
     занимал четыре строки на узком экране, остальные три.

     Пять строк с запасом. Пустое место под коротким текстом лучше,
     чем кнопка, которая уезжает из-под пальца в момент нажатия. */
  /* ВЫСОТА В ПИКСЕЛЯХ, А НЕ В em.

     Замерил дважды. Первая попытка (4.6em) давала разброс 8 пикселей,
     вторая (5.4em) — 2. Дело оказалось не в запасе: em считается от
     размера шрифта и даёт дробное значение, которое браузер округляет
     то вверх, то вниз в зависимости от того, сколько строк реально
     занял текст.

     Точное число в пикселях убирает округление совсем. Кнопки стоят
     намертво, и палец не промахнётся. */
  min-height:84px;
}

.guide-dots{
  display:flex; justify-content:center; gap:.4rem;
  /* Прижаты к фотографии сверху — они про неё, а не про кнопки. */
  margin:.6rem 0 .2rem;
}
.guide-dot{
  width:7px; height:7px; border-radius:50%;
  background:var(--border);
  transition:background var(--dur), transform var(--dur);
}
.guide-dot.active{
  background:var(--primary);
  transform:scale(1.4);
}

.guide-nav{ display:flex; gap:.6rem }
.guide-nav .btn{ flex:1 }

@media (max-width:400px){
  .guide-title{ font-size:var(--fs-base) }
  .guide-text{ font-size:var(--fs-sm); min-height:92px }
}

/* ══ ПАНЕЛЬ УПРАВЛЕНИЯ СЕЙФОМ ════════════════════════════════════

   СИММЕТРИЯ И ОТСТУПЫ (round210).

   Кирилл заметил: отступы несимметричны. Так и было — блоки внутри
   панели набирались по месту, у каждого свои значения: где .75rem,
   где .9rem, где 1rem. Глаз это ловит, даже когда не может назвать
   причину: строки не выстраиваются по одной линии.

   Здесь всё сведено к ОДНОМУ шагу: внутренний отступ блока .85rem,
   расстояние между блоками .7rem. Больше нигде в панели чисел
   вручную не ставим — иначе через месяц всё разъедется снова.

   ЦЕНА БЕЛЫМ, А НЕ ЗОЛОТЫМ. Золотой на этой странице означает
   «действие»: им подсвечены кнопка открытия и рамка панели. Цена
   действием не является, а притягивала взгляд наравне с кнопкой. */

:root{
  --safe-pad: .85rem;
  --safe-gap: .7rem;
}

/* Ссылка «как управлять?» в заголовке панели.

   Серая и мелкая намеренно: это подсказка, а не действие. Кнопка
   открытия рядом должна оставаться единственным заметным элементом —
   человек пришёл открыть сейф, а не читать. */
.safe-howto{
  background:none; border:none; padding:0;
  font-family:inherit; font-size:var(--fs-xs); font-weight:700;
  color:var(--text-muted);
  text-decoration:underline; text-underline-offset:2px;
  cursor:pointer; white-space:nowrap;
  transition:color var(--dur-fast);
}
.safe-howto:hover{ color:var(--primary) }
.safe-howto:active{ opacity:.7 }

.safe-total{
  background:var(--surface-2);
  border-radius:var(--radius-md);
  padding:var(--safe-pad);
  margin-bottom:var(--safe-gap);
  display:flex; justify-content:space-between; align-items:center;
  gap:.6rem;
}
.safe-total-label{
  font-size:var(--fs-xs); color:var(--text-muted);
  font-weight:700; text-transform:uppercase; letter-spacing:.4px;
}
.safe-total-value{
  font-weight:700; font-size:var(--fs-md);
  color:var(--text);          /* БЕЛЫЙ, не золотой */
  white-space:nowrap;
}

/* ── Состояние сейфа: связь и сигнал ───────────────────────────── */
.safe-state{
  background:var(--surface-2);
  border-radius:var(--radius-md);
  padding:var(--safe-pad);
  margin-bottom:var(--safe-gap);
  display:flex; flex-direction:column; gap:.5rem;
}
.safe-state-row{
  display:flex; justify-content:space-between; align-items:center;
  gap:.6rem;
}
.safe-state-label{
  font-size:var(--fs-xs); color:var(--text-muted);
  font-weight:700; text-transform:uppercase; letter-spacing:.4px;
}
.safe-state-id{
  font-family:var(--font-mono, monospace);
  font-weight:700; font-size:var(--fs-base);
  letter-spacing:.5px;
  color:var(--text);
}
.safe-state-val{
  display:flex; align-items:center; gap:.45rem;
  font-weight:700; font-size:var(--fs-sm);
  color:var(--text);
}
/* ══ ИСТОРИЯ АРЕНД КАК ЧЕК (round232) ════════════════════════════

   Кирилл обсуждал внимание к деталям: госномер мы сделали настоящей
   табличкой, и это сработало не как украшение, а потому что повторяет
   предмет, который человек держит перед глазами.

   Записи в истории — по сути ПЛАТЁЖНЫЕ ДОКУМЕНТЫ: дата, за что,
   сколько. Вид чека узнаётся мгновенно и говорит «это про деньги»
   раньше, чем человек прочтёт хоть слово.

   ЧТО ДЕЛАЕТ ЧЕК ЧЕКОМ, и что взято:

     • ЗУБЧАТЫЙ КРАЙ снизу — след отрыва от рулона. Это самая
       узнаваемая примета, без неё чек выглядит просто карточкой;

     • ПУНКТИРНАЯ ЛИНИЯ перед итогом — так на кассовых чеках отделяют
       сумму от перечня;

     • МОНОШИРИННЫЕ ЦИФРЫ — в кассовых аппаратах шрифт всегда такой,
       и суммы выстраиваются в столбик сами;

     • СУММА КРУПНЕЕ остального — на чеке глаз ищет её первой.

   ⚠️ ЧЕГО НЕ ДЕЛАЮ И ПОЧЕМУ. Не крашу в белый «как бумагу»: у нас
   тёмная тема, белый прямоугольник резал бы глаз на каждой строке
   списка. Берём форму чека, а не цвет бумаги — узнаваемость даёт
   именно форма.

   ⚠️ И ГЛАВНОЕ: табличка госномера остаётся как была. Строить вид
   чека ПОВЕРХ неё значило бы смешать два приёма в одном блоке — стало
   бы пестро. Чек здесь рамка, табличка внутри. */

.receipt{
  position:relative;
  /* Бумага — тёплый оттенок, а не чистый белый: он мягче на тёмном
     фоне и ближе к настоящему кассовому чеку, который белоснежным
     не бывает. */
  background:#f4f1ea;
  color:#1a1c1f;
  padding:1rem .95rem 1.05rem;
  margin:6px 0 1.2rem;
  box-shadow:0 4px 14px rgba(0,0,0,.35);
  /* Углы прямые: у чека их нет, он оторван по прямой. */
  border-radius:0;
}

/* ══ ТЕКУЩАЯ АРЕНДА — ОДНА СТРОКА (round237) ═════════════════════

   У незакрытой аренды нет ни окончательного итога (продление и
   просрочка его изменят), ни повода для отзыва — она ещё идёт.

   ⚠️ В round236 я сделал это ПОЛОВИНЧАТО: менял только класс, а
   чековые строки и кнопку отзыва оставлял. Получился «чек без
   дизайна» — Кирилл прислал снимок.

   Теперь здесь просто строка: что взял и когда. Всё остальное появится
   в чеке, когда аренда закроется. */
.rental-row{
  display:flex; align-items:center; justify-content:space-between;
  gap:.7rem;
  background:var(--surface-2);
  border-radius:var(--radius-md);
  padding:.75rem .9rem;
  margin-bottom:.7rem;
}
.rr-main{ min-width:0 }
.rr-title{
  font-weight:700; font-size:var(--fs-sm); color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.rr-meta{
  font-size:var(--fs-sm); color:var(--text-muted); margin-top:.15rem;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* Метка «идёт» — спокойная, не зовущая нажать: это состояние, а не
   действие. */
.rr-badge{
  flex-shrink:0;
  font-size:var(--fs-xs); font-weight:700; text-transform:uppercase;
  letter-spacing:.5px;
  color:var(--primary);
  background:rgba(198,203,209,.12);
  border:1px solid rgba(198,203,209,.28);
  border-radius:var(--radius-xl);
  padding:.25rem .6rem;
}

/* Идентификатор сейфа, когда госномера нет (старые записи). Обычным
   текстом: табличкой рисуем только настоящий номер. */
.rc-plate-plain{
  font-family:var(--font-mono, ui-monospace, Menlo, Consolas, monospace);
  font-weight:700; letter-spacing:.04em;
}

/* ══ РВАНЫЕ КРАЯ СВЕРХУ И СНИЗУ (round233) ═══════════════════════

   Кирилл: «хочу ещё чтобы верх и низ были порваны как в реальном
   магазине».

   У настоящего чека оторваны ОБА конца — его отрывают от рулона
   сверху и снизу. Это самая узнаваемая примета: по одному только
   краю чек опознаётся раньше, чем прочитан хоть один символ.

   КАК СДЕЛАНО. Зубцы рисуем градиентом из полукругов, а не
   картинкой: лишний запрос к серверу ради полоски в шесть пикселей
   не нужен, и цвет бумаги правится в одном месте.

   ⚠️ ВЕРХНИЙ И НИЖНИЙ КРАЙ СМЕЩЕНЫ ДРУГ ОТНОСИТЕЛЬНО ДРУГА на
   половину зубца. У настоящего чека отрывы никогда не совпадают —
   ровные одинаковые зубцы сверху и снизу выглядели бы штампованными,
   как декоративная рамка, а не как разрыв бумаги. */
.receipt::before,
.receipt::after{
  content:'';
  position:absolute; left:0; right:0;
  height:6px;
  background-size:12px 12px;
  background-repeat:repeat-x;
}
.receipt::before{
  top:-6px;
  /* Полукруги вырезают бумагу сверху: заливка идёт снизу зубца. */
  background-image:radial-gradient(circle at 6px 0, transparent 6px, #f4f1ea 6px);
  background-position:0 0;
}
.receipt::after{
  bottom:-6px;
  background-image:radial-gradient(circle at 6px 6px, transparent 6px, #f4f1ea 6px);
  /* Смещение на половину зубца — чтобы верх и низ не были близнецами. */
  background-position:6px 0;
}

/* ── ШАПКА ЧЕКА ─────────────────────────────────────────────────
   Что за прицеп и его номер, по центру — как реквизиты в верху
   документа. */
.rc-head{ text-align:center; margin-bottom:.75rem }
.rc-title{
  font-weight:700; font-size:var(--fs-base);
  letter-spacing:.02em;
  margin-bottom:.4rem;
}
.rc-plate{ display:flex; justify-content:center }

/* ── СТРОКИ С ТОЧКАМИ ───────────────────────────────────────────

   Точки от названия к значению — примета чека и разом решение
   задачи: глаз ведёт от слова к цифре, не теряя строку.

   Рисуются самой строкой, а не набиты вручную: при любой ширине
   экрана дотянутся ровно до значения. */
.rc-line{
  display:flex; align-items:baseline;
  font-size:var(--fs-sm);
  margin-bottom:.22rem;
}
.rc-key{ color:#6b6f76; white-space:nowrap }
.rc-val{
  color:#1a1c1f; font-weight:700; white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.rc-dots{
  flex:1;
  margin:0 .35rem;
  border-bottom:1px dotted rgba(0,0,0,.3);
  transform:translateY(-.18em);
}

/* Просрочка — красным даже на бумаге: это единственная строка, где
   человек мог не ожидать списания. Оттенок тёмный, под бумагу: наш
   яркий красный на светлом фоне резал бы глаз. */
.rc-over{ color:#b8241c !important }

/* Разделитель перед итогом — пунктиром, как на кассовом чеке. */
.rc-sep{
  border-top:1px dashed rgba(0,0,0,.28);
  margin:.6rem 0 .5rem;
}

/* ── ИТОГ ───────────────────────────────────────────────────────
   Крупнее остального: на чеке глаз ищет сумму первой. */
.rc-total{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:.6rem;
  margin-bottom:.85rem;
}
.rc-total-label{
  font-size:var(--fs-xs); text-transform:uppercase; letter-spacing:.6px;
  color:#6b6f76; font-weight:700;
}
.rc-total-sum{
  font-family:var(--font-mono, ui-monospace, Menlo, Consolas, monospace);
  font-variant-numeric:tabular-nums;
  font-size:var(--fs-md); font-weight:700;
  color:#1a1c1f;
}

/* ── ДЕЙСТВИЕ ВНИЗУ ─────────────────────────────────────────────

   ⚠️ ЗДЕСЬ И БЫЛА ГЛАВНАЯ БЕДА ПРЕЖНЕГО ВИДА. Кнопка стояла СБОКУ,
   в одной строке с содержимым: ей доставалась почти половина ширины
   под один элемент, а чек ужимался в левый столбец.

   Внизу во всю ширину она читается как строка подписи на бланке —
   и пустоты не остаётся. */
.rc-action{ display:flex }
.rc-action .btn{ flex:1; justify-content:center }
.rc-note{
  flex:1; text-align:center;
  font-size:var(--fs-sm); font-weight:700;
  color:#6b6f76;
  padding:.4rem 0;
}
/* ⚠️ «ОТЗЫВ ОПУБЛИКОВАН» — ЧЁРНЫМ, ШРИФТОМ ЧЕКА.
   Было color:#0d7a3c — зелёный. На бумажном бланке зелёный текст
   выглядит вклейкой из другого места: чек весь чёрный по тёплой
   бумаге, и цветная строка ломает вид. Смысл она несёт тот же —
   состояние, а не действие, — и цветом его подчёркивать не надо.
   Тон #1a1c1f — тот самый, что у .rc-val и итога чека, чтобы это был
   ОДИН цвет, а не похожий. Начертание тоже чековое: те же .8rem и
   табличные цифры, что в .rc-line.
   is-bad остаётся красным: отклонённый отзыв — это то, на что человек
   должен обратить внимание и переписать. */
.rc-note.is-ok{
  color:#1a1c1f;
  font-size:var(--fs-sm);
  letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
}
.rc-note.is-bad{ color:#b8241c }

/* ══ КНОПКА НА ЧЕКЕ (round232) ═══════════════════════════════════

   Кирилл: «проверь, чтобы кнопка оставить отзыв на чеке была
   лаконична, а не просто тупо вставлена».

   ЧТО БЫЛО НЕ ТАК. На чеке стояла наша главная золотая кнопка — с
   заливкой и бликом. Она рассчитана на ТЁМНЫЙ фон, там золото
   светится. На бумаге получилось наоборот: два ярких пятна рядом,
   которые спорят друг с другом.

   И по смыслу тоже мимо: отзыв — НЕ главное действие. Человек открыл
   историю посмотреть свои аренды, а не оставлять отзыв. Кнопка не
   должна перекрикивать сам чек.

   КАК СДЕЛАНО. На бумажном документе действие обозначают не
   заливкой, а рамкой — как поле для подписи или штампа. Тонкий
   контур, тёмный текст, тот же моноширинный шрифт, что у сумм.

   Заметно ровно настолько, чтобы найти и нажать. При наведении
   темнеет — видно, что это кнопка, а не рамка.

   ⚠️ ПРАВИЛО ДЕЙСТВУЕТ ТОЛЬКО ВНУТРИ ЧЕКА. На тёмном фоне золотая
   кнопка остаётся золотой: там она к месту. */
.receipt .btn{
  background:transparent !important;
  background-image:none !important;
  border:1.5px solid rgba(0,0,0,.35) !important;
  color:#1a1c1f !important;
  box-shadow:none !important;
  text-shadow:none !important;
  font-family:var(--font-mono, ui-monospace, Menlo, Consolas, monospace);
  font-size:var(--fs-sm) !important;
  font-weight:700;
  letter-spacing:.02em;
  padding:.4rem .8rem !important;
  border-radius:var(--radius-sm) !important;
  white-space:nowrap;
}
.receipt .btn:hover{
  background:rgba(0,0,0,.06) !important;
  border-color:rgba(0,0,0,.55) !important;
}
.receipt .btn:active{ transform:scale(.97) }

/* Подписи о состоянии отзыва — тоже под бумагу.

   Они приходят с цветами для тёмной темы: на бумаге светло-серый
   текст был бы почти не виден. */
.receipt .muted-note,
.receipt span[style*="color:var(--text-muted)"]{
  color:#6b6f76 !important;
}

/* Добавка от продления в блоке тарифа (round240).

   Золотом и рядом с основой: человек видит, что дни ДОБАВЛЕНЫ к его
   аренде, а не что тариф стал другим. */
.tariff-ext{
  display:inline-block;
  margin-left:.4rem;
  font-size:var(--fs-sm); font-weight:700;
  /* ⚠️ ЗОЛОТО УБРАНО (round323). Кирилл: «когда клиент продлевает
     тариф, в панели управления текст +5 дней золотого стиля — убери
     его, пусть продление будет такого же белого, как и сам тариф».

     Он прав и по правилу проекта: золото — цвет кнопки действия.
     Продление ничего не предлагает нажать, это часть значения «срок
     аренды»: «1 сутки +5 дней» — одна мысль, и разными цветами она
     читается как две. Плашку тоже убираем: рамка вокруг добавки
     делала из неё отдельную сущность. */
  color:var(--text);
  background:none;
  border:none;
  padding:0;
  vertical-align:middle;
}

/* ══ ОГОНЁК СЕЙФА — КАК НАСТОЯЩИЙ (round232) ═════════════════════

   Кирилл: «светодиод загорается в сейфе, когда прицеп подключают к
   машине, в этом вся суть — чтобы не использовать аккумулятор, мы
   питаем сейф от машины».

   На его фотографиях в инструкции светодиод даёт ЯРКОЕ ПЯТНО с
   ореолом вокруг — свет отражается от корпуса и стола. В панели то
   же состояние показывала точка 8 пикселей без свечения. Тот же
   смысл, но не тот же предмет.

   ЗАЧЕМ ПОВТОРЯТЬ ИМЕННО ВИД. Человек стоит у прицепа и смотрит на
   железный сейф: горит? Потом смотрит в телефон. Одинаковый вид
   позволяет сверить за долю секунды, без чтения.

   Как собран настоящий вид:
     1. ядро — маленькое и почти белое в середине;
     2. ореол — цветное свечение вокруг, оно и делает «лампочку»;
     3. отсвет снизу — как на фото, где свет ложится на поверхность;
     4. лёгкое дыхание — живой огонёк чуть мерцает, ровный кажется
        нарисованным.

   ⚠️ ПОГАШЕННЫЙ ДОЛЖЕН ВЫГЛЯДЕТЬ ПОГАШЕННЫМ, а не «красным огоньком».
   Красный светодиод значил бы «горит красным» — а он не горит вовсе.
   Поэтому серый и матовый, без свечения. Красным остаётся только
   подпись рядом. */

.safe-led{
  position:relative;
  width:12px; height:12px;
  border-radius:50%;
  flex-shrink:0;
  display:inline-block;
}

/* ГОРИТ: прицеп подключён к машине */
.safe-led.is-on{
  background:radial-gradient(circle at 38% 34%,
             #eafff2 0%, #6bff9f 26%, #22e06b 55%, #0d8f42 100%);
  box-shadow:
    0 0 5px  rgba(34,224,107,.95),
    0 0 12px rgba(34,224,107,.55),
    0 0 22px rgba(34,224,107,.25),
    0 2px 6px rgba(34,224,107,.35);
  animation:ledBreathe 2.6s ease-in-out infinite;
}
@keyframes ledBreathe{
  0%,100%{ filter:brightness(1) }
  50%    { filter:brightness(1.18) }
}

/* НЕ ГОРИТ: прицеп не подключён. Матовый, без свечения. */
.safe-led.is-off{
  background:radial-gradient(circle at 38% 34%,
             #4a4d52 0%, #34373b 55%, #232528 100%);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6);
}

/* Подсказка под строкой состояния. Появляется только когда прицеп
   молчит — при рабочем она была бы шумом. */
.safe-hint{
  margin-top:.5rem;
  font-size:var(--fs-sm); line-height:1.5;
  color:var(--text-muted);
  background:var(--surface-2);
  border-radius:var(--radius-sm);
  padding:.6rem .75rem;
}

.safe-dot{
  width:8px; height:8px; border-radius:50%;
  flex-shrink:0;
}
.safe-state-val.is-online   .safe-dot{
  background:#22e06b;
  box-shadow:0 0 8px rgba(34,224,107,.8);
  /* Мягкое дыхание: показывает, что связь ЖИВАЯ, а не подпись,
     нарисованная один раз при загрузке страницы. */
  animation:safeDotPulse 2.2s ease-in-out infinite;
}
.safe-state-val.is-online   { color:#22e06b }
.safe-state-val.is-offline  .safe-dot{ background:var(--danger) }
.safe-state-val.is-offline  { color:var(--danger) }
@keyframes safeDotPulse{
  0%,100%{ opacity:1 }
  50%    { opacity:.45 }
}

/* Полоски сигнала — как в телефоне, понятны без подписи */
.sig-bars{
  display:inline-flex; align-items:flex-end; gap:2px;
  height:14px;
}
.sig-bars i{
  width:3px; border-radius:var(--radius-sm);
  background:var(--border);
  display:block;
}
.sig-bars i:nth-child(1){ height:5px }
.sig-bars i:nth-child(2){ height:8px }
.sig-bars i:nth-child(3){ height:11px }
.sig-bars i:nth-child(4){ height:14px }
.sig-bars[data-level="1"] i:nth-child(-n+1),
.sig-bars[data-level="2"] i:nth-child(-n+2),
.sig-bars[data-level="3"] i:nth-child(-n+3),
.sig-bars[data-level="4"] i:nth-child(-n+4){ background:#22e06b }
/* Одна полоска — цвет тревожный: связь на грани, стоит знать */
.sig-bars[data-level="1"] i:nth-child(-n+1){ background:var(--danger) }
.sig-bars[data-level="2"] i:nth-child(-n+2){ background:#c6cbd1 }
.sig-text{ font-size:var(--fs-sm); color:var(--text-muted); font-weight:600 }

/* ── Мини-карта с прицепом ─────────────────────────────────────── */
/* Строка состояния под кнопками. Пустая — не занимает места:
   раньше она держала высоту всегда и раздувала зазор до «Продлить
   аренду» вдвое. */
.safe-status-line{
  text-align:center; font-size:var(--fs-sm); color:var(--text-muted);
  margin-top:.5rem;
}
.safe-status-line:empty{ margin:0; height:0; overflow:hidden }

.safe-map-wrap{ margin-bottom:var(--safe-gap) }
.safe-mini-map{
  /* ⚠️ ВЫШЕ, ЧЕМ БЫЛО (round328). Кирилл: «карта маленькая, делай
     больше, клиент хочет видеть свой прицеп — так дадим ему это».

     На 170 пикселях в кадр попадал двор и половина соседнего дома:
     чтобы понять, у какого подъезда стоит прицеп, приходилось
     разводить пальцами. 260 — это примерно квартал на телефоне, то
     есть ровно тот масштаб, на котором ориентируются пешком. Выше
     делать нельзя: карта вытеснит кнопку «Открыть» за нижний край,
     а за ней сюда и приходят. */
  width:100%; height:260px;
  border-radius:var(--radius-md);
  background:var(--surface-2);
  overflow:hidden;
  /* Карта не должна перехватывать прокрутку страницы: человек
     листает раздел пальцем, и если карта ловит жест, страница
     застревает. Приближение — кнопками на самой карте. */
  touch-action:pan-y;
}
/* Пульсация своей метки на мини-карте. Не украшение: на карте с
   синими зонами глаз должен найти прицеп сразу, без поиска. */
@keyframes safeMineBeat{
  0%,100%{ box-shadow:0 0 0 0 rgba(215,219,224,.7), 0 2px 6px rgba(0,0,0,.45) }
  50%    { box-shadow:0 0 0 10px rgba(215,219,224,0), 0 2px 6px rgba(0,0,0,.45) }
}

.safe-map-addr{
  margin-top:.4rem;
  font-size:var(--fs-sm); color:var(--text-muted);
  text-align:center;
}

/* ══ КНОПКИ СЧЁТЧИКА «+» И «−» (round220) ════════════════════════

   Кирилл: «кнопка + и − в продлении аренды дефолтного белого
   дизайна, надо сделать под наш стиль».

   ПРИЧИНА БЫЛА НЕ В ОТСУТСТВИИ СТИЛЯ. Он существовал — в
   static/css/dashboard.css. Но окно продления живёт на странице
   СЕЙФА, где dashboard.css не подключён: там свои стили.

   Получилось, что в каталоге те же кнопки выглядели правильно, а в
   разделе «Сейф» — как серые системные квадраты. Один класс, два
   разных вида в зависимости от страницы.

   Перенёс сюда, в common.css: он подключён на всех страницах, и
   кнопка теперь выглядит одинаково везде. В dashboard.css правило
   удалено, чтобы не было двух определений одного класса — они
   однажды разъедутся. */
.calc-btn{
  width:48px;height:48px;border-radius:50%;
  border:1.5px solid rgba(198,203,209,.45);
  background:rgba(198,203,209,.08);
  color:var(--primary);
  font-family:inherit;font-size:var(--fs-lg);font-weight:700;line-height:1;
  cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:background var(--dur-fast) ease,border-color var(--dur) ease,transform var(--dur) ease;
  -webkit-tap-highlight-color:transparent;
  flex-shrink:0;
}
.calc-btn:hover{ background:rgba(198,203,209,.16); border-color:rgba(198,203,209,.7) }
.calc-btn:active{ transform:scale(.9); background:rgba(198,203,209,.24) }
.calc-btn:disabled{
  opacity:.4; cursor:not-allowed; transform:none;
  border-color:var(--border); color:var(--text-muted);
}

/* Красный текст на сером фоне: цвет и вес задаются вместе.

   По отдельности их разносить нельзя — оттенок держится на пределе
   нормы контраста, и без жирности читаться будет хуже. Класс
   гарантирует, что одно не появится без другого. */
.danger-text{
  color:var(--danger);
  font-weight:700;
}

/* ══ ГОСНОМЕР ПРИЦЕПА ════════════════════════════════════════════

   Идентификатор сейфа совпадает с госномером прицепа, поэтому
   показываем его как настоящую табличку. Человек сверяет то, что
   видит на прицепе, с тем, что на экране — одинаковое начертание
   узнаётся мгновенно.

   ── ПРО ШРИФТ: ЧЕСТНО О ТОМ, ЧТО ПОЛУЧИЛОСЬ (round219) ──

   Сначала я взял Oswald, потому что он уже подключён. ЭТО БЫЛА
   ОШИБКА: замерил пропорции цифр — у Oswald 0.45, то есть он УЗКИЙ,
   а на настоящих номерах символы почти квадратные, около 0.70-0.75.
   Направление было противоположным.

   Кирилл попросил проверить, нельзя ли загрузить настоящий шрифт
   ГОСТ. Проверил: в npm таких нет, в Google Fonts тоже, на GitHub
   нашёлся один подходящий — но БЕЗ УКАЗАННОЙ ЛИЦЕНЗИИ, и файл мне
   не открылся.

   Шрифт без лицензии на коммерческий сайт брать нельзя, а вставлять
   то, что я не смог даже проверить, — тем более. Поэтому делаем
   приближение, и делаем его хорошо.

   ЧТО СДЕЛАНО ВМЕСТО:
     • набор шрифтов с запасом на все системы, от широких к узким;
     • пропорции доводим растяжением по горизонтали (scaleX) — так
       результат перестаёт зависеть от того, какой шрифт нашёлся у
       человека: узкий растянется сильнее, широкий меньше;
     • тяжёлое начертание и минимальные межбуквенные просветы, как
       на настоящей табличке.

   Разница с настоящим номером заметна, только если положить рядом.

   ── ДВОЙНАЯ РАМКА ──

   Кирилл: «не понятно, что у белого фона есть чёрная обводка».

   Так и было: чёрная рамка на тёмном фоне сайта сливалась с ним, и
   табличка казалась просто белым прямоугольником.

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

.plate{
  display:inline-flex; align-items:stretch;
  background:#fff;
  border:2px solid #0d0d0d;
  border-radius:3px;
  overflow:hidden;
  line-height:1;
  vertical-align:middle;
  /* Светлый контур снаружи — им чёрная рамка отделяется от тёмного
     фона сайта. Тенью, а не второй рамкой: рамка добавила бы ширины
     и сбила бы пропорции таблички. */
  box-shadow:
    0 0 0 1px rgba(255,255,255,.55),
    0 2px 5px rgba(0,0,0,.5);
}

/* Шрифт: от широких к узким. Первый найденный и будет использован. */
.plate-main, .plate-code{
  font-family:'Arial Black', 'Arial Bold', 'DejaVu Sans', 'Liberation Sans',
              'Helvetica Neue', Arial, sans-serif;
  font-weight:700;
  color:#0d0d0d;
  font-variant-numeric:lining-nums tabular-nums;
}

.plate-main{
  font-size:var(--fs-sm);
  letter-spacing:.02em;
  padding:.26rem .42rem .24rem;
  display:flex; align-items:center;
  /* Растяжение по горизонтали доводит пропорции до номерных. Origin
     по центру, чтобы отступы остались симметричными. */
  transform:scaleX(1.12);
  transform-origin:center;
}
.plate-region{
  border-left:2px solid #0d0d0d;
  padding:.1rem .24rem .08rem;
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  min-width:1.95rem;
}
.plate-code{
  font-size:var(--fs-xs);
  letter-spacing:.01em;
  transform:scaleX(1.1);
}
.plate-rus{
  display:flex; align-items:center; gap:.11rem;
  color:#0d0d0d;
  font-family:Arial, sans-serif;
  font-size:var(--fs-xs); font-weight:700;
  letter-spacing:.04em;
  margin-top:.07rem;
}
.plate-flag{
  display:inline-flex; flex-direction:column;
  width:.4rem; height:.28rem;
  border:.5px solid #444;
}
.plate-flag i{ display:block; flex:1 }
.pf-w{ background:#fff }
.pf-b{ background:#0039A6 }
.pf-r{ background:#D52B1E }

/* Крупный вариант — панель управления сейфом, где номер это главная
   примета прицепа. */
.plate-md{ border-width:2.5px }
.plate-md .plate-main{ font-size:var(--fs-base); padding:.32rem .5rem .3rem }
.plate-md .plate-region{ min-width:2.4rem; padding:.14rem .3rem .1rem; border-left-width:2.5px }
.plate-md .plate-code{ font-size:var(--fs-sm) }
.plate-md .plate-rus{ font-size:var(--fs-xs) }
.plate-md .plate-flag{ width:.48rem; height:.34rem }

/* Идентификатор, не похожий на номер (SAFE_A и подобные): обычный
   моноширинный текст. Рисовать табличку из служебного идентификатора
   значило бы врать. */
.plate-plain{
  font-family:var(--font-mono, monospace);
  font-weight:700; letter-spacing:.5px;
  color:var(--text);
}

/* ══ ТРИ РОЛИ КНОПОК В РАЗДЕЛЕ «СЕЙФ» (round217) ═════════════════

   Кирилл: «4 кнопки на скрине и все разного стиля».

   Так и было. На одном экране стояли:
     • «Открыть»          — золотой слиток с бликом
     • «Завершить»        — тёмная с красной обводкой
     • «Продлить аренду»  — свой стиль ПРЯМО В РАЗМЕТКЕ, мимо системы
     • «Показать парковки»— обычная btn-outline

   Четыре разных вида на четыре действия. Глаз не понимает, что
   главное, а что второстепенное — всё выглядит одинаково важным и
   одновременно несвязанным.

   ТРИ РОЛИ, И БОЛЬШЕ НИКАКИХ:

     ГЛАВНОЕ ДЕЙСТВИЕ    золотой слиток, блик, пульсация
                         только «Открыть» — за него платят

     ВТОРОЕ ДЕЙСТВИЕ     тёмный фон, золотая рамка, золотой текст
                         «Продлить аренду», «Показать парковки»
                         видно, что кнопка, но глаз не задерживается

     ОПАСНОЕ ДЕЙСТВИЕ    тёмный фон, красная рамка, красный текст
                         «Завершить» — необратимо, цвет предупреждает

   Форма у всех одна: та же высота, те же углы, тот же отклик на
   нажатие. Различается ТОЛЬКО цвет, и он означает роль. */

.safe-btn{
  width:100%;
  padding:1.05rem .8rem;
  border-radius:var(--radius-sm);
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size:var(--fs-base); font-weight:700;
  letter-spacing:.4px;
  cursor:pointer;
  display:flex; align-items:center; justify-content:center; gap:.45rem;
  transition:background var(--dur-fast), border-color var(--dur), transform var(--dur), opacity var(--dur);
  background:var(--surface-2);
  border:1.5px solid rgba(198,203,209,.4);
  color:var(--primary);
}
.safe-btn:hover{
  background:rgba(198,203,209,.1);
  border-color:rgba(198,203,209,.6);
}
.safe-btn:active{ transform:scale(.97); opacity:.9 }
.safe-btn:disabled{
  opacity:.5; cursor:not-allowed;
  background:var(--surface-2);
  border-color:var(--border);
  color:var(--text-muted);
}

/* ══ ДВЕ ГЛАВНЫЕ КНОПКИ РАЗДЕЛА «СЕЙФ» ═══════════════════════════

   ИЕРАРХИЯ БЫЛА ПЕРЕВЁРНУТА (round202).

   «Завершить аренду» была ярко-красной с бегущим бликом, а
   «Открыть сейф» — просто золотой, без блеска вообще. Взгляд падал
   на завершение, хотя открытие человек делает каждый раз, а
   завершение — один раз в конце.

   Правило простое: чем чаще действие и чем оно желаннее, тем
   заметнее кнопка. Открытие — главное действие сервиса, за него
   платят. Завершение — служебное, его не надо продавать.

   Стало:
     ОТКРЫТЬ    — золотой слиток с бегущим бликом и мягкой
                  пульсацией. Самый заметный элемент экрана.
     ЗАВЕРШИТЬ  — сдержанная, тёмная с красной обводкой. Видно, что
                  она есть, но глаз на ней не задерживается.

   Обе стоят В ОДНУ СТРОКУ и подписаны одним словом — раньше они
   занимали два полных блока по высоте, а на телефоне это половина
   экрана ради двух нажатий. */

.safe-actions-row {
  display: flex;
  gap: .6rem;
  margin-top: .6rem;
}
.safe-actions-row > * { flex: 1; min-width: 0; }

.btn-open-safe {
  width: 100%;
  padding: 1.05rem .8rem;
  border: none; border-radius:var(--radius-sm);
  background: var(--metal-grad);
  /* Было #1a1305 — тёмно-коричневый из ЗОЛОТОЙ темы, которую сменило
     серебро, а серебро сменил фирменный синий (round425). */
  color: #ffffff;
  font-size:var(--fs-base); font-weight:700;
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: .4px;
  cursor: pointer;
  position: relative; overflow: hidden;
  text-shadow: 0 1px 0 rgba(255,255,255,.15);
  box-shadow: 0 0 0 0 rgba(176,183,191,.35), var(--metal-inset);
  animation: openBtnPulse 2.6s ease-in-out infinite;
  transition: transform var(--dur-fast), opacity var(--dur), filter var(--dur);
  display: flex; align-items: center; justify-content: center; gap: .45rem;
}
/* Бегущий блик — ТОТ САМЫЙ, что был у красной. Переехал сюда,
   потому что притягивать взгляд должно открытие.
   Анимируем transform, а не left: left пересчитывает раскладку на
   каждом кадре и заметно тормозит на слабых телефонах. */
.btn-open-safe::after {
  content: ''; position: absolute; top: 0; left: 0;
  width: 40%; height: 100%;
  background: linear-gradient(105deg, transparent 0%, rgba(255,255,255,.75) 50%, transparent 100%);
  pointer-events: none;
  transform: translateX(-200%) skewX(-18deg);
  animation: metalSweep 4.5s ease-in-out infinite;
  will-change: transform;
}
.btn-open-safe:hover  { filter: brightness(1.04); }
.btn-open-safe:active { transform: scale(.97); opacity: .9; }
.btn-open-safe.is-off,
.btn-open-safe:disabled {
  /* ⚠️ ЗОЛОТО ОБЕСЦВЕЧЕНО, А НЕ ПРОСТО ПРИГЛУШЕНО (round234).

     Кирилл: «как бы сделать её золото серовато прозрачно».

     Было opacity:.55 — золото просто бледнело, но оставалось
     золотом. На тёмном фоне такая кнопка всё равно читается как
     рабочая: человек нажимает, ничего не происходит, и он решает,
     что сломался сайт.

     Теперь золото ПОЛУВЫЦВЕТШЕЕ: убираем насыщенность фильтром,
     оставляя форму и блик. Кнопка узнаётся как та самая — но видно,
     что она сейчас не работает.

     Свечение и пульсация сняты: они зовут нажать, а нажимать
     нечего. */
  filter: grayscale(.72) brightness(.78);
  opacity: .62;
  /* Курсор обычный, а не «запрещено»: кнопка нажимается и отвечает
     подсказкой. Знак запрета говорил бы «не трогай», а мы как раз
     хотим, чтобы человек нажал и узнал причину. */
  cursor: pointer;
  animation: none;
  box-shadow: none;
  text-shadow: none;
}
.btn-open-safe.is-off::after,
.btn-open-safe:disabled::after { animation: none; opacity: 0; }
@keyframes openBtnPulse {
  /* ⚠️ ПУЛЬСАЦИЯ В ФИРМЕННОМ ТОНЕ (round425). Было серебряное
     rgba(176,183,191) с отблеском metal-inset — остаток серебряной
     темы round332 на кнопке, которую в round404 уже покрасили в
     фирменный синий. Кольцо вокруг синей кнопки светилось серым. */
  0%, 100% { box-shadow: 0 0 0 0 rgba(44,52,112,.28); }
  50%       { box-shadow: 0 0 0 6px rgba(44,52,112,0); }
}

/* ══ КРАСНЫЙ СЛИТОК — кнопка «Завершить аренду» ═══════════════
   Та же механика, что у золотой .btn-primary, но в красной палитре:
   многослойный градиент (светлый верх / тёмный низ даёт объём),
   внутренние тени вместо плоской заливки и бегущий блик.

   Блик анимируется ЧЕРЕЗ transform, а не left — это принципиально.
   Анимация left пересчитывает раскладку страницы на каждом кадре и
   заметно тормозит на слабых андроидах; transform считает видеокарта.
   На этом уже обжигались с золотыми кнопками, повторять не будем.

   Почему красная. Кнопка закрывает аренду — действие необратимое:
   после подтверждения админом сейф освобождается, вернуться нельзя.
   Такое действие не должно выглядеть так же, как «открыть сейф». */
.btn-finish-rental{
  /* ФОРМА ОБЩАЯ С safe-btn, ОТЛИЧАЕТСЯ ТОЛЬКО ЦВЕТОМ (round217).
     Красный означает необратимость: после подтверждения админом
     сейф освобождается, вернуться нельзя.

     СДЕРЖАННАЯ, А НЕ ЯРКАЯ (round202).

     Была красным «слитком» с бегущим бликом — ярче, чем кнопка
     открытия. Кирилл заметил верно: взгляд падал на завершение,
     хотя открывают сейф каждый раз, а завершают один раз в конце.

     Блик отсюда переехал на золотую. Здесь остался тёмный фон с
     красной обводкой: кнопку видно, назначение читается по цвету,
     но она не спорит с главным действием.

     Красный сохранён намеренно — действие необратимое: после
     подтверждения админом сейф освобождается, вернуться нельзя. */
  width: 100%;
  padding: 1.05rem .8rem;
  border-radius:var(--radius-sm);
  border: 1.5px solid rgba(252,129,129,.45);
  background: rgba(252,129,129,.08);
  color: var(--danger);
  font-size:var(--fs-base); font-weight:700;
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: .4px;
  cursor: pointer;
  position: relative;
  transition: background var(--dur-fast), border-color var(--dur), transform var(--dur), opacity var(--dur);
  display: flex; align-items: center; justify-content: center; gap: .45rem;
}
.btn-finish-rental:hover {
  background: rgba(252,129,129,.14);
  border-color: rgba(252,129,129,.65);
}
.btn-finish-rental:active { transform: scale(.97); opacity: .9; }
.btn-finish-rental:disabled {
  opacity: .5; cursor: not-allowed;
  background: rgba(255,255,255,.04);
  border-color: var(--border);
  color: var(--text-muted);
}

/* ══ АНИМАЦИЯ ЗАМКА ════════════════════════════════════════════ */
#lockOverlay {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(10,10,10,.88);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1rem;
  opacity: 0;
  /* fade-in при появлении */
  animation: lockFadeIn .25s ease forwards;
}
@keyframes lockFadeIn { to { opacity: 1; } }
#lockOverlay.hiding { animation: lockFadeOut .4s ease forwards; }
@keyframes lockFadeOut { to { opacity: 0; } }

.lock-svg-wrap { position: relative; }

/* Дужка замка поднимается вверх */
.lock-shackle {
  transform-origin: center bottom;
  animation: shackleUp .55s cubic-bezier(.34,1.56,.64,1) .3s forwards;
}
@keyframes shackleUp {
  0%   { transform: translateY(0); }
  100% { transform: translateY(-14px); }
}

/* Тело замка мягко покачивается */
.lock-body {
  animation: bodyWiggle .4s ease .85s forwards;
}
@keyframes bodyWiggle {
  0%,100% { transform: rotate(0deg); }
  25%     { transform: rotate(-3deg); }
  75%     { transform: rotate(3deg); }
}

/* Золотое свечение вокруг замка */
.lock-glow {
  position: absolute; inset: -20px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(176,183,191,.25) 0%, transparent 70%);
  opacity: 0;
  animation: glowAppear .5s ease .7s forwards;
}
@keyframes glowAppear { to { opacity: 1; } }

.lock-label {
  color: #D7DBE0;
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size:var(--fs-base); font-weight: 700;
  opacity: 0;
  animation: lockFadeIn .3s ease .6s forwards;
}
.lock-sub {
  color: rgba(176,183,191,.55);
  font-size:var(--fs-sm);
  opacity: 0;
  animation: lockFadeIn .3s ease .85s forwards;
}

/* ══ FADE-ПЕРЕХОД МЕЖДУ СТРАНИЦАМИ (лёгкий) ═══════════════════ */
/* Переход страниц через JS (см. TOAST_JS) — не CSS animation на body,
   чтобы не было зум-петли на мобилках. */
.page-wrap{flex:1;display:flex;flex-direction:column;width:100%}

/* Уважаем системную настройку «уменьшить движение» — полностью
   отключаем анимации для тех, кому они мешают или сажают батарею. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important;transition:none !important}
}

/* Компактная атрибуция Leaflet на ВСЕХ картах (пикер аренды, карта админа,
   карта парковок) — минимальный размер, допустимый по правилам OSM. */
.leaflet-control-attribution{
  font-size:var(--fs-xs) !important;
  opacity:.55 !important;
  background:rgba(15,15,15,.7) !important;
  color:#cfcabb !important;
  padding:0 4px !important;
}
.leaflet-control-attribution a{ color:#cfcabb !important; }

/* ══ ШРИФТ КНОПОК И ПОЛЕЙ ════════════════════════════════════════
   <button>, <input>, <select> и <textarea> по спецификации НЕ наследуют
   font-family от body — браузер подставляет системный шрифт. Из-за этого
   любое новое правило кнопки, где забыли font-family, вылезало чужим
   шрифтом (так случилось с кнопкой «Взять» на карте). Здесь это
   закрывается один раз для всего сайта, чтобы больше не повторялось. */
button, input, select, textarea, .btn, .btn-primary, .btn-outline{
  font-family:inherit;
}

/* ══ ССЫЛКА ОПАСНОГО ДЕЙСТВИЯ ════════════════════════════════════
   Для необратимых действий, которые нужны единицам (удаление аккаунта).
   Намеренно тише всего остального: не кнопка, без фона и рамки, мелким
   приглушённым текстом. Красный проявляется только при наведении и
   нажатии — до этого элемент не должен притягивать палец. */
.link-danger{
  background:none;border:none;padding:.1rem .2rem;
  font-family:inherit;font-size:var(--fs-sm);font-weight:600;
  color:var(--text-muted);opacity:.75;
  text-decoration:underline;text-decoration-color:rgba(255,255,255,.18);
  text-underline-offset:3px;cursor:pointer;
  transition:color var(--dur-fast), opacity var(--dur);
}
.link-danger:hover,.link-danger:focus-visible{
  color:var(--danger);opacity:1;text-decoration-color:rgba(252,129,129,.5);
}

/* Кнопка опасного, но осознанного действия внутри окна подтверждения:
   уже нажатая ссылка привела человека сюда, поэтому здесь кнопка обычного
   размера — но красная, а не золотая, чтобы не путалась с обычным «ок». */
.btn-danger-soft{
  background:rgba(252,129,129,.12);
  border:1px solid rgba(252,129,129,.5);
  color:var(--danger);font-weight:700;
}
.btn-danger-soft:hover{background:rgba(252,129,129,.2)}

/* ══ НАСТОЯЩИЙ ТЯЖЁЛЫЙ ВЕС ТАМ, ГДЕ ОН НУЖЕН (round274) ══════════

   ⚠️ 157 МЕСТ ПРОСИЛИ ВЕС, КОТОРОГО В ШРИФТЕ НЕТ.

   У Oswald максимальный вес — 700, а в проекте стояло font-weight:800
   (127 раз) и 900 (30 раз). Браузер такой вес рисует сам: раздувает
   контуры букв. Синтетический жир грубее настоящего и выглядит
   по-разному в Safari и Chrome — это и есть та «дешевизна», которую
   Кирилл описывал с самого начала и не мог назвать.

   ⚠️ MONTSERRAT ГРУЗИЛСЯ ВПУСТУЮ. base.html подключает его весами
   700;800;900 — и ни одного правила с ним в CSS не было. То есть мы
   тратили загрузку на шрифт, которым ничего не набрано.

   Теперь пара работает как задумано: Oswald для текста (до 700),
   Montserrat для крупного и тяжёлого. Класс применяется точечно — к
   заголовкам экранов и главным числам, а не ко всему подряд: если
   тяжёлым сделать всё, тяжёлым не будет ничего. */
.u-display{
  font-family:'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight:800;letter-spacing:-.01em;
}

/* Кнопка в инструкции — без золотого слитка: инструкция объясняет,
   а не зовёт к покупке. Тёмная с рамкой, читаемая. */
.guide-next{background:var(--surface-2);border-color:var(--border);color:var(--text);font-weight:600}
.guide-next:hover{border-color:var(--text-muted);color:var(--text)}

/* ══ ДОКУМЕНТ В МОДАЛЬНОМ ОКНЕ — БЕЛЫЙ ЛИСТ ═════════════════════════

   Юридический текст читают подряд и долго: светлый фон для этого
   привычнее, и документ выглядит документом, а не частью интерфейса.
   Цвета заданы явно, а не через переменные темы — те рассчитаны на
   тёмный фон и здесь дали бы нечитаемый текст. */
.legal-modal{
  max-width:min(680px, 94vw);
  max-height:86vh;
  background:#ffffff;
  color:#1a1a1a;
  padding:0;
  display:flex;flex-direction:column;
  position:relative;
  text-align:left;
}
.legal-close{
  /* ⚠️ 44 — принятый минимум для пальца (round425). Было 34. */
  position:absolute;top:12px;right:12px;z-index:2;
  width:44px;height:44px;border-radius:50%;
  background:rgba(0,0,0,.06);border:none;color:#555;
  font-size:var(--fs-md);line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.legal-close:hover{background:rgba(0,0,0,.12)}
.legal-title{
  font-family:Georgia,'Times New Roman',Tinos,'Noto Serif',serif;
  padding:22px 52px 14px 24px;
  font-size:var(--fs-md);font-weight:700;color:#1a1a1a;
  border-bottom:1px solid #e5e5e5;
  line-height:1.3;text-transform:none;letter-spacing:0;
}
.legal-body{
  padding:20px 24px 24px;
  overflow-y:auto;
  /* ⚠️ GEORGIA ТОЛЬКО В ДОКУМЕНТАХ (round330). Кирилл: «верни прошлый
     шрифт, он для сайта подходит лучше, но для содержимого оферты,
     политики и согласия оставь Georgia».

     Разница по делу: интерфейс читают взглядом — короткие подписи,
     цифры, кнопки, и рубленый Oswald для этого и сделан. Юридический
     текст читают ПОДРЯД, абзацами: засечки ведут глаз по строке и
     снижают усталость. Поэтому договоры набирают с засечками, а
     вывески — без. */
  font-family:Georgia,'Times New Roman',Tinos,'Noto Serif',serif;
  font-size:var(--fs-base);line-height:1.65;color:#1a1a1a;
  /* Переносы из базы сохраняем стилем, а не тегами — текст
     вставляется как текст (см. openLegal), разметки в нём нет. */
  white-space:pre-wrap;
  -webkit-overflow-scrolling:touch;
}

/* ══ ДОКУМЕНТ ОТДЕЛЬНОЙ СТРАНИЦЕЙ — ТОТ ЖЕ БЕЛЫЙ ЛИСТ (round321) ═════

   Кирилл: «сделай чтобы документы были не чёрные с белым текстом, а
   наоборот выглядели как офисные документы, белый лист с чёрным
   текстом».

   Модалка (.legal-modal) такой стала ещё в round316, а СТРАНИЦА
   /legal/<тип> осталась тёмной — то есть один и тот же документ
   выглядел по-разному в зависимости от того, как его открыли.

   ⚠️ САМУ СТРАНИЦУ НЕ УДАЛЯЮ, И ЭТО НЕ ЛЕНЬ. На неё ведут ссылки
   извне: поисковики, письма, договоры, требование держать оферту
   публично доступной. Удали её — эти ссылки станут «страница не
   найдена». В интерфейсе документы теперь открываются модалкой,
   страница остаётся запасным и внешним путём — и выглядит так же.

   Цвета заданы явно, а не переменными темы: те рассчитаны на тёмный
   фон и здесь дали бы серый текст на белом. */
.legal-page{max-width:820px;margin:0 auto;padding:1.2rem 1rem 3rem}
.legal-page-top{
  display:flex;align-items:center;gap:.6rem;margin-bottom:1rem;
}
.legal-back{
  display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:var(--radius-md);
  background:var(--surface-2);border:1px solid var(--border);
  color:var(--text);text-decoration:none;flex-shrink:0;
}
.legal-sheet{
  background:#ffffff;color:#1a1a1a;
  border-radius:var(--radius-md);
  padding:2.2rem 2.4rem 2.6rem;
  box-shadow:0 6px 28px rgba(0,0,0,.35);
  text-align:left;
}
@media (max-width:560px){ .legal-sheet{padding:1.4rem 1.2rem 1.8rem} }
.legal-sheet-title{
  font-family:Georgia,'Times New Roman',Tinos,'Noto Serif',serif;
  font-size:var(--fs-lg);font-weight:700;color:#1a1a1a;
  line-height:1.3;margin:0 0 .35rem;
}
.legal-sheet-meta{
  font-size:var(--fs-sm);color:#6b6b6b;
  padding-bottom:1rem;margin-bottom:1.2rem;
  border-bottom:1px solid #e5e5e5;
}
.legal-sheet-body{
  /* Переносы приходят из базы обычным текстом, разметки в нём нет. */
  white-space:pre-wrap;
  font-size:var(--fs-base);line-height:1.7;color:#1a1a1a;
  /* Georgia — как в модалке: один документ не должен выглядеть
     по-разному в зависимости от того, как его открыли (round330). */
  font-family:Georgia,'Times New Roman',Tinos,'Noto Serif',serif;
}
/* Предупреждение о тестовой редакции — на белом листе, поэтому свои
   цвета: янтарная плашка темы на нём не читалась бы. */
.legal-sheet-warn{
  background:#f2f4f6;border:1px solid #cfd4d9;color:#3f464e;
  border-radius:var(--radius-sm);padding:.75rem .95rem;margin-bottom:1.4rem;
  font-size:var(--fs-sm);line-height:1.5;
}
/* Список документов (индекс /legal) — карточки светлыми листами,
   чтобы переход на документ не менял язык оформления. */
.legal-index{display:flex;flex-direction:column;gap:.7rem}
.legal-index a{
  display:block;background:#ffffff;color:#1a1a1a;
  border-radius:var(--radius-md);padding:1rem 1.2rem;text-decoration:none;
  box-shadow:0 3px 14px rgba(0,0,0,.28);
}
.legal-index-name{font-weight:700;font-size:var(--fs-base)}
.legal-index-sub{font-size:var(--fs-sm);color:#6b6b6b;margin-top:.2rem}


/* ⚠️ РАМКИ ЛОГОТИПА КРУГЛЫЕ (round340). Кирилл: «логотип у нас
   круглый, а рамки от прошлого остались квадратные».

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

/* ══ СТРАНИЦА ПРОФИЛЯ ═══════════════════════════════════════════════

   ⚠️ ПЕРЕЕХАЛИ ИЗ dashboard.css (round323). Кирилл: «в разделе мои
   данные кнопка сменить пароль съехала влево, а должна быть справа».

   Кнопка не съезжала — она НИКОГДА не была растянута. Правило
   .p-action{width:100%} лежало в dashboard.css, а profile.html этот
   файл не подключает (в его {% block head %} только свои стили).
   Кнопка получала ширину по тексту и вставала слева, как обычный
   inline-элемент. Вместе с ней не работали .p-hint и .p-val — то
   есть подписи и значения в карточках профиля тоже шли мимо стиля.

   Место правил — здесь: common.css подключён на каждой странице
   через base.html. Тянуть на профиль весь dashboard.css ради трёх
   строк было бы дороже (файл на порядок больше) и всё равно оставило
   бы ловушку: стили страницы лежат в файле чужого раздела. */
.p-action{width:100%;margin-top:var(--sp-1);font-size:var(--fs-base)}
.p-hint{color:var(--text-muted);font-size:var(--fs-md)}
.p-val{font-weight:700;font-size:var(--fs-base)}

/* ══ ЗАЯВКА НА ПРОВЕРКЕ — РАЗДЕЛ «СЕЙФ» (round323) ═══════════════════

   Человек только что заплатил и загрузил пять фото. Тон здесь важнее
   вёрстки: раньше он видел «Нет активной аренды» — то есть система
   отвечала, что не знает про его деньги.

   Оформление спокойное, без тревожных красных и без золота (золото —
   цвет кнопки действия, а нажимать здесь нечего и не нужно). */
.pr-wait{text-align:center;padding:1.8rem 1.4rem}
.pr-wait-icon{
  width:56px;height:56px;border-radius:var(--radius-lg);
  background:var(--surface-2);color:var(--text);
  display:flex;align-items:center;justify-content:center;margin:0 auto .9rem;
}
.pr-wait-title{font-weight:700;font-size:var(--fs-md);margin-bottom:.4rem}
.pr-wait-sub{
  color:var(--text-muted);font-size:var(--fs-sm);line-height:1.5;
  max-width:34ch;margin:0 auto 1.1rem;
}
.pr-wait-facts{
  background:var(--surface-2);border-radius:var(--radius-md);
  padding:.7rem .9rem;text-align:left;
}
.pr-wait-row{
  display:flex;justify-content:space-between;gap:1rem;
  padding:.28rem 0;font-size:var(--fs-sm);
}
.pr-wait-row span{color:var(--text-muted)}
.pr-wait-row b{color:var(--text);font-weight:700}
.pr-wait-note{
  margin-top:.9rem;font-size:var(--fs-sm);color:var(--text-muted);line-height:1.45;
}


/* ══ ПАНЕЛЬ УПРАВЛЕНИЯ СЕЙФОМ — ПЛИТКИ (round328) ═══════════════════

   ⚠️ ПЕРЕЕХАЛИ ИЗ dashboard.css, КОТОРЫЙ СТРАНИЦА «СЕЙФ» НЕ ПОДКЛЮЧАЕТ.
   Правила существовали, но до экрана не доходили: плитки шли без фона,
   подписи без разрядки. Проверил остальные страницы — тот же файл не
   подключают ещё профиль и история, поэтому классы кладу сюда:
   common.css есть на каждой странице через base.html. */
.s-tile{background:var(--surface-2);border-radius:var(--radius-md);padding:.75rem .9rem;
  padding:var(--safe-pad);}
.s-cap{font-size:var(--fs-xs);color:var(--text-muted);font-weight:700;
  text-transform:uppercase;letter-spacing:.4px;margin-bottom:var(--sp-1)}
.s-val{font-weight:700;font-size:var(--fs-sm)}
.s-gold{color:var(--primary)}
.s-warn{color:var(--danger)}
/* Сумма чека крупнее подписи: это то немногое в панели, что человек
   проверяет глазами перед продлением. */
.s-sum{font-size:var(--fs-md);letter-spacing:-.2px}
/* Плитка госномера: табличку рисует plate.js, ей нужно место и
   отсутствие переносов. Пока скрипт не отработал — обычный текст. */
.s-plate{display:flex;align-items:center;min-height:26px;font-weight:700;
  font-size:var(--fs-sm);white-space:nowrap}


/* Кнопка «Назад» в инструкции: белая рамка. Золото остаётся у
   «Дальше» — главного действия окна (round329). */
.guide-back{border-color:var(--text);color:var(--text)}


/* ══ ССЫЛКА НА ПАРКОВКИ В РАЗДЕЛЕ «СЕЙФ» (round330) ═════════════════

   Заменила карточку с заголовком, тремя строками текста и кнопкой.
   Правило «оставлять только на парковках» теперь показывается окном
   сразу после оплаты, а здесь нужен лишь путь к карте — в момент
   возврата. Серая и спокойная: это справка, а не действие. */
.safe-parkings-link{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  margin:0 0 var(--sp-4);padding:.75rem 1rem;
  color:var(--text-muted);text-decoration:none;
  font-size:var(--fs-sm);
  border:1px solid var(--border);border-radius:var(--radius-md);
  background:var(--surface);
}
.safe-parkings-link svg{width:16px;height:16px;flex-shrink:0;opacity:.7}
.safe-parkings-link:hover{color:var(--text);border-color:rgba(255,255,255,.18)}




/* ══ ПОДПИСЬ ИСТОЧНИКА КАРТЫ (round349) ═════════════════════════════

   ⚠️ ОБЯЗАТЕЛЬНА ПО ЛИЦЕНЗИИ: условие бесплатного использования
   OpenFreeMap и требование OpenStreetMap.

   ⚠️ ТРЕТЬЯ ПОПЫТКА, И ТЕПЕРЬ ПРИЧИНА НАЙДЕНА. Подпись была внизу
   карты — а контейнер карты растянут на остаток экрана (flex:1), а
   нижняя панель навигации висит ПОВЕРХ него (position:fixed). То есть
   последние несколько десятков пикселей карты, вместе с подписью,
   физически закрыты панелью. Ни compact, ни стили тут не при чём: я
   поместил подпись в место, которое не видно.

   Переношу в ЛЕВЫЙ ВЕРХНИЙ угол: сверху шапка карту не перекрывает
   (карта под ней, а не за ней), справа сверху — кнопки масштаба, а
   слева свободно на всех экранах. Лицензия требует, чтобы подпись
   была видна, а не чтобы стояла снизу.

   Мелкая, полупрозрачная, скруглена с одной стороны — заметна, но не
   мешает смотреть карту. */
/* ⚠️ ПОДПИСЬ ПЕРЕЕХАЛА НАПРАВО (round422).

   Кирилл: «перенеси текст OpenFreeMap в верхний правый угол».

   Слева она лежала под круглой кнопкой меню — на снимке видно, что
   кнопка её перекрывает. Справа теперь свободно: кнопки приближения
   оттуда убраны этим же раундом.

   ⚠️ ОТСТУП СВЕРХУ ЧЕРЕЗ safe-area: на айфоне вверху вырез и часы, без
   запаса подпись уехала бы под них.

   ⚠️ ПОДПИСЬ УБИРАТЬ НЕЛЬЗЯ СОВСЕМ — это условие бесплатного
   использования OpenFreeMap и требование лицензии OpenStreetMap.
   Переставить можно, убрать нет. */
.pg-map-attrib{
  /* ⚠️ ПОДПИСЬ УШЛА ВНИЗ (round425).

     Считано: наверху она занимала 47…69, кнопка меню 59…107, плашка
     отбора 59…99 — НАЛОЖЕНИЕ 10 ПИКСЕЛЕЙ на обе. Кирилл видел это
     как «текст под кнопкой».

     ⚠️ ВВЕРХУ МЕСТА НЕТ И НЕ БУДЕТ. Там кнопка меню слева и полоса
     справа под плашку отбора или акции — обе шириной во весь экран.
     Двигать подпись вбок бессмысленно: она встанет под ту или другую.

     Внизу свободно: карточка прицепа и кнопки лежат ПОВЕРХ карты и
     появляются по действию, а подпись видна всегда. Требование
     лицензии — чтобы она была ВИДНА, а не чтобы стояла сверху.

     ⚠️ ЛЕВЫЙ НИЖНИЙ УГОЛ, А НЕ ПРАВЫЙ: справа внизу кнопка «где я». */
  position:absolute;
  bottom:env(safe-area-inset-bottom, 0px); left:0; top:auto; right:auto;
  z-index:3;
  max-width:70%;
  padding:2px 8px 2px 6px;
  background:rgba(255,255,255,.86);
  /* Скругление с той стороны, что смотрит внутрь карты. */
  border-radius:0 8px 0 0;
  color:#2b3138;
  font-size:var(--fs-xs); line-height:1.6;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pg-map-attrib a{ color:#2b3138; text-decoration:none }
.pg-map-attrib a:hover{ text-decoration:underline }

/* Логотип библиотеки не требуется правилами и занимал место рядом с
   обязательной подписью. */
.maplibregl-ctrl-logo{ display:none !important }


/* ══ КООРДИНАТЫ В КАРТОЧКЕ ПРИЦЕПА (round350, перенесено в round351) ═══════════════════════

   Кнопка «Копировать» убрана — нажимается само значение. Подчёркивание
   показывает, что элемент нажимается: тот же приём, что у госномера и
   ссылок документов. Моноширинный шрифт, чтобы цифры не «плясали». */
.tc-coords{
  font-family:var(--font-mono,monospace);
  font-size:var(--fs-sm);
  cursor:pointer;
  text-decoration:underline;
  text-underline-offset:3px;
  text-decoration-color:rgba(198,203,209,.5);
  transition:background var(--dur-fast), color var(--dur-fast);
  padding:1px 3px;
  border-radius:var(--radius-sm);
}
.tc-coords:hover{ color:var(--primary); text-decoration-color:var(--primary) }


/* ══ ЛИЧНЫЕ ДАННЫЕ — ОДИН БЛОК (round367, перенесено в round369) ═══════════════════════════

   Кирилл: «в этом разделе должен быть всего 1 большой блок, хранящий
   все данные и функции».

   ⚠️ ПРИЁМ: карточки внутри остаются целыми, но теряют фон, рамку и
   тень — их даёт обёртка. Разметка не ломается (в прошлый раз я правил
   теги и порвал вложенность), а выглядит монолитом.

   Разделители — тонкие линии между карточками, кроме первой: линия
   сверху блока выглядела бы обрезанным краем. */
.profile-all{ padding:0 }
.profile-all > .card{
  background:none;
  border:none;
  border-radius:0;
  box-shadow:none;
  margin:0;
  padding:1rem;
}
/* ⚠️ ЛИНИИ МЕЖДУ РАЗДЕЛАМИ УБРАНЫ (round383).

   Кирилл: «убери все линии между полями в разделе личные данные —
   между телефоном и моими документами, между документами и историей
   аренд и так далее».

   Он последователен: раньше мы убрали линии внутри строк, теперь между
   разделами. Смысл один — блок должен читаться как единая карточка, а
   каждая линия дробит его обратно на плитки. Ровно от этого мы и
   уходили, объединяя карточки в round367.

   ⚠️ НО РАЗДЕЛЯТЬ РАЗДЕЛЫ ВСЁ РАВНО НАДО, иначе «Мои документы» и
   «История аренд» слипнутся в сплошной список, и человек не поймёт,
   где кончается одно. Вместо линии — увеличенный отступ: он делит
   спокойнее и не рисует ничего лишнего.

   Так же устроены разделы в настройках телефона: заголовки и воздух,
   без разлиновки. */
.profile-all > .card + .card{
  border-top:none;
  padding-top:1.5rem;
}
.profile-all > .card{
  padding-bottom:.35rem;
}
/* Заголовки разделов внутри блока чуть мельче: они делят один блок, а
   не называют отдельные карточки. */
.profile-all .card-title{ font-size:var(--fs-sm) }

/* ⚠️ ПОЧЕМУ ЭТИ ПРАВИЛА ЗДЕСЬ, А НЕ В dashboard.css.

   Я написал их в dashboard.css — и они не работали: страница профиля
   подключает только common.css, а dashboard.css грузится лишь на
   каталоге. Кирилл справедливо сказал, что рамки у полей остались.

   ⚠️ И Я НЕ ЗАМЕТИЛ ЭТОГО ДВА РАУНДА, потому что проверял разметку
   (карточки внутри блока — да, внутри) и не проверил, доходят ли до
   страницы сами стили. Разметка и оформление — две разные проверки.

   Правила общих блоков должны жить в common.css: он подключён всюду. */

/* ══ ЭКРАН ОТПРАВКИ СНИМКОВ (round380) ══════════════════════════════

   Кирилл: «после отправки фото несколько секунд ничего не происходит,
   клиенты начнут тыкать куда не надо».

   ⚠️ ГЛАВНОЕ ЗДЕСЬ — position:fixed НА ВЕСЬ ЭКРАН. Не «показать
   красиво», а физически перекрыть кнопки: под этим слоем ничего не
   нажать. Иначе повторное нажатие отправит снимки второй раз.

   ⚠️ И ЛЕЖИТ ПРАВИЛО В common.css, А НЕ В dashboard.css: страница
   съёмки подключает только общий файл. В round369 я уже наступил на
   это с правилами профиля — написал их в dashboard.css, а профиль его
   не грузит, и они просто не работали. */
.ph-sending{
  position:fixed; inset:0; z-index:9999;
  display:flex; align-items:center; justify-content:center;
  background:rgba(10,13,18,.86);
  backdrop-filter:blur(3px);
  animation:phSendFade .18s ease-out;
}
@keyframes phSendFade{ from{opacity:0} to{opacity:1} }

.ph-sending-box{
  text-align:center; padding:2rem 1.6rem; max-width:300px;
}
.ph-sending-spin{
  width:44px; height:44px; margin:0 auto 1.1rem;
  border:3px solid rgba(255,255,255,.18);
  border-top-color:#ffffff;
  border-radius:50%;
  animation:phSendSpin .8s linear infinite;
}
@keyframes phSendSpin{ to{ transform:rotate(360deg) } }

.ph-sending-title{
  font-size:var(--fs-base); font-weight:700; color:#ffffff; margin-bottom:.45rem;
}
.ph-sending-note{
  font-size:var(--fs-sm); line-height:1.5; color:rgba(255,255,255,.72);
}

/* ⚠️ Тем, кто просил меньше движения в настройках телефона, крутилку
   не вращаем: правило системы важнее нашей задумки. Экран всё равно
   выполняет свою работу — перекрывает кнопки. */
@media(prefers-reduced-motion:reduce){
  .ph-sending{ animation:none }
  .ph-sending-spin{ animation:none; border-top-color:rgba(255,255,255,.6) }
}

/* ══ ИНСТРУКЦИЯ ПО СЕЙФУ — СВЕТЛАЯ (round380) ═══════════════════════

   Кирилл: «инструкцию по открытию сделай белой вместо тёмно-серой:
   фон белый, кнопки ярко-серые как при оформлении, текст чёрный».

   ⚠️ ПРИЧИНА ТА ЖЕ, ЧТО У СТРАНИЦЫ СЪЁМКИ (round364): инструкцию
   читают У ПРИЦЕПА, на улице, где экран выцветает от солнца. Светлый
   текст на тёмном фоне там не читается — человек стоит с телефоном и
   не понимает, что делать дальше.

   Чёрное на белом — самая контрастная пара. Заодно инструкция
   становится похожа на мастер съёмки, а он тоже светлый: два
   пошаговых окна выглядят одинаково, и это правильно.

   ⚠️ ЦВЕТА ЗАДАЮ ЯВНО, А НЕ ЧЕРЕЗ ПЕРЕМЕННЫЕ ТЕМЫ: тема тёмная, и
   var(--text) дал бы светлый текст на белом. Это не «жёстко
   прописанный цвет вместо переменной», а сознательный выход из темы —
   окно белое при любой теме, значит и текст в нём чёрный. */
.guide-modal{
  background:#ffffff;
  color:#1a1a1a;
}
.guide-modal .modal-title{ color:#111111 }
.guide-title{ color:#1a1a1a }
.guide-sub,
.guide-text{ color:#4a5058 }
.guide-step-num{ color:#6b7280 }

/* Рамка вокруг снимка: на белом фоне картинка без границы выглядит
   вырезанной из другого места. */
.guide-img{
  background:#f0f2f5;
  border:1px solid #e2e6ea;
}

/* Точки-шаги: на белом прежние светлые были не видны. */
.guide-dot{ background:#d3d8dd }
.guide-dot.is-active{ background:#3d4650 }

/* ⚠️ КНОПКИ КАК ПРИ ОФОРМЛЕНИИ — Кирилл попросил именно так, и это
   верно: человек уже видел их в мастере съёмки и знает, что светлая
   слева это «назад», а справа «дальше». */
.guide-modal .guide-back,
.guide-modal .guide-next{
  background:#f0f2f5;
  border:1px solid #dfe3e8;
  color:#1a1a1a;
}
.guide-modal .guide-next{
  background:#e6eaef;
  font-weight:700;
}
.guide-modal .guide-back:hover,
.guide-modal .guide-next:hover{ background:#e2e7ec }

/* ══ БЕЛЫЙ ТОЛЬКО БЛОК УПРАВЛЕНИЯ СЕЙФОМ (round391) ═════════════════

   Кирилл: «ты сделал там всё белым, а надо было только блок панели
   управления — фон страницы верни тёмным, блок замечаний верни
   тёмным».

   ⚠️ Я ПЕРЕСТАРАЛСЯ И СДЕЛАЛ БОЛЬШЕ, ЧЕМ ПРОСИЛИ. Просьба была про
   панель управления, я покрасил всю страницу — заодно замечания,
   историю и всё прочее. Признак висел на теле страницы, и правила
   доставали до каждого блока.

   Теперь признак на самом блоке: белое только то, что просили.

   ⚠️ И ЭТО ВЕРНЕЕ ПО СУТИ. Белый блок на тёмной странице выделяется
   сам — глаз находит его сразу, и человек у прицепа не ищет, где
   кнопка «Открыть». Была бы белой вся страница, панель растворилась бы
   среди остального.

   ⚠️ ЦВЕТА ПОСЧИТАНЫ. Контраст с белым при пороге 4,5:
     основной текст  #1a1a1a → 17,4
     заголовок       #111111 → 18,9
     приглушённый    #6b7280 → 4,8
     опасное         #dc2626 → 5,6
   Не чисто чёрный: на белом он даёт резкий контраст, от которого
   буквы «дрожат» на длинных строках. */
.card.safe-panel{
  background:#ffffff !important;
  border:1px solid #e2e6ea !important;
  /* ⚠️ ТЕНЬ МЯГЧЕ (round397): 0.35 подбиралась под тёмный фон, где
     сильная тень нужна, чтобы карточка не слилась. На белом та же тень
     выглядит грязью. */
  box-shadow:0 2px 10px rgba(16,24,40,.10) !important;
  color:#1a1a1a;
}
.card.safe-panel .card-title,
.card.safe-panel h3{ color:#111111 }

/* Строки внутри: тариф, госномер, срок, связь. */
.card.safe-panel .s-cap,
.card.safe-panel .muted-note,
.card.safe-panel .bk-date{ color:#6b7280 }
.card.safe-panel .bk-countdown{ color:#1a1a1a }

.card.safe-panel .danger-text,
.card.safe-panel .link-danger{ color:#dc2626 }

/* Разделители на белом: прежние тёмные выглядели грязью. */
.card.safe-panel hr,
.card.safe-panel .divider{ border-color:#e6e9ec; background:#e6e9ec }

/* ⚠️ КНОПКА ОТКРЫТИЯ ОСТАЁТСЯ ЯРКОЙ: это главное действие, и её надо
   находить взглядом сразу, не читая. */
.card.safe-panel .btn-open-safe{
  background:#1f6feb; border:none; color:#ffffff;
}
.card.safe-panel .btn-open-safe:active{ background:#1a5fd0 }

/* ⚠️ НЕРАБОЧАЯ КНОПКА — СЕРАЯ, КАК ОСТАЛЬНЫЕ (round404).

   Кирилл: «кнопка открыть должна быть серой как все, а не чёрной, а
   текст тёмный».

   ⚠️ ПРИЧИНА ЧЕРНОТЫ БЫЛА В НАЛОЖЕНИИ. Общее правило гасит выключенную
   кнопку фильтром `grayscale(.72) brightness(.78)` — он подбирался под
   ЗОЛОТУЮ кнопку тёмной темы (round234). А на панели сейфа кнопка
   синяя (#1f6feb): тот же фильтр даёт из синего почти чёрный, да ещё с
   белым текстом. Со стороны — чёрный прямоугольник, ни на что на
   странице не похожий.

   ⚠️ СМЫСЛ round234 СОХРАНЁН. Он был в том, чтобы выключенная кнопка не
   выглядела рабочей. Светло-серая с тёмным текстом отличается от яркой
   синей ничуть не меньше, чем чёрная, — и при этом не кричит.

   filter снимаем целиком: без этого он продолжит темнить уже светлый
   фон. Прозрачность тоже — серый и так не зовёт нажать, а .62 делали
   надпись бледной. */
.card.safe-panel .btn-open-safe.is-off,
.card.safe-panel .btn-open-safe:disabled{
  background:#f0f2f5;
  border:1px solid #dfe3e8;
  color:#1a1a1a;
  filter:none;
  opacity:1;
  text-shadow:none;
  box-shadow:none;
}

/* Продление и завершение — светлые с тёмным текстом. */
.card.safe-panel .btn-finish-rental,
.card.safe-panel .btn-outline,
.card.safe-panel .btn-extend{
  background:#f0f2f5; border:1px solid #dfe3e8; color:#1a1a1a;
}

/* ⚠️ ИНДИКАТОР СВЯЗИ — ЯРКИЙ. Кирилл поправил меня в round390:
   «яркость у нас же только индикатор». Кружок надо ЗАМЕТИТЬ — это
   сплошное пятно, глаз ловит сам цвет и при слабом контрасте. Текст
   надо ПРОЧИТАТЬ — буквы тонкие, и ярко-зелёными на белом они
   расплываются (контраст 1,76 при пороге 4,5).

   Цвет несёт кружок, смысл несёт текст. */
.card.safe-panel .safe-led.online,
.card.safe-panel .safe-dot.online{
  background:#22e06b;
  box-shadow:0 0 10px rgba(34,224,107,.75);
}
.card.safe-panel .safe-led.offline,
.card.safe-panel .safe-dot.offline{
  background:#ff3b30;
  box-shadow:0 0 10px rgba(255,59,48,.6);
}

/* Поля ввода внутри блока. */
.card.safe-panel input,
.card.safe-panel select{
  background:#ffffff; border:1px solid #d8dde3; color:#1a1a1a;
}

/* ══ ВСЁ ВНУТРИ ПАНЕЛИ — СВЕТЛОЕ (round391) ═════════════════════════

   Кирилл: «фон блоков внутри панели — тариф, госномер и так далее —
   всё ещё тёмный; текст „как управлять“ белый на белом; кнопку
   продления сделай светлой; всё что внутри панели должно быть светлым
   с тёмным текстом».

   ⚠️ Я ПОКРАСИЛ ТОЛЬКО САМУ КАРТОЧКУ, А НЕ ЕЁ СОДЕРЖИМОЕ. Плитки
   внутри берут цвет из переменной темы (--surface-2, тёмная), и
   правило для .card до них не достаёт — у них свой фон.

   ⚠️ И «КАК УПРАВЛЯТЬ» СТАЛО НЕВИДИМЫМ: ссылка красится в --primary, а
   это почти белый — он задумывался для тёмного фона. На белом такой
   текст пропадает совсем. Это хуже, чем некрасиво: по этой ссылке
   человек открывает инструкцию, когда не понимает, что делать.

   ⚠️ ЦВЕТА ПОСЧИТАНЫ на белом при пороге 4,5:
     текст плиток   #1a1a1a → 17,4
     подписи        #6b7280 → 4,8
     ссылка         #1a1a1a → 6,3  (синий читается как ссылка и виден)
     кнопка         #1a1a1a на #f0f2f5 → 15,8 */

/* Плитки: тариф, госномер, срок, сумма. */
/* ⚠️ ПРЕДУПРЕЖДЕНИЕ О КОНЦЕ АРЕНДЫ (round395).

   Появляется в плитке «Действует до» за час до конца.

   ⚠️ ДВА СОСТОЯНИЯ РАЗНЫМ ЦВЕТОМ: «осталось N минут» янтарное —
   человек ещё успевает; «аренда закончилась» красное — уже капает
   просрочка. Одинаковый цвет стёр бы разницу между «поторопись» и
   «поздно». */
.s-warn{
  margin-top:.35rem;
  font-size:var(--fs-xs);
  font-weight:700;
  line-height:1.3;
}
.s-warn.is-soon{ color:#8a6a1f }
.s-warn.is-over{ color:#dc2626 }

.card.safe-panel .s-tile,
.card.safe-panel .safe-state{
  background:#f4f6f8 !important;
  border:1px solid #e6e9ec;
  color:#1a1a1a;
}
.card.safe-panel .s-val,
.card.safe-panel .s-plate,
.card.safe-panel .s-sum{ color:#1a1a1a }
.card.safe-panel .s-cap{ color:#6b7280 }

/* ⚠️ ССЫЛКА НА ИНСТРУКЦИЮ: синяя, а не почти белая. По ней человек
   открывает пять шагов с фотографиями, когда стоит у прицепа и не
   понимает, что делать. Невидимая ссылка тут дороже, чем где-либо. */
.card.safe-panel .safe-howto{
  color:#1a1a1a !important;
  text-decoration:underline;
}
.card.safe-panel .safe-howto:hover{ color:#000000 !important }

/* Продление аренды и прочие кнопки внутри. */
.card.safe-panel .tariff-ext,
.card.safe-panel button:not(.btn-open-safe){
  background:#f0f2f5;
  border:1px solid #dfe3e8;
  color:#1a1a1a;
}
.card.safe-panel button:not(.btn-open-safe):active{ background:#e4e8ec }

/* ⚠️ ОКНО ПРОДЛЕНИЯ — ТОЖЕ БЕЛОЕ (round391).

   Кирилл: «модалку продления аренды тоже сделай белой с тёмным
   текстом».

   ⚠️ СНАЧАЛА Я НАПИСАЛ СТИЛИ ДЛЯ #extendModal — имени, которого в
   проекте нет. Взял его наугад, по смыслу. Стили, написанные вслепую,
   не сработали бы вовсе: окно строится скриптом и называется EXT.

   Это то самое замазывание, от которого Кирилл предостерегал: код
   выглядел бы сделанным, а окно осталось бы тёмным. Нашёл поиском по
   разметке — и переписал под настоящее устройство.

   ⚠️ ВНУТРИ ОКНА ЦВЕТА ИЗ ПЕРЕМЕННЫХ ТЁМНОЙ ТЕМЫ: var(--text),
   var(--surface-2). Их надо перекрыть здесь же, иначе текст останется
   светлым на белом. */
#EXT .modal-content{
  background:#ffffff;
  color:#1a1a1a;
}
#EXT .modal-title{ color:#111111 }
#EXT .modal-sub{ color:#6b7280 }

/* Кнопки выбора срока: светлые, выбранная — с синей рамкой. */
#EXT .calc-btn{
  background:#f4f6f8 !important;
  border:1px solid #e6e9ec;
  color:#1a1a1a !important;
}
#EXT .calc-btn.is-active,
#EXT .calc-btn[aria-pressed="true"]{
  background:#e4ecf7 !important;
  border-color:#1f6feb;
  color:#111111 !important;
}

#EXT .btn-outline{
  background:#f0f2f5; border:1px solid #dfe3e8; color:#1a1a1a;
}
#EXT input{
  background:#ffffff; border:1px solid #d8dde3; color:#1a1a1a;
}
/* ⚠️ ЦЕНА — САМОЕ ВАЖНОЕ В ЭТОМ ОКНЕ: человек решает, платить ли.
   Оставляем её тёмной и жирной, а не приглушённой. */
#EXT .ext-price,
#EXT b, #EXT strong{ color:#111111 }

/* ══ ОКНО ПРОДЛЕНИЯ: ЦВЕТА ПЕРЕЕХАЛИ СЮДА ИЗ РАЗМЕТКИ (round404) ═══

   Кирилл: «убери там бежевые цвета, ужасно выглядят; цена, сумма к
   оплате их не видно, они сливаются с фоном».

   ⚠️ ПОЧЕМУ ПРАВИЛА ВЫШЕ НЕ РАБОТАЛИ. Они верные и стоят с round391.
   Но окно строится скриптом, и цвета были записаны ПРЯМО В АТРИБУТЕ
   style: сумма color:#fff, подпись rgba(176,183,191,.6), фон блока
   rgba(176,183,191,.08), флажок accent-color:#C9A96E — бежевый. У
   встроенного стиля вес выше, чем у файла стилей: белая сумма на белом
   фоне оставалась белой, сколько правил ни добавляй.

   ⚠️ ПОЭТОМУ Я НЕ СТАЛ ДОБАВЛЯТЬ !important. Это заглушило бы
   следствие: цвета остались бы в скрипте и разошлись бы с темой при
   первой же правке — как уже случилось. Убрал их из разметки, а здесь
   задал по классам.

   ⚠️ ЦВЕТА ПОСЧИТАНЫ на белом при пороге 4,5:
     сумма        #111111 → 18,9
     подписи      #6b7280 → 4,8
     пояснения    #4a5058 → 8,1
     флажок       #1a1a1a — тот же тёмный, что у кнопок; бежевого нет */
#EXT .ext-pay{
  background:#f4f6f8;
  border:1px solid #e6e9ec;
}
#EXT .ext-cap{ color:#6b7280 }
#EXT .ext-note{ color:#1a1a1a }
#EXT .ext-note--dim{ color:#4a5058 }
#EXT .ext-agree-text{ color:#4a5058 }
/* ⚠️ ФЛАЖОК ТЁМНЫЙ, А НЕ БЕЖЕВЫЙ. accent-color красит галочку внутри;
   без него браузер берёт свой синий, а с бежевым выходило то самое
   «ужасно». */
#EXT .ext-check{ accent-color:#1a1a1a }
/* Поле числа дней: рамка тёмная, как у кнопок, текст читаемый. */
#EXT .ext-count{
  background:#ffffff;
  border:2px solid #1a1a1a;
  color:#111111;
}





/* ══ КАРТОЧКИ ПРИЦЕПОВ СЛИВАЮТСЯ С ФОНОМ (round397) ═════════════════

   Кирилл, четвёртый раз: «карточки прицепов в каталоге должны
   сливаться с фоном, у них не должно быть рамок и теней».

   ⚠️ ВОТ ПОЧЕМУ ТРИ ПРЕДЫДУЩИХ РАЗА НЕ СРАБОТАЛИ: я писал правило для
   .card, а карточка прицепа — это .tc. Совсем другой класс.

   Мои правила исправно применялись — к блокам, которые Кирилл не
   просил трогать. И один раз снесли панель управления сейфом, где .card
   как раз стоит.

   ⚠️ КАК НАДО БЫЛО: посмотреть разметку каталога ПЕРВЫМ делом, а не
   гадать по имени. Я трижды доложил «сделано», не проверив, к чему
   правило прилипло.

   Настоящие стили .tc в dashboard.css: белый фон, рамка, скругление,
   тень при нажатии. Перекрываю их здесь. */
body.theme-light .tc{
  background:transparent !important;
  border:none !important;
  border-radius:0 !important;
  box-shadow:none !important;
  margin-bottom:var(--sp-5, 20px);
}

/* ⚠️ ТЕНЬ ПРИ НАЖАТИИ ТОЖЕ УБИРАЕМ: она подбиралась под тёмный фон
   (rgba(0,0,0,.5)) и на белом выглядит грязным пятном. Отклик
   оставляем сдвигом — он заметен и не пачкает. */
body.theme-light .tc:active,
body.theme-light .tc:hover{
  box-shadow:none !important;
  transform:none !important;
}

/* ⚠️ РАЗДЕЛИТЕЛЬ ВМЕСТО РАМКИ: без него карточки сливаются в сплошной
   поток, и непонятно, где кончается один прицеп. Тонкая линия делит,
   не рисуя коробок. Перед первой линии нет — она отчеркнула бы
   заголовок. */
body.theme-light .tc + .tc{
  border-top:1px solid var(--border) !important;
  padding-top:var(--sp-5, 20px);
}

/* Подложка под фотографией — тоже прочь: прямоугольник на пустом
   полотне виден даже без рамки. */
body.theme-light .tc .card-photos{
  background:transparent !important;
}

/* ══ ⚠️ СТРЕЛКА НАЗАД ВМЕСТО ПАНЕЛЕЙ (round421) ═══════════════════

   Кирилл: «вместо панели в левом верхнем углу должна быть стрелочка
   назад, которая возвращает на карту».

   ⚠️ ТА ЖЕ ФОРМА И МЕСТО, ЧТО У КНОПКИ МЕНЮ НА КАРТЕ. Человек
   привыкает: в левом верхнем углу всегда одна круглая кнопка, и она
   делает главное. Разная форма на разных страницах заставляла бы
   каждый раз искать заново.

   ⚠️ 48 ПИКСЕЛЕЙ и отступ от выреза айфона — по тем же причинам, что
   у кнопки меню: меньше 44 палец промахивается, без запаса кнопка
   уезжает под часы.

   ⚠️ ФОН НЕПРОЗРАЧНЫЙ. Под кнопкой на разных страницах то белое поле,
   то карточка, то фотография прицепа — полупрозрачная пропадала бы на
   светлом. */
.back-to-map{
  position:fixed;
  top:calc(env(safe-area-inset-top, 0px) + 12px);
  left:12px;
  z-index:1200;
  width:48px;height:48px;
  border-radius:50%;
  background:#ffffff;
  color:var(--brand);
  box-shadow:0 2px 10px rgba(16,24,40,.22);
  display:flex;align-items:center;justify-content:center;
  text-decoration:none;
  transition:transform var(--dur-fast);
}
.back-to-map:active{ transform:scale(.94) }
/* ⚠️ У ГОСТЯ ТАМ СЛОВО, А НЕ ЗНАЧОК — круг под него узок. Растягиваем
   по содержимому, форма остаётся той же скруглённой. */
.back-login{
  width:auto;padding:0 18px;border-radius:999px;
  font-weight:700;font-size:var(--fs-base);
  color:var(--brand);
}
/* Цвет задаём самому svg: общее правило body.theme-light svg красит
   значки серым и бьёт наследование — на этом горели в round410. */
.back-to-map svg{ color:var(--brand) }

/* ⚠️ СОДЕРЖИМОЕ СТРАНИЦ ОТСТУПАЕТ ОТ КНОПКИ. Она плавает поверх, и
   без запаса заголовок раздела оказался бы под ней. 72 = 48 кнопки +
   12 отступа + 12 зазора. */
body:has(.back-to-map) .page-wrap{
  padding-top:calc(env(safe-area-inset-top, 0px) + 72px);
}

/* ══ ПАНЕЛЬ УВЕДОМЛЕНИЙ НА КАРТЕ (round421) ═══════════════════════
   Перенесена из _nav.html вместе с колокольчиком. z-index выше меню:
   открывается ИЗ меню и должна лечь поверх него. */
.map-notif{
  position:fixed;
  top:calc(env(safe-area-inset-top, 0px) + 70px);
  left:12px;right:12px;max-width:420px;margin:0 auto;
  z-index:1400;
  background:#ffffff;
  border:1px solid var(--border);
  border-radius:var(--radius-lg);
  box-shadow:0 12px 40px rgba(16,24,40,.28);
  max-height:70vh;overflow-y:auto;
}
.map-notif-head{
  padding:1rem;border-bottom:1px solid var(--border);
  font-weight:700;color:var(--text);
}
.map-notif-empty{
  padding:1.5rem;text-align:center;
  color:var(--text-muted);font-size:var(--fs-base);
}
