/* ═══════════════════════════════════════════════════════════════════════
   Road to Freedom — оболонка для телефона.

   Не «те саме, тільки вужче». На настільному екрані інтерфейс стоїть збоку
   від мапи; на телефоні місця збоку немає, тож усе, чим керують, лежить
   поверх мапи склом у нижній третині — там, де дістає великий палець. Угорі
   лишається тільки те, що читають.

   ─── три шкали, з яких складено все ───────────────────────────────────

   ПРОСТІР кратний чотирьом. Не з любові до круглих чисел: у першій редакції
   тут було п'ятнадцять різних відступів (7, 9, 11, 13, 14, 18, 22, 34…), і
   поверхні одного рівня стояли на різних вертикалях — око читає це як
   недбалість, навіть коли не може назвати причину.

   КЕГЛІВ шість, не п'ятнадцять. Дрібніше за 11 px на телефоні в русі не
   читається взагалі, тож нижньої межі тримаємося жорстко.

   СКЛО має три рівні, і що поверхня вище, то вона легша й розмитіша — так
   само, як в iOS. Однакове скло на різній висоті зливає їх в одну площину, і
   зникає відчуття, що аркуш лежить НАД мапою, а навігація — над аркушем.

   ─── чому скло, а не панель ───────────────────────────────────────────

   Непрозора смуга внизу на 90 пікселів забирає в мапи десяту частину висоти
   назавжди — і саме ту, куди дивляться. Крізь скло видно, що під ним, тож
   смуга не відрізає ділянку, а лежить на ній.

   Усе під класом .is-mobile на <html>, який ставить index.html до першої
   відмальовки. Медіазапитом це задати не можна: телефон боком — 844 px, і
   розкладка стрибала б на кожному повороті.
   ═══════════════════════════════════════════════════════════════════════ */

/* ────────────────────────────────────────────────────────── 1. токени */

.is-mobile {
  /* простір: крок 4 */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px;

  /* скруглення: чотири, і жодного більше */
  --r-s: 12px; --r-m: 16px; --r-l: 22px; --r-pill: 999px;

  /* кеглі */
  --t-title: 22px;   /* заголовок екрана, serif */
  --t-lede:  16px;   /* головний рядок картки */
  --t-body:  15px;   /* абзац */
  --t-meta:  13px;   /* підпис, примітка */
  --t-tag:   11px;   /* мітка mono, нижня межа читабельності */
  --t-tab:   10px;   /* підпис вкладки: коротке слово, високий контраст */

  /* навігація */
  --nav-h: 62px;
  --nav-gap: var(--s2);
  --nav-side: var(--s5);

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* Скільки внизу зайнято навігацією разом із безпечною зоною. Одне джерело
     замість шести однакових обчислень у накладках мапи. */
  --nav-space: calc(var(--nav-h) + var(--safe-b) + 18px);

  /* СКЛО. Три рівні: накладки на мапі → аркуш → навігація.
     Заповнення тримаємо низьким: вище ~0.45 воно перестає читатися як скло
     й стає просто темною плашкою. Насиченість повертає колір, який blur
     з'їдає, brightness трохи піднімає верхній рівень над рештою. */
  --g-low-bg: rgba(10, 13, 18, 0.46);
  --g-low-fx: saturate(170%) blur(18px);
  --g-mid-bg: rgba(13, 17, 23, 0.38);
  --g-mid-fx: saturate(180%) blur(26px);
  --g-top-bg: rgba(22, 27, 34, 0.24);
  --g-top-fx: saturate(190%) blur(30px) brightness(1.07);

  /* Грані. Світла зверху й темна знизу — це те, що робить поверхню
     поверхнею: без нижньої скло виглядає наліпкою, а не пластиною. */
  --rim:  inset 0 1px 0 rgba(255, 255, 255, 0.18);
  --rim-b: inset 0 -1px 0 rgba(0, 0, 0, 0.42);
  --cast: 0 10px 30px -8px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.32);
  --hair: 1px solid rgba(255, 255, 255, 0.10);

  /* Рух: пружина для панелей, легкий перебіг для пігулки під вкладкою. */
  --spring: cubic-bezier(0.32, 0.72, 0, 1);
  --bounce: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* --ink-3 (#5d6b78) на склі дає контраст близько 3.4:1 — нижче за норму
     для дрібного тексту. Для всього, що менше за 13 px, беремо це. */
  --ink-dim: #a3b1bd;

  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

.m-shell { display: none; }
.is-mobile .m-shell { display: block; }

/* ─────────────────────────────────────────── 2. каркас: мапа на весь екран */

.is-mobile body {
  display: block;
  overflow: hidden;
  /* dvh, а не vh: мобільний Safari міряє vh по РОЗГОРНУТОМУ вікну, тобто без
     адресної смуги, і нижні 60 пікселів сторінки лежать під нею. */
  height: 100dvh;
  overscroll-behavior: none;
}

.is-mobile .masthead,
.is-mobile .console,
.is-mobile .rail,
.is-mobile .caption,
.is-mobile .ai-call { display: none; }

.is-mobile .stage { display: block; position: fixed; inset: 0; }
.is-mobile .canvas { position: absolute; inset: 0; }
.is-mobile #map { position: absolute; inset: 0; height: 100%; }

/* Мапа дотягується під вікно рівно на ту смугу, якої вікну бракує до екрана
   (міряє underfill() у mobile.js). У застосунку з екрана «Home» iOS буває
   віддає веб-в'ю вже без нижньої безпечної зони — і тоді під мапою лишалася
   чорна смуга завширшки в смугу жестів. Якщо вікно й так на весь екран,
   --under дорівнює нулю й правило нічого не робить. */
.is-mobile.is-standalone .stage { bottom: calc(-1 * var(--under, 0px)); }
/* Накладки на мапі відлічуються від низу .canvas, який тепер нижчий за екран,
   тож те саме число повертаємо їм у запас. */
.is-mobile.is-standalone { --nav-space: calc(var(--nav-h) + var(--safe-b) + 18px + var(--under, 0px)); }

/* Зерна на телефоні немає. На настільному воно рятує великі темні площини від
   мертвого вигляду, а тут це шар на весь екран із mix-blend-mode: overlay і
   z-index 9999 — тобто композиція поверх УСЬОГО, включно з чотирма скляними
   поверхнями, на кожен кадр прокрутки. Ціна є, а на 0.02 непрозорості поверх
   розмиття його все одно не видно. */
.is-mobile .grain { display: none; }

/* ────────────────────────────────────────────────── 3. скло, три рівні */

.is-mobile .m-chips .cell,
.is-mobile .scale,
.is-mobile .dossier,
.is-mobile .draw-hud,
.is-mobile .leaflet-popup-content-wrapper {
  background: var(--g-low-bg);
  -webkit-backdrop-filter: var(--g-low-fx);
  backdrop-filter: var(--g-low-fx);
  border: var(--hair);
  box-shadow: var(--rim), var(--rim-b), var(--cast);
}

.is-mobile .m-sheet,
.is-mobile .m-mark {
  background: var(--g-mid-bg);
  -webkit-backdrop-filter: var(--g-mid-fx);
  backdrop-filter: var(--g-mid-fx);
  border: var(--hair);
  box-shadow: var(--rim), var(--cast);
}

.is-mobile .m-bar,
.is-mobile .m-orb {
  background: var(--g-top-bg);
  -webkit-backdrop-filter: var(--g-top-fx);
  backdrop-filter: var(--g-top-fx);
  border: var(--hair);
  box-shadow: var(--rim), var(--rim-b), 0 8px 26px -10px rgba(0, 0, 0, 0.5);
}

/* Там, де скла в браузері немає (старий Android, режим економії), прозорість
   перестає бути прийомом і стає вадою: текст лягає просто на мапу. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .is-mobile .m-chips .cell,
  .is-mobile .scale,
  .is-mobile .dossier,
  .is-mobile .draw-hud,
  .is-mobile .leaflet-popup-content-wrapper,
  .is-mobile .m-sheet,
  .is-mobile .m-mark,
  .is-mobile .m-bar,
  .is-mobile .m-orb { background: rgba(9, 12, 17, 0.94); }
}

/* ───────────────────────────────────────────────────── 4. верхня смужка */

.is-mobile .m-top {
  position: fixed; z-index: 1200;
  top: calc(var(--safe-t) + var(--s2));
  left: var(--s3); right: var(--s3);
  display: flex; align-items: center; gap: var(--s2);
  pointer-events: none;                 /* проміжки лишаються за мапою */
}
.is-mobile .m-top > * { pointer-events: auto; }

.is-mobile .m-mark {
  position: relative; flex: none;
  width: 38px; height: 38px; border-radius: var(--r-s);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-weight: 600; font-size: var(--t-tag);
  letter-spacing: -0.02em; line-height: 1;
  color: var(--signal);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  transition: transform 0.12s ease;
}
/* Ціль для пальця більша за сам значок: 38 + 6 з кожного боку = 50.
   Малювати кнопку на 50 пікселів заради трьох літер було б грубо. */
.is-mobile .m-mark::after { content: ''; position: absolute; inset: -6px; }
.is-mobile .m-mark:active { transform: scale(0.92); }

/* Числа з шапки — пігулками, які гортаються вбік. Тримати їх у нерухомому
   рядку означало б або обрізати, або зменшити до нечитабельного. */
.is-mobile .m-chips {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--s1);
  overflow-x: auto; overflow-y: hidden;
  touch-action: pan-x;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  padding: 2px;
  /* Маски тут НЕМАЄ, хоч край, що гортається, і просився згасати.
     Елемент з mask стає Backdrop Root, і backdrop-filter у його дітей починає
     семплити порожнечу замість мапи: пігулки лишилися б без розмиття —
     46-відсоткова плівка просто на тайлах, крізь яку білі числа зникають над
     світлою дорогою. Те саме роблять opacity < 1, filter і clip-path на
     предку. Скло дорожче за згасання, тож край просто обривається — так само,
     як в усіх горизонтальних стрічках iOS. */
}
.is-mobile .m-chips::-webkit-scrollbar { display: none; }
.is-mobile .m-chips .readout { display: contents; }
/* flex-direction: row — явно. Базове правило в style.css ставить клітинці
   стовпчик (число над підписом), і на телефоні вміст двома рядками не влазив
   у пігулку заввишки 30: число виїжджало ЗА неї й висіло над склом окремо.
   У рядок воно й читається краще: «1 342 км кордону» — це одна фраза. */
.is-mobile .m-chips .cell {
  flex: none;
  display: flex; flex-direction: row; align-items: baseline; gap: 5px;
  height: auto; min-height: 30px; padding: var(--s1) var(--s3);
  border-radius: var(--r-pill);
  text-align: left; border-left: none;
}
/* Правило зі style.css лишає в шапці одну клітинку — там для решти не було
   місця. Тут місце є: пігулки гортаються. */
.is-mobile .m-chips .cell:nth-child(n+2) { display: flex; }
.is-mobile .m-chips .cell b {
  font-size: var(--t-meta); font-family: var(--mono); color: var(--ink);
}
.is-mobile .m-chips .cell span {
  font-size: var(--t-tag); color: var(--ink-dim);
  letter-spacing: 0; text-transform: none;
}
.is-mobile .m-chips .cell.hot b { color: var(--ro); }

/* Коли відкрито аркуш, числа ховаються: вони описують мапу, а мапи в цей
   момент майже не видно. */
.is-mobile .m-chips { transition: opacity 0.25s ease 0.08s, transform 0.3s var(--spring) 0.08s; }
.is-mobile.has-sheet .m-chips {
  opacity: 0; transform: translateY(-6px); pointer-events: none; transition-delay: 0s;
}

/* ────────────────────────────────────── 5. навігація: капсула й коло */

.is-mobile .m-nav {
  position: fixed; z-index: 4500;
  left: 0; right: 0; margin-inline: auto;
  width: min(480px, calc(100% - var(--nav-side) * 2));
  bottom: calc(var(--safe-b) + 6px);
  height: var(--nav-h);
  display: flex; align-items: stretch; gap: var(--nav-gap);
  pointer-events: none;                 /* проміжок між капсулою й колом */
  transition: height 0.4s var(--spring);
}
.is-mobile .m-nav > * { pointer-events: auto; }

/* Поки піднято клавіатуру, острова немає — так само, як iOS ховає свою смугу
   вкладок. Інакше він або лишається під клавіатурою, або висить посеред
   екрана: fixed прибитий до layout viewport, який від клавіатури не
   змінюється.

   display, а не transform чи opacity: обидва зробили б острів Backdrop Root і
   вимкнули б скло в капсули й кола — те саме, що вже сталося зі смугою
   чисел. */
.is-mobile.is-kb .m-nav { display: none; }
/* Разом з островом зникає й місце, яке під нього лишали всі накладки, аркуш,
   аналітика й підпис під полем асистента. Одна змінна — шість правил. */
.is-mobile.is-kb { --nav-space: var(--s3); }

/* Згортання на прокрутку: гортаєш униз — підписи зникають, острів стає
   нижчим і віддає мапі ще дванадцять пікселів; гортаєш угору — вертається. */
.is-mobile .m-nav.is-min { --nav-h: 50px; }

.is-mobile .m-bar {
  position: relative; flex: 1; min-width: 0;
  display: flex; padding: 6px;
  /* Справжня капсула, а не «дуже скруглений прямокутник»: радіус у пікселях
     при зміні висоти на прокрутку почав би відставати від форми. */
  border-radius: var(--r-pill);
}

/* Пігулка під активною вкладкою. Веде її transform, а не left: тоді рух не
   викликає перерахунку розкладки й лишається плавним на слабкому телефоні.
   Ширину й зсув рахує mobile.js — вкладок буває три або чотири. */
.is-mobile .m-pill {
  position: absolute; top: 6px; bottom: 6px; left: 6px;
  width: var(--pill-w, 0px);
  transform: translateX(var(--pill-x, 0px));
  background: color-mix(in srgb, var(--signal) 20%, transparent);
  border: 1px solid color-mix(in srgb, var(--signal) 34%, transparent);
  border-radius: var(--r-pill);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform 0.38s var(--bounce), width 0.38s var(--bounce), opacity 0.2s ease;
  pointer-events: none;
}
.is-mobile .m-bar.is-first .m-pill { transition: none; }

.is-mobile .m-tab,
.is-mobile .m-orb {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 0;
  background: none; border: none; cursor: pointer;
  color: var(--ink-2);
  font-family: var(--mono); font-size: var(--t-tab); letter-spacing: 0.04em;
  text-transform: uppercase;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  transition: color 0.2s ease, transform 0.1s ease;
}
.is-mobile .m-tab { flex: 1; min-width: 0; }
.is-mobile .m-tab[hidden] { display: none; }

.is-mobile .m-tab svg,
.is-mobile .m-orb svg {
  width: 19px; height: 19px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  transition: stroke-width 0.25s ease;
}
.is-mobile .m-orb svg { width: 21px; height: 21px; }

.is-mobile .m-tab span {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: opacity 0.22s ease, max-height 0.26s var(--spring);
  max-height: 14px;
}
.is-mobile .m-nav.is-min .m-tab span { opacity: 0; max-height: 0; }

.is-mobile .m-tab.on { color: var(--signal); }
.is-mobile .m-tab.on svg { stroke-width: 2; }
.is-mobile .m-tab:active,
.is-mobile .m-orb:active { transform: scale(0.9); }

/* Коло. Діаметр дорівнює висоті капсули й береться з тієї самої змінної —
   інакше при згортанні воно перестало б бути колом. */
.is-mobile .m-orb {
  flex: 0 0 auto; width: var(--nav-h);
  border-radius: 50%;
  transition: width 0.4s var(--spring), color 0.2s ease,
              background 0.2s ease, transform 0.1s ease;
}
.is-mobile .m-orb.on {
  color: var(--signal);
  background: color-mix(in srgb, var(--signal) 20%, var(--g-top-bg));
  border-color: color-mix(in srgb, var(--signal) 38%, transparent);
}

/* Асистент кличе до себе рівно доти, доки ним жодного разу не скористалися. */
.is-mobile .m-tab.is-new svg { animation: m-spark 2.8s ease-in-out infinite; }
@keyframes m-spark {
  0%, 72%, 100% { opacity: 1; }
  84%           { opacity: 0.4; }
}

/* ───────────────────────────────────────────────────── 6. аркуш */

.is-mobile .m-scrim {
  position: fixed; inset: 0; z-index: 1250;
  background: rgba(3, 5, 8, 0.4);
  opacity: 0; transition: opacity 0.42s var(--spring);
}
.is-mobile .m-scrim.is-on { opacity: 1; }
.is-mobile .m-scrim[hidden] { display: none; }

.is-mobile .m-sheet {
  position: fixed; z-index: 1300;
  left: 0; right: 0;
  /* Не просто нижче, а НАД клавіатурою: самої лише меншої висоти замало —
     аркуш лишався б прибитим до низу сторінки, тобто цілком під нею. */
  bottom: var(--kb, 0px);
  /* Висота завжди повна, а положення задає зсув. Анімувати height було б
     чесніше на вигляд і гірше насправді: кожен кадр перебудовував би вміст,
     а в аркуші шарів його чимало. */
  /* --kb — висота клавіатури, яку міряє mobile.js. iOS не зменшує ні dvh, ні
     вікно, коли її піднімає, тож без цього нижня частина аркуша (а в пошуку
     це саме поле вводу) лишалася б під нею. */
  height: calc(100dvh - var(--safe-t) - 44px - var(--kb, 0px));
  display: flex; flex-direction: column;
  border-radius: var(--r-l) var(--r-l) 0 0;
  border-bottom: none;
  transform: translateY(var(--m-off, 100%));
  transition: transform 0.44s var(--spring);
  will-change: transform;
}
.is-mobile .m-sheet[hidden] { display: none; }
.is-mobile .m-sheet.is-drag { transition: none; }

.is-mobile .m-grab {
  flex: none; height: 22px; width: 100%;
  background: none; border: none; padding: 0;
  position: relative; cursor: grab; touch-action: none;
}
.is-mobile .m-grab::before {
  content: ''; position: absolute; left: 50%; top: 8px;
  width: 36px; height: 5px; margin-left: -18px; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.24);
}

.is-mobile .m-sheet-top {
  flex: none; display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s4) var(--s3);
}
.is-mobile .m-sheet-top h2 {
  /* Вільне місце забирає заголовок, а не кнопки: інакше flexbox ділить його
     між усіма auto-відступами порівну, і «+ Шар» зависає посеред рядка. */
  margin-right: auto;
  font-family: var(--serif); font-size: var(--t-title); font-weight: 500;
  letter-spacing: -0.015em; line-height: 1.15;
}
/* «+ Шар» у шапці аркуша: єдина жовта пляма на екрані шарів, бо це єдина дія,
   з якої там усе починається. */
.is-mobile .m-add {
  flex: none;
  min-height: 40px; padding: 0 var(--s4); border-radius: var(--r-pill);
  background: var(--signal); border: none; color: var(--void);
  font-family: var(--mono); font-size: var(--t-tag); font-weight: 600;
  letter-spacing: 0.02em; white-space: nowrap;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  position: relative;
}
.is-mobile .m-add::after { content: ''; position: absolute; inset: -4px; }
.is-mobile .m-add[hidden] { display: none; }
.is-mobile .m-add:active { transform: scale(0.94); }
/* Лічильник лишається сам, тож рядок під сегментами стає підписом, а не
   смугою з кнопкою. */
.is-mobile .lyr-bar { display: block; padding: 0; }
.is-mobile .m-x {
  flex: none;
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.09); border: none;
  color: var(--ink-2); cursor: pointer;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  position: relative;
}
.is-mobile .m-x::after { content: ''; position: absolute; inset: -6px; }
.is-mobile .m-x svg {
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round;
}
.is-mobile .m-x:active { background: rgba(255, 255, 255, 0.16); }

/* Сегменти всередині аркуша. Шари, свої файли й пояснення — три відповіді на
   одне питання, тож вони живуть в одній панелі. Окремими вкладками внизу вони
   змагалися б за місце з мапою й аналітикою, які потрібні частіше. */
.is-mobile .m-seg {
  flex: none; display: flex; gap: 2px; margin: 0 var(--s4) var(--s3);
  padding: 3px; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
}
.is-mobile .m-seg[hidden] { display: none; }
.is-mobile .m-seg button {
  flex: 1; min-width: 0; height: 38px; padding: 0 var(--s2);
  position: relative;
  border: none; border-radius: var(--r-pill); background: none; cursor: pointer;
  color: var(--ink-2);
  font-family: var(--mono); font-size: var(--t-tag); letter-spacing: 0.03em;
  text-transform: uppercase; white-space: nowrap;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  transition: background 0.24s var(--spring), color 0.2s ease;
}
/* Активний сегмент — підняте скло, а НЕ жовтий блок. Жовтий у цій мапі
   означає кордон і головну дію; три жовті плями поруч (сегмент, «Додати
   шари», пігулка навігації) знецінюють його всі одразу. Тут достатньо
   різниці у висоті поверхні. */
/* Сегменти стоять упритул один до одного, тож ціль розтягується вниз і вгору
   на висоту всієї смуги-контейнера — 44 на дотик при видимих 38. */
.is-mobile .m-seg button::after {
  content: ''; position: absolute; left: 0; right: 0; top: -3px; bottom: -3px;
}
.is-mobile .m-seg button.on {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 1px 3px rgba(0, 0, 0, 0.35);
}

.is-mobile .m-sheet-body {
  flex: 1; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  touch-action: pan-y; -webkit-overflow-scrolling: touch;
  /* Тіло закінчується там, де закінчується ЕКРАН, а не аркуш.

     Аркуш завжди повної висоти, а на половинному детенті його нижня частина
     за екраном. Раніше цю частину дописували тілу як відступ — щоб кінець
     списку можна було догорнути у видиму зону. Працювало, але ціною
     чотирьохсот пікселів порожнечі: догорнувши до кінця будь-якої панелі,
     людина опинялася у велетенській пустці, бо відступ нікуди не дівався.

     Тепер тіло просто коротше рівно на ту саму величину — його низ збігається
     з низом екрана. Догортати нема куди, порожнечі немає, а знизу лишається
     тільки запас під острів навігації. */
  margin-bottom: var(--m-off, 0px);
  padding: 0 var(--s4) calc(var(--nav-space) + var(--s6));
}

.is-mobile .m-sheet-body .console-body:not([hidden]) {
  display: flex;
  padding: 0; gap: var(--s5); animation: none;
  overflow: visible; height: auto;
}

/* Легенда переїхала з мапи в аркуш, а клас .overlay несе з собою
   position: absolute — усередині аркуша вона просто зникала за його межами.
   display теж явно: на вузькому екрані її ховає правило зі style.css. */
.is-mobile .m-about .legend {
  display: block; position: static; width: auto; max-width: none;
  background: none; border: none; box-shadow: none; padding: 0;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.is-mobile .m-about .legend-toggle { display: none; }
/* max-height ставить інлайном fitLegend() (app.js) для легенди на мапі; в
   аркуші її прокручує сам аркуш. */
.is-mobile .m-about .legend-body { display: block; font-size: var(--t-meta); max-height: none !important; overflow: visible; }
.is-mobile .m-about .legend-row { line-height: 1.85; }
.is-mobile .m-about #note-mobile { font-size: var(--t-body); line-height: 1.55; }

/* Панель пошуку: поле велике, під палець, і одразу під ним результати. */
.is-mobile .m-find .finder { width: 100%; position: relative; }
.is-mobile .m-find .finder input {
  width: 100%;
  /* 16 пікселів — не про вигляд: нижче цього iOS сам наближає сторінку на
     фокусі поля, і повернути її назад людина вже не може. */
  font-size: var(--t-lede); padding: var(--s3) var(--s4);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid transparent; border-radius: var(--r-s);
  backdrop-filter: none;
}
.is-mobile .m-find .finder input:focus {
  background: rgba(255, 255, 255, 0.1);
  border-color: color-mix(in srgb, var(--signal) 55%, transparent);
}
.is-mobile .m-find .finder-results {
  position: static; margin-top: var(--s3);
  max-height: none; overflow: visible;
  background: none; border: none; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.is-mobile .m-find .finder-hit {
  padding: var(--s3) var(--s2); font-size: var(--t-body);
  min-height: 48px; border-radius: var(--r-s);
}
.is-mobile .m-find .finder-hit .h-meta { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .m-find .finder-group {
  padding: var(--s3) var(--s2) var(--s1); font-size: var(--t-tag);
  color: var(--ink-dim);
}
.is-mobile .m-find .finder-empty { padding: var(--s3) var(--s2); font-size: var(--t-body); }
/* Підпис зникає, щойно з'явилися результати. */
.is-mobile .m-find-hint { padding: var(--s3) var(--s2); }
.is-mobile .m-find:has(.finder-results:not([hidden])) .m-find-hint { display: none; }

/* ────────────────────────────────────────────── 7. накладки над мапою */

/* Шкала градієнта. Розгорнута вона займає чверть екрана — на настільному це
   смужка збоку, тут це чверть мапи назавжди. Тому видно заголовок і саму
   шкалу, а застереження розкриваються тапом: сховати їх зовсім не можна,
   вони пояснюють, чого цим кольорам не варто вірити буквально. */
.is-mobile .scale {
  left: var(--s3); right: var(--s3); width: auto; max-width: none;
  bottom: var(--nav-space);
  padding: var(--s3) 44px var(--s3) var(--s4); border-radius: var(--r-m);
  font-size: var(--t-tag); color: var(--ink-2);
}
.is-mobile .scale:not(.is-open) .scale-note { display: none; }
/* Згорнута шкала — смужка 28 px: «0 ▬▬▬ ≥ 1 500» в один рядок. Разом з
   островом навігації вона колись з'їдала ≈155 px низу екрана: заголовок,
   смуга й поділки трьома рядками. Заголовок і середня поділка з'являються
   на розгортанні; крайні числа лишаються, бо без них колір нічого не каже. */
.is-mobile .scale:not(.is-open) {
  display: flex !important; align-items: center; gap: var(--s2);
  height: 28px; padding: 0 36px 0 var(--s3); border-radius: var(--r-pill);
}
.is-mobile .scale[style*="display: none"] { display: none !important; }
.is-mobile .scale:not(.is-open) .scale-title { display: none; }
.is-mobile .scale:not(.is-open) .scale-bar { flex: 1; order: 1; height: 6px; }
.is-mobile .scale:not(.is-open) .scale-ticks { display: contents; }
.is-mobile .scale:not(.is-open) .scale-ticks span { order: 0; flex: none; }
.is-mobile .scale:not(.is-open) .scale-ticks span:nth-child(2) { display: none; }
.is-mobile .scale:not(.is-open) .scale-ticks span:last-child { order: 2; }
/* Без смуги (у вибірці немає справ) згорнута шкала — лише заголовок. */
.is-mobile .scale:not(.is-open):not(:has(.scale-bar)) .scale-title { display: block; }
.is-mobile .scale:not(.is-open)::after { top: 8px; right: 14px; width: 7px; height: 7px; }
.is-mobile .scale.is-open { max-height: 42dvh; overflow-y: auto; touch-action: pan-y; }
.is-mobile .scale::after {
  content: ''; position: absolute; top: 14px; right: 16px;
  width: 9px; height: 9px; border-right: 1.5px solid var(--ink-2);
  border-bottom: 1.5px solid var(--ink-2); transform: rotate(45deg);
  transition: transform 0.36s var(--spring);
}
.is-mobile .scale.is-open::after { transform: rotate(-135deg); }
.is-mobile .scale-title { font-size: var(--t-tag); }
/* Числа під самою шкалою — це її вісь, а не службовий підпис: без них колір
   нічого не означає. 9.5 px з базового аркуша тут замало. */
.is-mobile .scale-ticks span { font-size: var(--t-tag); }
.is-mobile .scale-note { font-size: var(--t-tag); color: var(--ink-dim); line-height: 1.6; }

.is-mobile .leaflet-control-zoom,
.is-mobile .dash-call,
.is-mobile #note { display: none; }
.is-mobile #note-mobile { display: block; }

/* Атрибуцію OpenStreetMap і Esri прибрати не можна — це умова обох сервісів.
   Але й віддавати їй смугу через увесь екран нема за що: згортаємо у значок,
   який розкривається тапом. */
.is-mobile .leaflet-control-attribution {
  bottom: calc(var(--nav-space) - 6px) !important;
  right: calc(var(--s3) + 2px) !important;
  font-size: 9px; max-width: 26px; height: 26px; overflow: hidden;
  border-radius: 13px; padding: 0 !important;
  background: var(--g-low-bg) !important;
  -webkit-backdrop-filter: var(--g-low-fx); backdrop-filter: var(--g-low-fx);
  border: var(--hair);
  transition: max-width 0.2s ease;
}
.is-mobile .leaflet-control-attribution::before {
  content: 'i'; display: block; width: 24px; line-height: 24px;
  text-align: center; font-family: var(--serif); font-style: italic;
  font-size: var(--t-meta); color: var(--ink-2);
}
.is-mobile .leaflet-control-attribution.open {
  max-width: calc(100vw - var(--s6)); height: auto;
  padding: var(--s1) var(--s2) !important; border-radius: var(--r-s);
}
.is-mobile .leaflet-control-attribution.open::before { display: none; }
.is-mobile .leaflet-control-attribution > * { display: none; }
.is-mobile .leaflet-control-attribution.open > * { display: inline; }

/* Досьє об'єкта — аркуш знизу, а не картка збоку: збоку на телефоні немає. */
.is-mobile .dossier {
  left: var(--s3); right: var(--s3); top: auto; width: auto;
  bottom: var(--nav-space);
  max-height: 54dvh; border-radius: var(--r-l);
  padding: var(--s4) var(--s4) var(--s5);
  touch-action: pan-y;
  /* Без fill-mode: кінцевий стан анімації дорівнює природному, а лишати після
     неї обчислений transform не варто — він робить блок контейнером для всього
     всередині й вимикає скло в дітей. */
  animation: m-rise 0.42s var(--spring);
}
/* Досьє й шкала прибиті до однієї лінії над навігацією, тобто налазять одне на
   одне. Коли відкрито досьє, шкала йде: досьє показує конкретний обʼєкт, шкала
   — загальний фон, і в цю мить потрібне перше. Сусідній селектор працює, бо
   #dossier стоїть у розмітці перед #scale. */
.is-mobile #dossier:not([hidden]) ~ #scale { display: none; }
@keyframes m-rise {
  from { transform: translateY(16px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
.is-mobile .dossier-close {
  position: relative;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.09);
  display: flex; align-items: center; justify-content: center;
}
.is-mobile .dossier-close::after { content: ''; position: absolute; inset: -6px; }

/* transform скидається явно: базове правило центрує смужку через
   translateX(-50%) при left: 50%. Ми міняємо left на 12px, а зсув лишався б —
   смужка їхала б на пів своєї ширини за лівий край екрана. */
.is-mobile .draw-hud {
  left: var(--s3); right: var(--s3); width: auto; transform: none;
  bottom: var(--nav-space); border-radius: var(--r-m); padding: var(--s3);
}
.is-mobile .draw-hud .ghost { padding: var(--s3) var(--s4); font-size: var(--t-meta); }

/* Попапи Leaflet: пальцем у хрестик 12×12 не влучити. */
.is-mobile .leaflet-popup-content-wrapper { border-radius: var(--r-m); }
.is-mobile .leaflet-popup-content { font-size: var(--t-body); margin: var(--s3) var(--s4); }
.is-mobile .leaflet-popup-close-button {
  width: 44px !important; height: 44px !important;
  font-size: 22px !important; padding: 10px 0 0 !important;
}
.is-mobile .leaflet-popup-tip { background: var(--g-low-bg); }

/* ─────────────────────────────────── 8. повні екрани: каталог і аналітика */

/* Модальне вікно на телефоні перестає бути вікном: «поверх мапи» тут не
   працює, бо на 390 пікселях від мапи під вікном лишається рамка. Тому це
   окремий екран — суцільним тлом, під островом навігації, який лишається на
   місці й веде далі. */
.is-mobile .modal {
  padding: 0; display: block;
  background: var(--void); backdrop-filter: none;
}
.is-mobile .modal[hidden] { display: none; }
.is-mobile .modal-box {
  width: 100%; max-width: none; height: 100%; max-height: none;
  border: none; border-radius: 0; box-shadow: none;
  background: var(--void);
}

.is-mobile .modal-top {
  position: relative; flex: none;
  flex-direction: column; align-items: stretch; gap: var(--s1);
  padding: calc(var(--safe-t) + var(--s4)) var(--s4) var(--s3);
  background: var(--g-mid-bg);
  -webkit-backdrop-filter: var(--g-mid-fx); backdrop-filter: var(--g-mid-fx);
  border-bottom: 1px solid var(--rule);
}
.is-mobile .modal-top h2 {
  font-size: var(--t-title); padding-right: 96px; line-height: 1.15;
}
.is-mobile .modal-top p { font-size: var(--t-meta); max-width: none; color: var(--ink-dim); }
.is-mobile .modal-top > div { display: flex; flex-direction: column; }
/* «Готово» — на рівні заголовка, а не окремим рядком під ним. */
.is-mobile .modal-top > button,
.is-mobile .dash-box .modal-top > button {
  position: absolute; top: calc(var(--safe-t) + var(--s2));
  right: var(--s4);
  margin: 0; min-height: 44px; padding: 0 var(--s5);
  font-size: var(--t-meta); border-radius: var(--r-pill);
}

/* Пояснення в шапці каталогу («клац по картці вмикає шар…») на телефоні
   з'їдало чотири рядки нерухомої шапки — сто пікселів із 812 назавжди. Тут
   воно й не потрібне: у кожної картки є смужка з написом, що саме станеться,
   а «у проєкті» видно жовтим. Дію показує сама дія. */
.is-mobile #catalog .modal-top p { display: none; }

.is-mobile .cat-search {
  width: 100%; max-width: none; margin: var(--s3) 0 0;
  border-radius: var(--r-s); background: rgba(255, 255, 255, 0.07);
  border-color: transparent; padding: 0 var(--s4);
}
.is-mobile .cat-search input { font-size: var(--t-lede); padding: var(--s3) 0; }

.is-mobile .cat-chips {
  overflow-x: auto; flex-wrap: nowrap; touch-action: pan-x;
  padding: var(--s3) var(--s4); gap: var(--s2); scrollbar-width: none;
}
.is-mobile .cat-chips::-webkit-scrollbar { display: none; }
.is-mobile .cat-chips button {
  flex: none; min-height: 40px; padding: 0 var(--s4);
  border-radius: var(--r-pill); font-size: var(--t-tag);
}

.is-mobile .cat-grid {
  grid-template-columns: 1fr; gap: var(--s3);
  padding: 0 var(--s4) var(--s6); touch-action: pan-y;
}
.is-mobile .card { border-radius: var(--r-m); }
.is-mobile .card-art { height: 132px; }
.is-mobile .card-txt { padding: var(--s3) var(--s4) var(--s4); }
/* Смужка «додати / прибрати з проєкту» — головна дія картки, і вона мала
   33 пікселі висоти. Дрібні підписи піднято до нижньої межі читабельності:
   на 9 пікселях у русі не читається нічого. */
.is-mobile .card-act { min-height: 48px; font-size: var(--t-meta); }
.is-mobile .cat-group { font-size: var(--t-tag); }
.is-mobile .card-flag,
.is-mobile .card-n { font-size: var(--t-tag); }
.is-mobile .card-src { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .card-txt h3 { font-size: var(--t-lede); }
.is-mobile .card-blurb { font-size: var(--t-meta); line-height: 1.5; }
.is-mobile .card-about,
.is-mobile .card-stat { font-size: var(--t-meta); line-height: 1.55; }
/* Обкладинка картки — не ілюстрація, а сама геометрія шару, і на телефоні
   вона все одно менша за настільну. Зате чипи розділів у каталозі мусять
   бути пальцевими. */
.is-mobile .cat-count { font-size: var(--t-tag); }
.is-mobile .modal-foot {
  padding: var(--s3) var(--s4) calc(var(--nav-space) + var(--s1));
  background: var(--g-mid-bg);
  -webkit-backdrop-filter: var(--g-mid-fx); backdrop-filter: var(--g-mid-fx);
}

/* ── аналітика: не сітка, а стрічка з власним змістом ──────────────────

   Виміряні висоти рядів (fitDash) на телефоні не мають сенсу: колонка одна,
   тобто ряд — це один блок, і «висота за найбільшим у ряду» перетворюється
   на «висота за самим собою». Тому mobile.js просить її не рахувати, а блоки
   ростуть під свій вміст. Прокрутка лишається одна — сторінки. */
.is-mobile .dash-grid {
  /* position: relative — не косметика. offsetTop у блоків рахується від
     найближчого позиційованого предка; без цього він включав висоту шапки й
     меню розділів, і підсвічений розділ ВІДСТАВАВ від того, що на екрані:
     читаєш «Річку проти суходолу», а підсвічено «Групові події». */
  position: relative;
  display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s3) var(--s4) calc(var(--nav-space) + var(--s5));
  touch-action: pan-y;
}
.is-mobile .dash-grid > .unit {
  grid-column: auto !important;
  /* flex: none — не косметика. У стовпці з прокруткою елементи за
     замовчуванням СТИСКАЮТЬСЯ, коли їхня сума не влазить у контейнер, і
     кожен блок сплющився б до свого заголовка, а вміст поліз би на сусідів. */
  flex: none;
  height: auto !important; min-height: 0; max-height: none;
  border-radius: var(--r-m); padding: var(--s4);
  background: var(--panel-2); overflow: visible;
}

/* А тут — пастка, через яку блоки спершу виявилися порожніми.

   У настільній сітці клітинка має ЗАДАНУ висоту (її рахує fitDash), і вміст
   ділить її між собою: основне отримує flex-basis 0, тобто «претендую тільки
   на вільне місце». На телефоні висоту дає вміст — і flex-basis 0 означає вже
   зовсім інше: «моя власна висота нуль». Графіки чесно ставали нульовими.

   Ланцюжок :not повторено навмисно: без нього правило програє тому, яке
   виправляє, — п'ять класів усередині :not() дають йому вагу. */
.is-mobile .dash-grid > .unit > :not(.unit-head):not(.fine):not(.choice):not(.axis):not(.pager),
.is-mobile .dash-grid > .unit > .fine {
  flex: none; min-height: 0; max-height: none; overflow: visible;
}
/* Убік екран не їде НІКОЛИ. .dash-grid — контейнер прокрутки, і варто
   одному блоку вилізти за ширину, як уся аналітика починає гортатися вбік:
   людина промахується пальцем і бачить порожнє поле збоку замість тексту.
   Тому впоперек тут заборонено, а те, що справді ширше, полагоджено нижче. */
.is-mobile .dash-grid { overflow-x: hidden; }

/* Таблиця «двох лічильників»: підпис і число на 341 пікселі поруч не стають.
   Рядок стає гнучким — число зісковзує під підпис і лишається праворуч.
   Саме цей блок, а не всі таблиці: у «річка проти суходолу» три колонки, і
   там перебудова зруйнувала б порівняння. */
.is-mobile #halves table,
.is-mobile #halves tbody { display: block; width: 100%; }
.is-mobile #halves tr {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0 var(--s3); padding: var(--s1) 0;
}
.is-mobile #halves td { display: block; }
.is-mobile #halves td:last-child { margin-left: auto; font-family: var(--mono); }

/* Хронологія ширша за блок на кілька пікселів через фіксовану вісь. */
.is-mobile .dash-grid .tl { overflow-x: auto; }
/* Назва суду довша за колонку — обрізаємо крапками, а не ламаємо сітку. */
.is-mobile .courts .court-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.is-mobile .dash-grid .unit-head { flex-wrap: wrap; gap: var(--s1) var(--s3); }
.is-mobile .dash-grid .unit-label { font-size: var(--t-tag); }
.is-mobile .dash-grid .unit-value { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .dash-grid .fine { font-size: var(--t-meta); line-height: 1.6; color: var(--ink-dim); }
/* Графікам на телефоні потрібна більша висота: ширина в них удвічі менша. */
.is-mobile .dash-grid .timeline,
.is-mobile .dash-grid .hours,
.is-mobile .dash-grid .hours.dist { min-height: 130px; }
.is-mobile .dash-grid .tl { min-height: 0; }
.is-mobile .dash-grid .prose { font-size: var(--t-body); line-height: 1.55; }

/* Нижня межа кегля в аналітиці. У боковій колонці настільної версії ці 9–10
   пікселів були виправдані шириною; тут блок на весь екран, місця вистачає, а
   дрібне — це не службовий текст, а самі дані: підписи осей, номери в
   рейтингу, дати джерел, відсотки штрафів по судах. Перелік поіменний, бо
   font-size не вміє «не менше за власне значення». */
.is-mobile .dash-grid .tl-axis span,
.is-mobile .dash-grid .tl-label,
.is-mobile .dash-grid .axis span,
.is-mobile .dash-grid .season-n,
.is-mobile .dash-grid .season-k,
.is-mobile .dash-grid .ev-meta,
.is-mobile .dash-grid .rank,
.is-mobile .dash-grid .src-when,
.is-mobile .dash-grid .court-pct,
.is-mobile .dash-grid .court-n,
.is-mobile .dash-grid .ro-year span,
.is-mobile .dash-grid .ro-year b,
.is-mobile .dash-grid .aid-head span,
.is-mobile .dash-grid .ranking .n,
.is-mobile .dash-grid th,
.is-mobile .dash-grid td,
.is-mobile .dash-grid .chip { font-size: var(--t-tag); }

/* Ряди, по яких клацають: суд, місце затримання, групова подія. Це не текст,
   а керування — клац по суду лишає на мапі тільки його справи. */
.is-mobile .court-row,
.is-mobile .ranking li,
.is-mobile .events .ev,
.is-mobile .aid-list .aid { min-height: 44px; }

/* Меню розділів: те, заради чого аналітика на телефоні — окремий екран, а не
   вікно. Гортається вбік, підсвічує розділ, у якому зараз читач. */
.is-mobile .m-dash-nav {
  flex: none; display: flex; gap: var(--s2);
  overflow-x: auto; touch-action: pan-x; scrollbar-width: none;
  padding: var(--s3) var(--s4);
  background: var(--g-mid-bg);
  -webkit-backdrop-filter: var(--g-mid-fx); backdrop-filter: var(--g-mid-fx);
  border-bottom: 1px solid var(--rule);
}
.is-mobile .m-dash-nav::-webkit-scrollbar { display: none; }
/* Той самий прийом, що й у числах угорі: край, який гортається, згасає, а не
   обривається на півслові. */
.is-mobile .m-dash-nav {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
}
.is-mobile .m-dash-nav button {
  position: relative;
  flex: none; min-height: 40px; padding: 0 var(--s4); border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid transparent; color: var(--ink-2);
  font-family: var(--mono); font-size: var(--t-tag); letter-spacing: 0.02em;
  white-space: nowrap; cursor: pointer; touch-action: manipulation;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}
.is-mobile .m-dash-nav button::after {
  content: ''; position: absolute; left: 0; right: 0; top: -6px; bottom: -6px;
}
.is-mobile .m-dash-nav button.on {
  color: var(--signal);
  background: color-mix(in srgb, var(--signal) 12%, transparent);
  border-color: color-mix(in srgb, var(--signal) 34%, transparent);
}
.is-mobile .m-dash-lede { padding: 0 2px var(--s1); }

/* ── перелік справ: картки замість таблиці ────────────────────────────

   Вісім колонок на 390 пікселях не поміщаються ні в якому вигляді. Але
   розмітку таблиці міняти не можна — її будує app.js і на неї ж вішає
   обробники. Тож міняємо не розмітку, а спосіб показу: рядок стає карткою,
   комірки — рядками в ній. Дані ті самі, обробники ті самі.

   Ряди й колонки задані поіменно: автоматичне розміщення ставить кожну
   комірку в новий рядок, бо в DOM місце йде перед напрямком. */
.is-mobile #casesUnit .cases-body { max-height: none; height: auto; overflow: visible; }
.is-mobile #list,
.is-mobile #list tbody { display: block; width: 100%; }
.is-mobile #list tr {
  display: grid; grid-template-columns: auto 1fr auto;
  gap: var(--s1) var(--s2);
  padding: var(--s3) var(--s4); margin-bottom: var(--s2);
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: var(--r-m);
}
.is-mobile #list tr.reading {
  border-color: color-mix(in srgb, var(--signal) 55%, transparent);
  background: color-mix(in srgb, var(--signal) 7%, var(--panel));
}
/* white-space скидається явно. Базове `td { white-space: nowrap }` зі
   style.css діє й тут, а назви судів бувають по 57 знаків («Івано-Франківський
   міський суд Івано-Франківської області» — app.js ріже лише «районний» і
   «міськрайонний»). Без переносу така назва виїжджає за картку й мовчки
   обрізається, без жодного знаку, що там є продовження. */
.is-mobile #list td {
  display: block; border: none; padding: 0;
  white-space: normal; overflow-wrap: anywhere;
}
.is-mobile #list td.when,
.is-mobile #list td.no { white-space: nowrap; }
.is-mobile #list td.when {
  grid-column: 1; grid-row: 1;
  font-family: var(--mono); font-size: var(--t-tag); color: var(--ink-2);
}
.is-mobile #list td:nth-child(3) { grid-column: 2; grid-row: 1; justify-self: start; }
.is-mobile #list td.place {
  grid-column: 1 / 3; grid-row: 2;
  font-size: var(--t-lede); color: var(--ink); line-height: 1.3;
}
.is-mobile #list td:nth-child(4) { grid-column: 1 / 3; grid-row: 3; font-size: var(--t-meta); }
.is-mobile #list td:nth-child(5) {
  grid-column: 1 / 3; grid-row: 4; font-size: var(--t-meta); color: var(--ink-dim);
}
.is-mobile #list td.no {
  grid-column: 1 / 3; grid-row: 5;
  font-family: var(--mono); font-size: var(--t-tag); color: var(--ink-dim);
}
.is-mobile #list td.go { grid-column: 3; grid-row: 1 / 6; align-self: center; width: auto; }
.is-mobile #list td.go button { width: 44px; height: 44px; font-size: 18px; }
/* Уривок тексту в картці зайвий: він і є те, заради чого відкривають справу. */
.is-mobile #list td.wide { display: none; }

.is-mobile .cases-tools { display: flex; flex-wrap: wrap; gap: var(--s2); width: 100%; }
.is-mobile .cases-tools input[type="search"] {
  flex: 1 1 100%; font-size: var(--t-lede); padding: var(--s3) var(--s4);
  border-radius: var(--r-s);
}
.is-mobile .cases-tools select {
  font-size: var(--t-body); min-height: 44px; padding: 0 var(--s3);
  border-radius: var(--r-s);
}
.is-mobile .cases-tools .ghost { min-height: 44px; padding: 0 var(--s4); }

.is-mobile .pager { flex-wrap: wrap; gap: var(--s2); padding-top: var(--s3); }
.is-mobile .pager button {
  min-height: 44px; min-width: 44px; padding: 0 var(--s4); font-size: var(--t-meta);
}
.is-mobile .pager-info { flex: 1 1 100%; text-align: center; font-size: var(--t-tag); }

/* ────────────────────────────────────────────── 9. читач справи */

.is-mobile .reader {
  inset: 0; width: 100%; max-width: none; z-index: 4600;
  border-left: none; padding-top: var(--safe-t); background: var(--void);
}
.is-mobile .reader-top { padding: var(--s3) var(--s4); gap: var(--s3); }
.is-mobile .reader-id { font-size: var(--t-meta); }
.is-mobile .reader-x {
  position: relative;
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.09);
  display: flex; align-items: center; justify-content: center;
}
.is-mobile .reader-x::after { content: ''; position: absolute; inset: -5px; }
.is-mobile .reader-meta {
  max-height: 34dvh; overflow-y: auto; touch-action: pan-y;
  padding: var(--s3) var(--s4);
}
.is-mobile .reader-meta dd { font-size: var(--t-meta); }
.is-mobile .reader-snip { font-size: var(--t-meta); line-height: 1.6; }
.is-mobile .reader-foot {
  padding: var(--s3) var(--s3) calc(var(--safe-b) + var(--s3));
  flex-wrap: wrap; gap: var(--s2);
}
.is-mobile .reader-foot button {
  min-height: 44px; padding: 0 var(--s4); font-size: var(--t-meta);
}
.is-mobile .reader-foot a { min-height: 44px; display: flex; align-items: center; }

/* Сторінка реєстру має фіксовану ширину 1000 пікселів. Вписана в 390 вона
   стає 39-відсотковою, тобто нечитабельною. Тому на телефоні читач дає
   масштаб руками: «за шириною» для огляду, «100%» для читання з поперечною
   прокруткою. Змінити саму сторінку зсередини не можна — вона чужа. */
.is-mobile .reader-frame { overflow: auto; touch-action: pan-x pan-y; }
/* Перемикач масштабу — окремим рядком над ногою, у потоці (mobile.js
   вставляє його перед .reader-foot). Колись він стояв absolute на bottom
   76px і на вузькому екрані, де нога переносилася в два рядки, накривав
   «наступна →». */
.is-mobile .reader .m-zoom {
  position: static; flex: none; align-self: flex-end;
  margin: var(--s2) var(--s4) 0;
  display: flex; gap: 2px; padding: 3px; border-radius: var(--r-pill);
  background: var(--g-top-bg);
  -webkit-backdrop-filter: var(--g-top-fx); backdrop-filter: var(--g-top-fx);
  border: var(--hair); box-shadow: var(--rim), var(--cast);
}
.is-mobile .m-zoom button {
  position: relative;
  min-height: 40px; padding: 0 var(--s4); border-radius: var(--r-pill);
  background: none; border: none; color: var(--ink-2);
  font-family: var(--mono); font-size: var(--t-tag); cursor: pointer;
  touch-action: manipulation;
}
.is-mobile .m-zoom button::after {
  content: ''; position: absolute; left: 0; right: 0; top: -5px; bottom: -5px;
}
.is-mobile .m-zoom button.on { background: rgba(255, 255, 255, 0.12); color: var(--signal); }

/* ────────────────────────────────────────────── 10. асистент */

.is-mobile .ai-panel {
  inset: 0; width: 100%; max-width: none; z-index: 4000;
  /* Поле вводу має стояти НАД клавіатурою, а не під нею. */
  height: calc(100dvh - var(--kb, 0px));
  border: none; border-radius: 0;
  padding-top: var(--safe-t); background: var(--void);
}
.is-mobile .ai-top { padding: var(--s3) var(--s4); }
.is-mobile .ai-log { padding: var(--s4); touch-action: pan-y; }
.is-mobile .ai-msg { font-size: var(--t-body); line-height: 1.55; }
.is-mobile .ai-sug { padding: 0 var(--s4) var(--s2); gap: var(--s2); }
.is-mobile .ai-sug button {
  font-size: var(--t-meta); min-height: 44px; padding: var(--s2) var(--s4);
  border-radius: var(--r-s); text-align: left;
}
.is-mobile .ai-form { padding: var(--s2) var(--s3); gap: var(--s2); }
.is-mobile .ai-form textarea {
  font-size: var(--t-lede); padding: var(--s3) var(--s4); border-radius: var(--r-m);
}
.is-mobile .ai-form button[type="submit"] {
  width: 46px; height: 46px; border-radius: 50%; flex: none;
}
.is-mobile .ai-note {
  padding: 0 var(--s4) calc(var(--nav-space) + var(--s1));
  font-size: var(--t-tag); color: var(--ink-dim); line-height: 1.55;
}

/* ────────────────────────────────────────────── 11. пальцеві цілі

   44 пікселі беруться не зі стелі: це та сама межа, з якої почали і Apple, і
   Google, і вона приблизно дорівнює подушечці пальця. Там, де малювати таку
   кнопку було б грубо, візуальний розмір лишається меншим, а ціль
   розширюється невидимим ::after. */

.is-mobile button,
.is-mobile .tag,
.is-mobile label.lyr {
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}

.is-mobile .choice button,
.is-mobile .toggle-pair button {
  min-height: 44px; padding: 0 var(--s2); font-size: var(--t-meta);
}
.is-mobile .pills button,
.is-mobile .tag {
  min-height: 44px; padding: 0 var(--s4); font-size: var(--t-meta);
  display: inline-flex; align-items: center;
}
/* «+» і «−» біля вибору робочого простору: висота була 44, а ширина 34 —
   ціль мусить бути пальцевою в обидва боки. */
.is-mobile .ws-row button { min-width: 44px; }
.is-mobile .ws-row select,
.is-mobile .ws-row input { min-height: 44px; }
.is-mobile .ghost { min-height: 44px; padding: 0 var(--s4); font-size: var(--t-meta); }
.is-mobile .prime { min-height: 48px; padding: 0 var(--s5); font-size: var(--t-body); }
.is-mobile .clear { min-height: 44px; }
.is-mobile .lyr { padding: var(--s2) 0; min-height: 48px; }
.is-mobile .lyr input { width: 22px; height: 22px; flex: none; }

/* Повзунки періоду: доріжка тонка, а бігунок має бути пальцевим. */
.is-mobile input[type="range"] { height: 34px; }
.is-mobile input[type="range"]::-webkit-slider-thumb { width: 24px; height: 24px; }

/* Рядок активного шару стає двоповерховим.

   В один рядок він не влазить за арифметикою, а не за смаком: чотири кнопки
   по 44 пікселі — це 176 із 341, і назві лишається сто. «Затримання з…» —
   не назва. Тому зверху те, що читають (позначка, назва, число), знизу те,
   чим керують: ліворуч порядок і видимість, праворуч налаштування й
   прибрати. Кнопки нарешті пальцеві, назва нарешті ціла.

   Ціль ще й ширша за видиму кнопку: ::after додає по чотири пікселі з боків,
   рівно половину проміжку, тож сусідні цілі стикаються без мертвих зон. */
.is-mobile .ly-row .row-head {
  display: grid;
  grid-template-columns: 40px 40px 1fr auto 40px 40px;
  align-items: center;
  gap: var(--s1);
  padding: var(--s2) var(--s1);
}
/* Кнопки другого поверху отримують видиму поверхню. Без неї ⠿ і ● читаються
   як позначки стану, а не як те, що можна натиснути: у порожньому рядку
   дрібний значок без рамки не виглядає кнопкою. */
.is-mobile .ly-row .row-head > button {
  position: relative; min-width: 40px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-s); font-size: 14px;
  background: rgba(255, 255, 255, 0.05); color: var(--ink-2);
}
.is-mobile .ly-row .row-head > button:active { background: rgba(255, 255, 255, 0.12); }
.is-mobile .ly-row .row-x:active { color: var(--alert); }
.is-mobile .ly-row .row-head > button::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: -4px; right: -4px;
}
.is-mobile .row-head .ly-sw    { grid-column: 1; grid-row: 1; justify-self: center; }
.is-mobile .row-head .row-name { grid-column: 2 / 5; grid-row: 1; }
.is-mobile .row-head .row-n    { grid-column: 5 / 7; grid-row: 1; text-align: right; }
.is-mobile .row-head .row-grip { grid-column: 1; grid-row: 2; }
.is-mobile .row-head .row-eye  { grid-column: 2; grid-row: 2; }
.is-mobile .row-head .row-cog  { grid-column: 5; grid-row: 2; }
.is-mobile .row-head .row-x    { grid-column: 6; grid-row: 2; }

/* Вибір підкладки: смужка на 30 пікселів не вціляється. */
.is-mobile .basemaps button { min-height: 44px; font-size: var(--t-meta); }
.is-mobile .stack-title { font-size: var(--t-tag); }
.is-mobile .clear { font-size: var(--t-meta); }
.is-mobile .ly-row .row-name { font-size: var(--t-body); }
.is-mobile .ly-row .row-n { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .ly-row .row-about,
.is-mobile .ly-row .row-stat { font-size: var(--t-meta); line-height: 1.6; }
.is-mobile .ly-row .row-src { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .lyr-bar { gap: var(--s3); }
.is-mobile .lyr-bar-n { font-size: var(--t-meta); }

.is-mobile .unit-label { font-size: var(--t-tag); }
.is-mobile .unit-value { font-size: var(--t-tag); color: var(--ink-dim); }
.is-mobile .fine { font-size: var(--t-meta); line-height: 1.6; color: var(--ink-dim); }
.is-mobile .set-lab { font-size: var(--t-meta); }
.is-mobile .set-note { font-size: var(--t-tag); color: var(--ink-dim); line-height: 1.55; }

/* Кнопки біля імпортованих файлів: 20×20 у базі, а збільшення до 34 живе лише
   в медіазапиті на 760 — тобто в горизонтальній орієнтації телефона (844 px)
   його немає саме там, де палець нікуди не подівся. */
.is-mobile .imp-btn {
  position: relative; width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
}
.is-mobile .imp-btn::after { content: ''; position: absolute; inset: -6px; }
.is-mobile .imp { gap: var(--s2); padding: var(--s2); }

/* Підписи годин під стовпчиками — 8.5 px у базовому аркуші. Це не «дрібний
   службовий текст», це вісь графіка: без неї стовпчики не читаються. */
.is-mobile .hbar span,
.is-mobile .hours.dist .hbar span { font-size: var(--t-tag); height: auto; }

/* Поля вводу: 16 пікселів усюди, інакше iOS наближає сторінку на фокусі.
   Правило стоїть ПІСЛЯ всіх часткових (.cases-tools select тощо) — інакше
   програє їм за вагою й захист мовчки зникає саме там, де поле вужче. */
.is-mobile input[type="search"],
.is-mobile input[type="text"],
.is-mobile select,
.is-mobile textarea,
.is-mobile .cases-tools select { font-size: var(--t-lede); }

/* ────────────────────────────────────────────── асистент: цілі й порожнеча */

/* Єдиний вихід із повноекранної панелі мав 17×21 пікселя. */
.is-mobile .ai-x {
  position: relative;
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.09); color: var(--ink-2);
  font-size: var(--t-body); padding: 0;
}
.is-mobile .ai-x::after { content: ''; position: absolute; inset: -5px; }

/* «Наблизити на мапі» й оцінки відповіді — 11 px і ~20 пікселів заввишки. */
.is-mobile .ai-apply {
  position: relative; min-height: 40px; padding: 0 var(--s3);
  font-size: var(--t-meta); border-radius: var(--r-s);
  display: inline-flex; align-items: center;
}
.is-mobile .ai-apply::after { content: ''; position: absolute; inset: -4px; }
.is-mobile .ai-vote { display: flex; gap: var(--s2); }
.is-mobile .ai-src-item { font-size: var(--t-meta); line-height: 1.55; }
.is-mobile .ai-case { font-size: var(--t-tag); }
.is-mobile .ai-kind { font-size: var(--t-tag); }

/* Порожній лог — це перше, що видно у відкритій панелі: сімсот пікселів
   порожнечі над підказками. Кажемо прямо, що робити. */
.is-mobile .ai-log:empty::before {
  content: 'Ще нічого не питали. Оберіть підказку нижче або напишіть своє.';
  display: block; padding: var(--s5) var(--s2);
  font-size: var(--t-body); line-height: 1.55; color: var(--ink-dim);
}

/* Результати пошуку: підпис під назвою, а не праворуч від неї. Праворуч він
   притискався до краю й обрізався на «населений пункт · Закарпатс…». */
.is-mobile .m-find .finder-hit { flex-wrap: wrap; }
.is-mobile .m-find .finder-hit .h-meta {
  flex: 1 1 100%; text-align: left; white-space: normal;
}

/* ────────────────────────────────────────────── 12. застосунок

   Ці правила свідомо НЕ під .is-mobile: установка й оновлення однакові на
   телефоні й на настільному, а підказка про оновлення потрібна там навіть
   більше — вкладку з мапою тримають відкритою тижнями. */

.pwa-toast {
  position: fixed; z-index: 5000;
  left: 50%; bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  max-width: calc(100vw - 24px);
  padding: 8px 8px 8px 16px; border-radius: 999px;
  background: rgba(9, 12, 17, 0.86);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  backdrop-filter: saturate(180%) blur(22px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  font-size: 13px; color: var(--ink);
  animation: pwa-in 0.42s cubic-bezier(0.32, 0.72, 0, 1) both;
}
.is-mobile .pwa-toast { bottom: calc(var(--nav-space) + 8px); }
.pwa-toast.is-out { opacity: 0; transition: opacity 0.5s ease; }
.pwa-toast button {
  flex: none; min-height: 40px; padding: 0 16px; border-radius: 999px;
  background: var(--signal); border: none; color: #000;
  font-family: var(--mono); font-size: 12px; cursor: pointer;
}
@keyframes pwa-in {
  from { transform: translate(-50%, 20px); opacity: 0; }
  to   { transform: translate(-50%, 0);    opacity: 1; }
}
.pwa-install { width: 100%; justify-content: center; }

/* ────────────────────────────────────────────── 13. менше руху */

/* Системне «зменшити рух» — не побажання. Пружини стають миттєвими,
   пульсація зникає; логіка лишається тією самою. */
@media (prefers-reduced-motion: reduce) {
  .is-mobile .m-sheet,
  .is-mobile .m-pill,
  .is-mobile .m-scrim,
  .is-mobile .m-chips,
  .is-mobile .m-nav,
  .is-mobile .m-orb,
  .is-mobile .m-tab,
  .is-mobile .m-tab span,
  .is-mobile .m-tab svg,
  .is-mobile .m-mark,
  .is-mobile .m-seg button,
  .is-mobile .scale,
  .is-mobile .scale::after { transition-duration: 0.01ms; }
  .is-mobile .dossier { animation: none; }
  .is-mobile .m-tab.is-new svg { animation: none; }
  .pwa-toast { animation: none; }
}

/* ────────────────────────────────────────────── 14. краї екранів */

/* iPhone SE та інші 320-ті: капсула на чотири вкладки лишається капсулою,
   але підписи стискаються, а бічні поля зменшуються. */
@media (max-width: 360px) {
  .is-mobile { --nav-side: 12px; --nav-h: 58px; --t-tab: 9px; }
  .is-mobile .m-tab svg { width: 18px; height: 18px; }
}

/* Телефон боком: висоти майже немає. Верхня смужка зникає (числа є в
   аналітиці), аркуш відкривається одразу на повну, підписи вкладок ідуть. */
@media (orientation: landscape) and (max-height: 520px) {
  .is-mobile { --nav-h: 50px; }
  .is-mobile .m-chips { display: none; }
  .is-mobile .m-sheet { height: calc(100dvh - var(--safe-t) - 12px); }
  .is-mobile .m-tab span { display: none; }
  .is-mobile .m-tab { gap: 0; }
}

/* Рядок розкладки («скільки справ стало точками») переїжджає з правої
   напрямної на верх аркуша шарів (mobile.js). Там він не накладка поверх
   мапи, а звичайний абзац аркуша: без власного скла й рамки. */
.is-mobile .m-sheet .shown-line {
  position: static; max-width: none;
  background: none; border: 0; border-radius: 0;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  padding: 0 0 var(--s2);
  font-size: var(--t-meta); line-height: 1.55; color: var(--ink-dim);
}
.is-mobile .m-sheet .shown-line .shown-go { min-height: 0; }

/* ────────────────────────────────── 15. вихід на платформу, смуга фільтрів */

/* Коло «←» зліва від марки: мапа — модуль платформи, і дорога назад на
   Головну мусить бути видна без аркушів. Посилання, а не кнопка: це
   справжній перехід на іншу сторінку. */
.is-mobile .m-home {
  text-decoration: none; color: var(--ink); font-family: var(--sans);
  font-size: var(--t-lede); font-weight: 500;
}

/* Посилання з шапки («← до платформи», «точки затримань — nemap.fyi ↗»)
   переїжджають в аркуш «Про мапу» (mobile.js): шапки на телефоні немає. */
.is-mobile .m-about .map-links {
  display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s3);
}
.is-mobile .m-about .map-link {
  font-size: var(--t-meta); padding: var(--s2) var(--s3);
  border-radius: var(--r-pill); color: var(--ink);
  border: var(--hair); background: rgba(255, 255, 255, 0.04);
}

/* «Показано:» — під верхньою смужкою, пігулками, що гортаються вбік. Та сама
   логіка, що в m-chips: переносити рядки означало б з'їсти ще смугу мапи. */
.is-mobile .filter-chips {
  position: fixed; z-index: 1190;
  top: calc(var(--safe-t) + var(--s2) + 38px + var(--s2));
  left: var(--s3); right: var(--s3);
  min-height: 0; padding: 2px; flex-wrap: nowrap;
  overflow-x: auto; overflow-y: hidden; touch-action: pan-x;
  scrollbar-width: none; background: none; border: 0;
  transition: opacity 0.25s ease 0.08s;
}
.is-mobile .filter-chips::-webkit-scrollbar { display: none; }
.is-mobile .filter-chips .fc-lab { display: none; }
.is-mobile .filter-chips .fc,
.is-mobile .filter-chips .fc-reset {
  flex: none; min-height: 32px; font-size: var(--t-meta);
  background: var(--g-low-bg);
  -webkit-backdrop-filter: var(--g-low-fx); backdrop-filter: var(--g-low-fx);
  border: var(--hair); box-shadow: var(--rim), var(--cast);
}
.is-mobile .filter-chips .fc-reset { color: var(--signal); }
/* Коли відкрито аркуш, смуга ховається разом із числами: вона описує мапу. */
.is-mobile.has-sheet .filter-chips { opacity: 0; pointer-events: none; transition-delay: 0s; }
@media (orientation: landscape) and (max-height: 520px) {
  .is-mobile .filter-chips { top: calc(var(--safe-t) + var(--s2)); left: 64px; }
}

/* ────────────────────────────────── 16. дотик, картки, масштаб, перелік */

/* Зона дотику крапки — 44 px, а не 24: точку в 7–9 px пальцем не влучити.
   На огляді (z ≤ 8) — 24 px: там крапки стоять щільно, і велика зона
   перекривала б сусідів. Сама крапка не більшає. */
.is-mobile .z-mid .rtf-mk > .pin::after,
.is-mobile .z-hi .rtf-mk > .pin::after { width: 44px; height: 44px; }
.is-mobile .z-lo .rtf-mk > .pin::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 24px; height: 24px; transform: translate(-50%, -50%); border-radius: 50%;
}

/* Попапи, що лишилися (контур ділянки, пункт пропуску, знак) — зі стелею по
   висоті й власною прокруткою: без неї довга картка виходила за екран. */
.is-mobile .leaflet-popup-content { max-height: 46dvh; overflow-y: auto; touch-action: pan-y; }

/* Картка знака й місця — нижній аркуш над навігацією (.dossier вище). */
.is-mobile .card-pop { font-size: var(--t-body); }
.is-mobile .card-pop h3 { font-size: var(--t-lede); }
.is-mobile .card-pop dt, .is-mobile .card-pop dd { font-size: var(--t-meta); }
.is-mobile .card-pop .pop-list li { font-size: var(--t-meta); min-height: 44px; align-items: center; }
.is-mobile .card-pop .open-case { font-size: var(--t-meta); min-height: 44px; }
.is-mobile .card-acts .ghost, .is-mobile .card-back {
  min-height: 44px; font-size: var(--t-meta); border-radius: var(--r-s);
}
.is-mobile .frame-list button { min-height: 44px; font-size: var(--t-meta); }
.is-mobile .dossier .dsr { font-size: var(--t-meta); }

/* Лінійний масштаб — над смужкою шкали, не під островом навігації. */
.is-mobile .leaflet-bottom.leaflet-left {
  bottom: calc(var(--nav-space) + 28px + var(--s2));
}
.is-mobile .leaflet-control-scale { margin: 0 0 0 var(--s3) !important; }
/* Кути Leaflet лежать вище за накладки (z-index 1000), тож коли відкрита
   картка, масштаб ховається — інакше він стояв би поверх її тексту. */
.is-mobile .canvas:has(#dossier:not([hidden])) .leaflet-bottom.leaflet-left { display: none; }

/* Заголовки таблиці справ на телефоні — рядок кнопок сортування, що
   гортається вбік: самі рядки тут картки, стовпців немає. */
.is-mobile #list thead { display: block; }
.is-mobile #list thead tr {
  display: flex; gap: var(--s2); overflow-x: auto; scrollbar-width: none;
  padding: 0 0 var(--s2); margin: 0; background: none; border: 0; border-radius: 0;
}
.is-mobile #list thead tr::-webkit-scrollbar { display: none; }
.is-mobile #list thead th {
  position: static; flex: none; display: block; padding: 0; border: 0; background: none;
}
.is-mobile #list thead th:not([data-sort]) { display: none; }
.is-mobile #list thead th button {
  min-height: 36px; padding: 0 var(--s3); border-radius: var(--r-pill);
  border: var(--hair); background: rgba(255, 255, 255, 0.04);
  font-size: var(--t-tag); color: var(--ink-2);
}
.is-mobile #list thead th.on button { color: var(--signal); border-color: color-mix(in srgb, var(--signal) 40%, transparent); }
.is-mobile #list td.no .row-open { font-size: var(--t-tag); color: var(--ink-dim); min-height: 32px; }

.is-mobile .unit-static { font-size: var(--t-tag); }

@media (prefers-reduced-motion: reduce) {
  .is-mobile .reader .m-zoom,
  .is-mobile .dossier { transition: none; animation: none; }
}
.is-mobile .sr-jump { top: calc(var(--safe-t) + 56px); z-index: 1250; }
