/* Затримання на державному кордоні.
   Аркуш побудований як приладова панель: тонкі лінії, табличні цифри,
   один сигнальний колір — той самий жовтий, яким на мапі позначено кордон.

   Мапа — свідомо лише темна (<meta name="color-scheme" content="dark"> у
   mapa/index.html): жовта шкала щільності (#2a2610 → #ffd400 → #fff4b8) і
   кольори знаків підібрані під темне тло, і на світлому початок шкали зникав
   би. Вибір теми платформи (rtf.theme) тут не діє — так і сказано на
   /metodolohiia/ (розділ «Точність мапи»). */

:root {
  --void:    #06080b;
  --panel:   #0c1015;
  --panel-2: #11161d;
  --raised:  #161d26;
  --rule:    #1d2630;
  --rule-2:  #2a3542;

  --ink:     #e9eff3;
  --ink-2:   #94a3b0;
  /* Був #5d6b78 — 3,1–3,7:1 на тлі панелей, нижче норми для дрібного тексту.
     #7a8896 дає ≥ 4,6:1 і збігається з --c-muted платформи. */
  --ink-3:   #7a8896;

  /* Палітра, спільна з платформою. Джерело одне — тут; app.js читає ці
     змінні (const C), а не тримає власні копії.
       --c-border    кордон і щільність уздовж нього (одновідтінкова шкала
                     #2a2610 → #ffd400 → #fff4b8)
       --c-case      справи — одним кольором
       --c-noescape  NoEscape без справи в корпусі
       --c-muted     контекст і невизначеність
       --c-select    вибране */
  --c-border:   #ffd400;
  --c-case:     #ff5147;
  --c-noescape: #4cc3ff;
  --c-muted:    #7a8896;
  --c-select:   #ffffff;

  --signal:  #ffd400;   /* кордон і акцент — один і той самий колір */
  --ua:      #2f6fd0;
  --alert:   #ff5147;

  --ro: #f5a524;
  --md: #a78bfa;
  --hu: #38bdf8;
  --sk: #34d399;

  --mono: 'IBM Plex Mono', ui-monospace, monospace;
  --sans: 'Commissioner', system-ui, sans-serif;
  --serif: 'Literata', Georgia, serif;

  --masthead-h: 62px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

/* Три ряди: шапка, смуга «Показано:» (auto — порожня згортається в нуль) і
   мапа. Ряди задано кожному явно: коли смуга прихована, вона не стає
   елементом сітки, і без явного grid-row мапа з'їхала б у рядок auto. */
body {
  display: grid;
  grid-template-rows: var(--masthead-h) auto 1fr;
  background: var(--void);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

/* Ледь помітне зерно: без нього великі темні площини виглядають мертвими. */
.grain {
  position: fixed; inset: 0; z-index: 9999; pointer-events: none;
  opacity: 0.035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

::selection { background: var(--signal); color: #000; }

/* ─────────────────────────────────────────────────────── шапка */

.masthead {
  display: flex; align-items: center; justify-content: space-between;
  gap: 28px; padding: 0 22px;
  background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border-bottom: 1px solid var(--rule);
}

.masthead { grid-row: 1; }
.stage { grid-row: 3; }
.filter-chips { grid-row: 2; }

.ident { display: flex; align-items: center; gap: 14px; min-width: 0; }

/* Два виходи з мапи: на платформу й на nemap.fyi, де самі точки затримань. */
.map-links { display: flex; gap: 6px; flex: none; margin-left: 6px; }
.map-link {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-2);
  text-decoration: none; white-space: nowrap;
  padding: 4px 8px; border: 1px solid var(--rule-2); border-radius: 3px;
  transition: color .15s, border-color .15s;
}
.map-link:hover { color: var(--c-border); border-color: color-mix(in srgb, var(--c-border) 50%, transparent); }
.map-link:focus-visible { outline: 2px solid var(--c-border); outline-offset: 2px; }

/* Смуга «Показано:» під шапкою: активні фільтри, кожен знімається хрестиком. */
.filter-chips {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 22px; min-height: 36px;
  background: var(--panel); border-bottom: 1px solid var(--rule);
}
.filter-chips[hidden] { display: none; }
.fc-lab {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); margin-right: 2px;
}
.fc, .fc-reset {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--sans); font-size: 11.5px; line-height: 1;
  padding: 5px 8px 5px 10px; border-radius: 999px; cursor: pointer;
  color: var(--ink); background: var(--panel-2); border: 1px solid var(--rule-2);
  transition: border-color .15s, color .15s;
}
.fc span { color: var(--ink-3); font-size: 13px; }
.fc:hover { border-color: var(--c-case); }
.fc:hover span { color: var(--c-case); }
.fc-reset { color: var(--c-border); background: transparent; border-color: transparent; padding-left: 6px; }
.fc-reset:hover { border-color: color-mix(in srgb, var(--c-border) 45%, transparent); }
.fc:focus-visible, .fc-reset:focus-visible { outline: 2px solid var(--c-border); outline-offset: 2px; }

.ident-mark {
  font-family: var(--mono); font-weight: 600; font-size: 15px;
  letter-spacing: -0.02em; color: #000;
  background: var(--signal); padding: 5px 8px 4px; border-radius: 3px;
  line-height: 1; white-space: nowrap;
  /* Марка — посилання на Головну платформи (не кнопка воріт, як колись). */
  text-decoration: none;
}
.ident-mark:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ident-mark span { opacity: 0.55; }

.ident-text h1 {
  font-family: var(--serif); font-weight: 600; font-size: 16px;
  letter-spacing: -0.005em; line-height: 1.2;
}
.ident-text p {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.readout { display: flex; align-items: stretch; flex: none; }
.readout .cell {
  padding: 0 18px; text-align: right; border-left: 1px solid var(--rule);
  display: flex; flex-direction: column; justify-content: center;
}
.readout .cell:first-child { border-left: none; }
.readout b {
  font-family: var(--mono); font-weight: 500; font-size: 19px;
  font-variant-numeric: tabular-nums; letter-spacing: -0.03em; line-height: 1.1;
}
.readout span {
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  letter-spacing: 0.06em; text-transform: uppercase; margin-top: 3px;
}
.readout .cell.hot b { color: var(--signal); }

/* ───────────────────────────────────────────────────── розкладка */

/* Консоль ширша, ніж була: у ній тепер живуть фільтри, а вони — це вісім
   блоків із двоколонковими заголовками, які на 306 пікселях переносилися. */
.stage { display: grid; grid-template-columns: 342px 1fr; min-height: 0; }

.console {
  display: flex; flex-direction: column; min-height: 0;
  background: var(--panel); border-right: 1px solid var(--rule);
}

.console-tabs { display: flex; border-bottom: 1px solid var(--rule); flex: none; }
.console-tabs button {
  flex: 1; padding: 11px 4px 10px; cursor: pointer;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--ink-3);
  background: transparent; border: none; border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.console-tabs button:hover { color: var(--ink-2); }
.console-tabs button.on { color: var(--ink); border-bottom-color: var(--signal); }

.console-body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 18px 16px 40px; display: flex; flex-direction: column; gap: 22px;
  animation: rise 0.22s ease both;
}
@keyframes rise { from { opacity: 0; transform: translateY(4px); } }

/* display:flex перебиває [hidden], тож ховаємо явно. */
.console-body[hidden] { display: none; }

.console-body::-webkit-scrollbar { width: 9px; }
.console-body::-webkit-scrollbar-thumb {
  background: var(--rule); border: 3px solid var(--panel); border-radius: 5px;
}

/* ────────────────────────────────────────────────────── елементи */

.unit-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 9px;
}
.unit-label {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
}
.unit-value {
  font-family: var(--mono); font-size: 10px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.fine { font-size: 11px; line-height: 1.45; color: var(--ink-3); margin-top: 8px; }

.prose { font-size: 12px; color: var(--ink-2); line-height: 1.55; }
.prose b { color: var(--ink); font-weight: 600; }
.prose ul { margin: 7px 0 0 15px; display: flex; flex-direction: column; gap: 5px; }
.prose a { color: var(--ink-3); }
.prose .lede {
  font-family: var(--mono); font-size: 22px; color: var(--signal);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.prose table { width: 100%; margin: 8px 0; border-collapse: collapse; }
.prose td { padding: 2px 0; border-bottom: 1px solid var(--rule); }
.prose td:last-child {
  text-align: right; color: var(--ink);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  /* Число не має злипатися з підписом, коли підпис займає всю ширину. */
  padding-left: 10px; white-space: nowrap;
}

.toggle-pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--rule); border: 1px solid var(--rule); border-radius: 4px;
  overflow: hidden;
}
.toggle-pair button {
  padding: 8px 4px; cursor: pointer; border: none;
  font-family: var(--mono); font-size: 11px;
  background: var(--panel-2); color: var(--ink-3); transition: 0.15s;
}
.toggle-pair button:hover { color: var(--ink-2); }
.toggle-pair button.on { background: var(--signal); color: #000; font-weight: 500; }

.choice { display: flex; gap: 4px; }
.choice button {
  flex: 1; padding: 7px 4px; cursor: pointer;
  font-family: var(--mono); font-size: 10.5px;
  background: var(--panel-2); color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 3px; transition: 0.15s;
}
.choice button:hover { border-color: var(--rule-2); color: var(--ink-2); }
.choice button.on { background: var(--raised); border-color: var(--signal); color: var(--ink); }

.slider { position: relative; height: 22px; }
.slider input {
  position: absolute; width: 100%; margin: 0; height: 22px;
  pointer-events: none; -webkit-appearance: none; appearance: none;
  background: transparent;
}
.slider input::-webkit-slider-runnable-track {
  height: 2px; background: var(--rule-2); border-radius: 1px;
}
.slider input::-webkit-slider-thumb {
  -webkit-appearance: none; pointer-events: auto; cursor: grab;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--panel); margin-top: -5px;
}
.slider input::-webkit-slider-thumb:active { cursor: grabbing; background: var(--signal); }

.pills { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 10px; }
.pills button {
  font-family: var(--mono); font-size: 10.5px; padding: 4px 9px; cursor: pointer;
  background: transparent; color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 20px; transition: 0.15s;
}
.pills button:hover { border-color: var(--rule-2); color: var(--ink-2); }
.pills button.on { background: var(--raised); border-color: var(--rule-2); color: var(--ink); }

.tags { display: flex; flex-wrap: wrap; gap: 4px; }
.tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; padding: 4px 9px; cursor: pointer;
  background: transparent; color: var(--ink-2);
  border: 1px solid var(--rule); border-radius: 3px; transition: 0.15s;
}
.tag:hover { border-color: var(--rule-2); }
.tag.on { background: var(--raised); border-color: var(--rule-2); color: var(--ink); }
.tag .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.tag .n {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.tag.on .n { color: var(--ink-2); }

.clear {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em;
  padding: 8px; cursor: pointer; text-transform: uppercase;
  background: transparent; color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 3px; transition: 0.15s;
}
.clear:hover { color: var(--alert); border-color: var(--alert); }

.basemaps { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
.basemap {
  display: flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 6px 8px; border: 1px solid var(--rule); border-radius: 3px;
  background: var(--panel-2); transition: 0.15s;
}
.basemap:hover { border-color: var(--rule-2); }
.basemap.on { border-color: var(--signal); background: var(--raised); }
.basemap i {
  width: 16px; height: 16px; border-radius: 2px; flex: none;
  background-size: cover; background-position: center;
}
.basemap span { font-size: 11px; color: var(--ink-2); }
.basemap.on span { color: var(--ink); }

/* ──────────────────────────────────────────────────── стек шарів */

.stack { display: flex; flex-direction: column; gap: 1px; }
.stack-title {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 7px; border-bottom: 1px solid var(--rule); margin-bottom: 5px;
}

.lyr {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 8px; cursor: pointer; border-radius: 3px;
  transition: background 0.15s;
}
.lyr:hover { background: var(--panel-2); }
.lyr input { accent-color: var(--signal); width: 13px; height: 13px; flex: none; }
.lyr-name { font-size: 12px; color: var(--ink-2); }
.lyr:has(input:checked) .lyr-name { color: var(--ink); }

.lyr-swatch { width: 14px; height: 10px; flex: none; border-radius: 2px; }
.lyr-swatch.dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--c);
}
.lyr-swatch.diamond {
  width: 9px; height: 9px; border: 1.5px solid var(--hu);
  border-radius: 2px; transform: rotate(45deg); background: transparent;
}
.lyr-swatch.heat {
  background: radial-gradient(circle, #ff5147 0%, #f5a524 45%, transparent 75%);
}
.lyr-swatch.grad {
  background: linear-gradient(90deg, #1e3a8a, #38bdf8, #a3e635, #ff2d2d);
}

/* ─────────────────────────────────────────────────────── графіки */

.timeline { display: flex; align-items: flex-end; gap: 2px; height: 88px; }
.timeline .bar {
  flex: 1; min-width: 3px; min-height: 2px; cursor: pointer;
  display: flex; flex-direction: column-reverse; overflow: hidden;
  background: var(--rule); border-radius: 2px 2px 0 0;
  transition: opacity 0.15s;
  animation: grow 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
@keyframes grow { from { transform: scaleY(0.02); transform-origin: bottom; } }
.timeline .bar i { display: block; width: 100%; }
.timeline .bar:hover { outline: 1px solid var(--ink-2); outline-offset: 1px; }
.timeline .bar.out { opacity: 0.25; }
.timeline .bar.picked { outline: 1px solid var(--signal); outline-offset: 1px; }

.axis {
  display: flex; justify-content: space-between; gap: 6px; margin-top: 6px;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.hours { display: flex; align-items: flex-end; gap: 2px; height: 60px; }
.hbar {
  flex: 1; height: 100%; cursor: pointer;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.hbar i {
  display: block; width: 100%; min-height: 2px; background: var(--ua);
  border-radius: 2px 2px 0 0; transition: background 0.15s;
  animation: grow 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.hbar span {
  font-family: var(--mono); font-size: 8.5px; color: var(--ink-3);
  text-align: center; margin-top: 4px; height: 10px;
}
.hbar:hover i { background: var(--signal); }
.hbar.out { opacity: 0.28; }
.hbar.picked i { background: var(--signal); }

/* Дев'ять смуг замість двадцяти чотирьох годин — підписи довші, тож
   і крок, і місце під них більші. */
.hours.dist { height: 84px; gap: 3px; }
.hours.dist .hbar span { font-size: 8px; height: 20px; line-height: 10px; }

.bars { display: flex; flex-direction: column; gap: 8px; }
.bars .row.pick { cursor: pointer; }
.bars .row.out { opacity: 0.32; }
.bars .row.picked .top span { color: var(--signal); }
.bars .row { font-size: 11.5px; }
.bars .row .top { display: flex; justify-content: space-between; color: var(--ink-2); }
.bars .row .top b {
  font-family: var(--mono); font-weight: 400; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.bars .row .track {
  height: 4px; background: var(--rule); border-radius: 2px;
  margin-top: 4px; overflow: hidden;
}
.bars .row .track i {
  display: block; height: 100%; border-radius: 2px;
  animation: slide 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
@keyframes slide { from { transform: scaleX(0); transform-origin: left; } }

.courts { display: flex; flex-direction: column; gap: 1px; }
.court-row {
  display: grid; grid-template-columns: 1fr 34px 46px 30px;
  align-items: center; gap: 7px; padding: 4px 6px;
  font-size: 11.5px; cursor: pointer; border-radius: 3px;
  transition: background 0.15s;
}
.court-row:hover { background: var(--panel-2); }
.court-row.on { background: var(--raised); }
.court-name {
  color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.court-row.on .court-name, .court-row:hover .court-name { color: var(--ink); }
.court-bar { height: 4px; background: var(--rule); border-radius: 2px; overflow: hidden; }
.court-bar i { display: block; height: 100%; }
.court-pct, .court-n {
  font-family: var(--mono); font-size: 10.5px; text-align: right;
  font-variant-numeric: tabular-nums;
}
.court-pct { color: var(--ink); }
.court-n { color: var(--ink-3); }

.lyr-swatch.court {
  background: linear-gradient(90deg, #2f6fd0, #94a3b0, #ff5147);
}

.ranking { list-style: none; display: flex; flex-direction: column; gap: 1px; }
.ranking li {
  display: flex; align-items: center; gap: 9px; padding: 4px 6px;
  font-size: 12px; cursor: pointer; border-radius: 3px; transition: background 0.15s;
}
.ranking li:hover { background: var(--panel-2); }
.ranking li:hover .name { color: var(--signal); }
.ranking .rank {
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  width: 14px; text-align: right; flex: none;
}
.ranking .name {
  flex: 1; color: var(--ink-2); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.ranking li.on .name { color: var(--signal); }
.ranking .meter { width: 46px; height: 3px; background: var(--rule); border-radius: 2px; overflow: hidden; }
.ranking .meter i { display: block; height: 100%; background: var(--ro); }
.ranking .n {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  min-width: 22px; text-align: right; font-variant-numeric: tabular-nums;
}

/* ─────────────────────────────────────────── список румунських точок */

.aid-list { display: flex; flex-direction: column; gap: 12px; }
.aid-group { font-size: 12px; }
.aid-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--mono); font-size: 10px; margin-bottom: 4px;
}
.aid-head span { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.aid-item {
  color: var(--ink-2); padding: 2px 0 2px 15px; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aid-item:hover { color: var(--signal); }

/* Перелік групових подій: число ліворуч, місце й дата праворуч. */
.events { display: flex; flex-direction: column; }
.ev {
  display: flex; align-items: baseline; gap: 9px; cursor: pointer;
  padding: 4px 0; border-bottom: 1px solid var(--rule);
}
.ev:hover .ev-place { color: var(--signal); }
.ev-n {
  font-family: var(--mono); font-size: 13px; color: var(--ink);
  font-variant-numeric: tabular-nums; min-width: 20px; text-align: right;
}
.ev-body { min-width: 0; flex: 1; }
.ev-place {
  font-size: 12px; color: var(--ink-2); transition: color 0.15s;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ev-meta { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); }

/* Покриття судами: смужка позаду назви показує обсяг, не забираючи рядка. */
.courts { display: flex; flex-direction: column; gap: 1px; }
.crt {
  position: relative; display: flex; align-items: baseline; gap: 8px;
  padding: 3px 6px; cursor: pointer; overflow: hidden;
}
.crt-bar {
  position: absolute; inset: 0 auto 0 0; background: var(--ua);
  opacity: .22; transition: opacity .15s;
}
.crt:hover .crt-bar { opacity: .38; }
.crt.picked .crt-bar { background: var(--signal); opacity: .3; }
.crt-name {
  position: relative; flex: 1; min-width: 0; font-size: 11.5px; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crt.picked .crt-name { color: var(--ink); }
.crt-n {
  position: relative; font-family: var(--mono); font-size: 10px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.crt-seg { color: var(--ink-3); }

/* ───────────────────────────────────────────────────────── мапа */

.canvas { position: relative; min-width: 0; }
#map { position: absolute; inset: 0; background: #05070a; }

.overlay {
  position: absolute; z-index: 500;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  border: 1px solid var(--rule); border-radius: 5px;
  backdrop-filter: blur(8px);
}

.legend { width: 300px; }
.legend-toggle {
  width: 100%; text-align: left; cursor: pointer; padding: 7px 11px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
  background: transparent; border: none;
}
.legend-toggle:hover { color: var(--ink-2); }
.legend-body {
  padding: 0 11px 10px; font-size: 10.5px; color: var(--ink-2); line-height: 1.75;
  display: flex; flex-direction: column; gap: 5px;
}
/* Висоту тіла обмежує fitLegend() в app.js: body має overflow:hidden, і все,
   що нижче краю мапи чи під шкалою, інакше недосяжне. Решту прокручуємо. */
.legend-body { overflow-y: auto; overscroll-behavior: contain; }
.legend.closed .legend-body { display: none; }
.legend-row { line-height: 1.75; }
.legend-row b { color: var(--ink); font-weight: 600; }
.legend .sw {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  margin: 0 4px 0 10px;
}
.legend-row .sw:first-child { margin-left: 0; }
.legend .sw.line {
  width: 16px; height: 2px; border-radius: 0; background: var(--signal);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--signal) 14%, transparent);
  vertical-align: middle;
}
/* Три зразки відповідають крайнім значенням таблиці PIN: 10 px для виміряної
   координати, 7 px для модельної, 5 px для прив'язки лише до району. */
.legend .sw.big { width: 10px; height: 10px; background: var(--ink-2); }
.legend .sw.mid { width: 7px; height: 7px; background: var(--ink-2); opacity: 0.6; }
.legend .sw.small { width: 5px; height: 5px; background: var(--ink-2); opacity: 0.35; }
.legend .sw.diamond {
  width: 8px; height: 8px; background: transparent;
  border: 2px solid var(--hu); border-radius: 2px; transform: rotate(45deg);
}
.legend .sw.ring {
  background: color-mix(in srgb, var(--ro) 15%, transparent); border: 1px solid var(--ro);
}
.legend .gl { margin: 0 3px 0 9px; font-size: 12px; }
/* Зразки форм справ — ті самі класи, що й на мапі (.pin--solid/ring/vague). */
.legend .sw.pin-sw { width: 9px; height: 9px; margin-left: 0; vertical-align: -1px; box-sizing: border-box; }
.legend .sw.grad-sw {
  width: 18px; height: 4px; border-radius: 2px; box-shadow: none;
  background: linear-gradient(90deg, #2a2610, #ffd400, #fff4b8);
}
.legend .sw.heat-sw { background: radial-gradient(#fff4b8, #ffd400 45%, transparent 72%); width: 12px; height: 12px; }
.legend .sw.ring-y { background: transparent; border: 1.5px solid var(--c-border); }
.legend .sw.line.thin { height: 1px; background: #2f6fd0; box-shadow: none; }
.legend .sw.cells { border-radius: 1px; background: color-mix(in srgb, #2f6fd0 60%, transparent); }

.scale { bottom: 12px; right: 12px; width: 214px; padding: 9px 11px; display: none; }
.scale-title { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); margin-bottom: 6px; }
.scale-bar { height: 7px; border-radius: 4px; }
.scale-ticks {
  display: flex; justify-content: space-between; margin-top: 3px;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.scale-note { font-size: 10px; color: var(--ink-3); margin-top: 5px; line-height: 1.4; }

/* Перемикач видимості легенди й шкали. Сам лишається на екрані завжди —
   інакше сховані панелі не було б чим повернути. */
.rail-btn {
  padding: 6px 10px; cursor: pointer;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase;
  /* Той самий жовтий, що й кордон на мапі: це керування показом, а не частина
     даних, тож воно має читатися як елемент інтерфейсу, а не як ще одна
     службова підказка поруч із легендою. */
  color: var(--signal);
  border-color: color-mix(in srgb, var(--signal) 35%, transparent);
}
.rail-btn:hover {
  color: var(--signal);
  border-color: color-mix(in srgb, var(--signal) 60%, transparent);
}
/* Коли панелі сховані, кнопка лишається жовтою — саме вона тепер єдиний спосіб
   їх повернути, і губитися на тлі мапи їй не можна. Приглушуємо лише тло. */
.rail-btn.off { background: color-mix(in srgb, var(--panel) 72%, transparent); }

/* !important тут не примха: видимість шкали ставить JS інлайновим
   style.display залежно від увімкненого шару, а інлайн сильніший за клас. */
/* Лише на широкому екрані: на телефоні кнопки «сховати пояснення» немає
   (напрямні там сховано), і вимкнене колись на комп'ютері перемикання
   (воно живе в localStorage) ховало б легенду в «Про мапу» й шкалу
   без способу їх повернути. */
html:not(.is-mobile) body.overlays-off #legend,
html:not(.is-mobile) body.overlays-off #scale { display: none !important; }
/* Вступ (#note) і розкладка «скільки стало точками» (#shownLine) — такі самі
   картки поверх мапи, і хто прибрав банери, хоче бачити саму мапу, а не
   половину пояснень до неї. На телефоні обидва живуть не над мапою, а в
   аркушах (mobile.js переносить розкладку в аркуш шарів), тож там не
   ховаємо: це вже не банер, а вміст панелі, яку людина сама відкрила. */
body.overlays-off #note,
html:not(.is-mobile) body.overlays-off #shownLine { display: none !important; }

/* А тепер — завжди, не лише з вимкненими банерами. Власник (26.09.2026):
   вступ, рядок розкладки й абзац пояснень під шкалою «заважають». Усе це
   тепер живе на платформі — /metodolohiia/ пояснює і лійку, і точність, і
   згладжування, — а мапа лишається інструментом, а не статтею поверх нього.
   Від шкали лишається смужка з підписом і двома поділками: без неї колір
   лінії не прочитати. На телефоні вступ і розкладка лежать в аркушах, які
   людина відкриває сама, тож там їх не чіпаємо. */
html:not(.is-mobile) #note,
html:not(.is-mobile) #shownLine,
#scale .scale-bar ~ .scale-note { display: none !important; }
/* Лише поруч зі смужкою: коли у вибірці немає справ із координатами, смужки
   немає, і абзац — єдине, що пояснює, чому лінія не пофарбована. */

/* 38 px знизу, а не 12: під підписом тепер стоїть лінійний масштаб
   Leaflet (кут bottomleft). */
.caption {
  bottom: 38px; left: 12px; max-width: 430px; padding: 8px 12px;
  font-size: 11px; color: var(--ink-3); line-height: 1.45; pointer-events: none;
}
/* Підпис прозорий для миші, щоб не заважати мапі, — окрім посилання в ньому. */
.caption a, #note-mobile a { pointer-events: auto; }
.how-link { color: var(--c-border); text-decoration: none; white-space: nowrap; }
.how-link:hover { text-decoration: underline; }

/* ──────────────────────────────────────────────────── пошук на мапі */

/* Напрямні мапи. Ширину задає найширший елемент у стовпці, тож пошук і кнопки
   вирівнюються самі — без жодного числа в кожному з них. */
.rail {
  position: absolute; top: 12px; z-index: 600;
  display: flex; flex-direction: column; gap: 10px;
  pointer-events: none;               /* мапа під проміжками лишається живою */
}
.rail > * { pointer-events: auto; }
/* .overlay сам ставить position: absolute — усередині напрямної це вибило б
   елемент із потоку, і стовпця не вийшло б. */
.rail .overlay { position: relative; top: auto; right: auto; left: auto; bottom: auto; }
.rail-left  { left: 12px; align-items: flex-start; }
.rail-right { right: 12px; align-items: flex-end; }

.finder { position: relative; width: 330px; }
.finder input {
  width: 100%; padding: 9px 12px;
  font-family: var(--sans); font-size: 12.5px; color: var(--ink);
  background: color-mix(in srgb, var(--panel) 94%, transparent);
  border: 1px solid var(--rule); border-radius: 5px;
  backdrop-filter: blur(8px); transition: border-color 0.15s;
}
.finder input::placeholder { color: var(--ink-3); }
.finder input:focus { outline: none; border-color: var(--signal); }

.finder-results {
  margin-top: 5px; max-height: 340px; overflow-y: auto;
  background: color-mix(in srgb, var(--panel) 96%, transparent);
  border: 1px solid var(--rule); border-radius: 5px;
  backdrop-filter: blur(8px); box-shadow: 0 16px 40px rgba(0,0,0,0.55);
}
.finder-group {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
  padding: 8px 12px 4px; border-top: 1px solid var(--rule);
}
.finder-group:first-child { border-top: none; }
.finder-hit {
  display: flex; align-items: baseline; gap: 8px;
  padding: 6px 12px; cursor: pointer; font-size: 12px;
  transition: background 0.1s;
}
.finder-hit:hover, .finder-hit.active { background: var(--raised); }
.finder-hit .h-name { color: var(--ink); flex: none; }
.finder-hit .h-meta {
  flex: 1; text-align: right; color: var(--ink-3);
  font-family: var(--mono); font-size: 10px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.finder-hit mark { background: none; color: var(--signal); }
.finder-empty { padding: 10px 12px; font-size: 11.5px; color: var(--ink-3); }

.finder-flash {
  border-radius: 50%; border: 2px solid var(--signal);
  animation: flash 1.4s ease-out forwards;
}
@keyframes flash {
  from { transform: scale(0.3); opacity: 1; }
  to   { transform: scale(2.4); opacity: 0; }
}

/* ────────────────────────────────────────────────── нижня шухляда */


/* Другорядна кнопка. Правило жило разом із полем пошуку нижньої панелі;
   панелі більше немає, а кнопка лишилася. */
.ghost {
  font-family: var(--mono); font-size: 11px; padding: 5px 10px;
  background: var(--panel-2); color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 3px;
  cursor: pointer; transition: 0.15s;
}
.ghost:hover { color: var(--ink); border-color: var(--rule-2); }

table { width: 100%; border-collapse: collapse; font-size: 12px; }
tbody tr { border-bottom: 1px solid #151c24; cursor: pointer; transition: background 0.12s; }
tbody tr:hover { background: var(--panel-2); }
td { padding: 6px 10px; white-space: nowrap; vertical-align: baseline; }
/* «Два лічильники»: підпис довгий («Прикордонна поліція Румунії (3 повіти),
   виявлені»), а загальне td { nowrap } тримало обидві комірки в один рядок —
   на 1440 px картка 295 px, рядок 522 px, і числа порівняння виходили за край
   («пс» замість «понад 3 700 → майже 2 500»). Рядок гнучкий: підпис
   переноситься, число лишається цілим і, якщо не вміщується, зісковзує під
   підпис праворуч — як на телефоні (mobile.css). */
#halves table, #halves tbody { display: block; width: 100%; }
#halves tr {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0 12px; padding: 4px 0; cursor: default;
}
#halves td { display: block; white-space: normal; padding: 0; }
#halves td:last-child { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
td.when { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
td.place { color: var(--ink); font-weight: 500; }
td.dim { color: var(--ink-3); }
td.wide {
  white-space: normal; color: var(--ink-3); max-width: 520px;
  overflow: hidden; text-overflow: ellipsis; font-size: 11.5px;
}
td a { color: var(--ua); text-decoration: none; font-family: var(--mono); font-size: 11px; }
td a:hover { color: var(--signal); }
.chip {
  display: inline-block; padding: 1px 7px; border-radius: 3px;
  font-family: var(--mono); font-size: 10px;
}

/* На світлих підкладках напівпрозорі накладки треба тримати темнішими,
   інакше білі підписи мапи просвічують крізь панелі. */
body.light-base .overlay { background: color-mix(in srgb, var(--void) 88%, transparent); }
body.light-base .caption { color: var(--ink-2); }

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

.leaflet-container { background: #05070a; font-family: var(--sans); }

/* Leaflet робить контейнер фокусованим заради клавіатури, і браузер малює
   навколо мапи обвідку на кожен клік. Для миші вона зайва, для клавіатури —
   потрібна, тож гасимо лише фокус, що НЕ :focus-visible.

   Колись тут стояло `.leaflet-container *:focus { outline: none }` — без
   винятку для клавіатури. Воно гасило фокус усього всередині мапи: кнопок
   масштабу, скупчень, хрестика попапа, кнопки «читати справу». Хто ходив
   Tab-ом, не бачив, де він. */
.leaflet-container:focus:not(:focus-visible),
.leaflet-container *:focus:not(:focus-visible) { outline: none; }
.leaflet-container:focus-visible {
  outline: 2px solid var(--signal); outline-offset: -2px;
}
.leaflet-container a:focus-visible,
.leaflet-container button:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.leaflet-marker-icon:focus-visible { outline: 2px solid var(--c-select); outline-offset: 2px; }
/* Значок .rtf-mk має нульовий розмір (стоїть рівно в точці), тож обвідка
   самого контейнера невидима — малюємо її на видимому вузлі всередині. */
.leaflet-marker-icon.rtf-mk:focus-visible { outline: none; }
.leaflet-marker-icon.rtf-mk:focus-visible > * { outline: 2px solid var(--c-select); outline-offset: 3px; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--raised); color: var(--ink);
  border: 1px solid var(--rule-2); box-shadow: 0 14px 40px rgba(0,0,0,0.6);
}
.leaflet-popup-content-wrapper { border-radius: 5px; }
.leaflet-popup-content { margin: 12px 14px; font-size: 12px; line-height: 1.5; width: 258px !important; }
.leaflet-popup-content h3 { font-family: var(--serif); font-size: 14px; margin-bottom: 4px; }
.leaflet-popup-content dl {
  display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; margin: 8px 0;
  padding: 8px 0; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.leaflet-popup-content dt { color: var(--ink-3); font-size: 11px; }
.leaflet-popup-content dd {
  text-align: right; font-family: var(--mono); font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.leaflet-popup-content a { color: var(--ua); font-family: var(--mono); font-size: 11px; }
.leaflet-control-attribution {
  background: rgba(6,8,11,0.82) !important; color: var(--ink-3) !important;
  font-family: var(--mono); font-size: 9.5px;
}
.leaflet-control-attribution a { color: var(--ink-2) !important; }
.leaflet-bar a { background: var(--panel-2); color: var(--ink); border-color: var(--rule); }
.leaflet-bar a:hover { background: var(--raised); }
.leaflet-tooltip {
  background: var(--raised); border: 1px solid var(--rule-2); color: var(--ink);
  font-size: 11px; box-shadow: 0 8px 24px rgba(0,0,0,0.5);
}
.leaflet-tooltip-top:before { border-top-color: var(--rule-2); }

/* Форма крапки — це спосіб прив'язки, а не просто оздоба. Заповнена означає
   «місце назване або виміряне», кільце — «обчислено моделлю», пунктир —
   «ділянка на десятки кілометрів». Числа, за якими проведено межі, лежать
   у app.js поруч із ERR_KM. */
.pin { border-radius: 50%; }
.pin--solid {
  background: var(--pin);
  border: 1.5px solid rgba(6,8,11,0.85);
}
.pin--ring {
  background: color-mix(in srgb, var(--pin) 22%, transparent);
  border: 1.5px solid var(--pin);
  box-shadow: 0 0 0 0.5px rgba(6,8,11,0.7);
}
.pin--vague {
  background: color-mix(in srgb, var(--pin) 10%, transparent);
  border: 1.5px dashed var(--pin);
}
.cp-pin {
  width: 9px; height: 9px; background: transparent;
  border: 2px solid var(--hu); border-radius: 2px; transform: rotate(45deg);
}
.aid { font-size: 14px; line-height: 16px; text-align: center; text-shadow: 0 0 4px #000, 0 0 2px #000; }
.cluster {
  background: color-mix(in srgb, var(--c-case) 26%, rgba(6,8,11,0.72));
  border: 1.5px solid color-mix(in srgb, var(--c-case) 85%, transparent);
  border-radius: 50%; color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 10.5px; font-weight: 500;
  font-variant-numeric: tabular-nums; line-height: 1;
}
/* Злиття кількох крапок без числа: на огляді й там, де справ менше 10. */
.cluster.cluster--dot {
  background: color-mix(in srgb, var(--c-case) 80%, transparent);
  border: 1px solid rgba(6,8,11,0.85);
}

/* ── Значки з розміром за рівнем зуму (app.js, pinIcon/stackIcon/blockIcon)

   Контейнер маркера має нульовий розмір і стоїть рівно в точці; видимий
   вузол центрується на ній сам, а розмір бере з --d-lo / --d-mid / --d-hi
   за класом рівня на контейнері мапи. Так якір не зсувається, хоч би яким
   був розмір, і перемикання зуму — це одна зміна класу, а не перебудова
   тисяч значків.

   Сам контейнер прозорий для миші, клік ловить видимий вузол: інакше на
   огляді невидимі поля великих значків перекривали б сусідні крапки. */
.leaflet-marker-icon.rtf-mk { pointer-events: none !important; overflow: visible; }
.rtf-mk > * {
  --d: var(--d-hi, 10px);
  position: absolute; left: 0; top: 0;
  width: var(--d); height: var(--d);
  transform: translate(-50%, -50%);
  pointer-events: auto; cursor: pointer;
  box-sizing: border-box;
}
.z-lo  .rtf-mk > * { --d: var(--d-lo, var(--d-hi, 4px)); }
.z-mid .rtf-mk > * { --d: var(--d-mid, var(--d-hi, 10px)); }
/* Зона дотику для дрібних крапок — більша за саму крапку, але лише там, де
   крапки не стоять щільно (з 9-го зуму). */
.z-mid .rtf-mk > .pin::after, .z-hi .rtf-mk > .pin::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 24px; height: 24px; transform: translate(-50%, -50%); border-radius: 50%;
}
/* Числа: на огляді — жодних; на середньому масштабі — лише від 10 справ. */
.z-lo .rtf-mk > .stack, .z-lo .rtf-mk > .blk,
.z-mid .rtf-mk > .stack.few, .z-mid .rtf-mk > .blk.few { color: transparent; font-size: 0; }
/* Місце групи на огляді — порожній квадрат: розмір каже, скільки справ, а
   порожнеча — що це одне місце на групу, а не скупчення людей. */
.z-lo .rtf-mk > .blk {
  background: transparent;
  border: 1.5px solid color-mix(in srgb, var(--c-case) 70%, #ffffff);
  box-shadow: 0 0 0 1px rgba(6,8,11,0.6);
}
.z-lo .rtf-mk > .stack { border-width: 1px; }

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

.only-narrow { display: none; }
.sheet-handle { display: none; }
#note-mobile { display: none; }

@media (max-width: 1120px) {
  /* Не вужче за 300: у консолі тепер живуть фільтри, і на 268 пікселях
     двоколонкові заголовки на кшталт «частина статті · 8 727 ч.1 · 9 713 ч.2»
     переносяться на три рядки кожен. */
  .stage { grid-template-columns: 300px 1fr; }
  .legend { max-width: 250px; }
  .ident-text p { display: none; }
  .map-link { font-size: 10px; padding: 3px 6px; }
}
@media (max-width: 980px) {
  .readout .cell:nth-child(n+3) { display: none; }
  }

/* ───────────────────────────────────────────────────── вузький екран
   Панель із 306 пікселів на телефоні лишала мапі сто. Тому на вузькому
   екрані вона стає нижньою шухлядою на всю ширину з трьома положеннями, а
   мапа отримує весь простір. Таблиця справ переїжджає в неї четвертою
   вкладкою — двом шухлядам на одному краю нема де розійтися.            */
@media (max-width: 760px) {
  body { grid-template-rows: 46px auto 1fr; overflow: hidden; }
  .map-links { display: none; }
  .filter-chips { padding: 5px 12px; }

  .masthead { padding: 0 12px; gap: 10px; }
  .ident { gap: 9px; }
  .ident-mark { font-size: 12px; padding: 4px 6px 3px; }
  .ident-text h1 { font-size: 13px; }
  .ident-text p { display: none; }
  /* Лишаємо один показник: решта живе в шухляді, де є місце на підпис. */
  .readout .cell { padding: 0 10px; }
  .readout .cell:nth-child(n+2) { display: none; }
  .readout b { font-size: 15px; }
  .readout span { font-size: 8px; }

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

  .console {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    height: 46vh;
    border-right: none; border-top: 1px solid var(--rule-2);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -14px 34px rgba(0, 0, 0, 0.55);
    transition: height 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  /* Три положення. «Peek» лишає саму смужку вкладок — мапа майже ціла.
     Висота задається напряму, а не через змінну: підстановка var() у height
     тут чомусь стабільно бралася із запасного значення, і шухляда не
     рухалася взагалі. Прямі значення роблять те саме й без загадок. */
  .console.peek { height: calc(52px + env(safe-area-inset-bottom, 0px)); }
  .console.half { height: 46vh; }
  .console.full { height: calc(100vh - 46px); }
  .console.dragging { transition: none; }

  .sheet-handle {
    display: block; flex: none; height: 16px; cursor: grab;
    touch-action: none; position: relative;
  }
  .sheet-handle::before {
    content: ''; position: absolute; left: 50%; top: 6px;
    width: 34px; height: 4px; margin-left: -17px; border-radius: 2px;
    background: var(--rule-2);
  }

  .console-tabs { touch-action: none; }
  .console-tabs button { padding: 12px 2px 11px; font-size: 10px; letter-spacing: .04em; }
  .only-narrow { display: block; }

  .console-body { padding: 14px 14px 30px; gap: 18px; }
  /* Таблиця в шухляді має власний скрол, тож зайві відступи прибираємо. */
  .console-list { padding: 0; gap: 0; }

  /* Пальцеві цілі: 14 пікселів чекбокса не вціляються. */
  .lyr { padding: 7px 0; min-height: 40px; }
  .lyr input { width: 20px; height: 20px; flex: none; }
  .choice button, .toggle-pair button { padding: 11px 4px; font-size: 11px; }
  .pills button, .tag { padding: 8px 11px; }
  .ghost { padding: 9px 12px; }

  /* Накладки на мапі. Усе, що плаває над мапою, мусить лишатися вище
     згорнутої шухляди (52 px), інакше ховається під нею. */
  .rail { top: 10px; }
  .rail-left { left: 10px; right: 10px; }
  .rail-right { right: 10px; }
  .finder { width: 100%; }
  .rail-left > .finder { align-self: stretch; }
  .legend { display: none; }
  .scale {
    left: 10px; right: 10px; width: auto; max-width: none;
    /* Вище за атрибуцію Leaflet, яка сидить на 54 px від низу. */
    bottom: calc(78px + env(safe-area-inset-bottom, 0px));
    font-size: 10px; max-height: 30vh; overflow-y: auto;
  }
  /* Довгий вступний підпис на телефоні з'їдав пів мапи. Той самий текст
     показується першим рядком у вкладці «Шари», де на нього є місце. */
  #note { display: none; }
  #note-mobile { display: block; }
  .leaflet-control-zoom { display: none; }
  /* Атрибуцію OpenStreetMap і Esri прибрати не можна — цього вимагають
     умови обох сервісів. Але тримати її розгорнутою на телефоні означає
     віддати їй смугу через увесь екран. Тому вона згортається у значок «i»
     біля краю й розкривається по тапу: вимога виконана, місце вільне. */
  .leaflet-control-attribution {
    bottom: calc(54px + env(safe-area-inset-bottom, 0px)) !important;
    right: 6px !important;
    font-size: 9px; max-width: 22px; height: 22px; overflow: hidden;
    border-radius: 11px; padding: 0 !important;
    background: rgba(6, 8, 11, 0.72) !important;
    border: 1px solid var(--rule);
    transition: max-width 0.2s ease;
  }
  .leaflet-control-attribution::before {
    content: 'i'; display: block; width: 20px; line-height: 20px;
    text-align: center; font-family: var(--serif); font-style: italic;
    font-size: 12px; color: var(--ink-2);
  }
  .leaflet-control-attribution.open {
    max-width: calc(100vw - 24px); height: auto; padding: 3px 8px !important;
    border-radius: 4px;
  }
  .leaflet-control-attribution.open::before { display: none; }
  /* Вміст ховається, поки значок згорнутий. */
  .leaflet-control-attribution > * { display: none; }
  .leaflet-control-attribution.open > * { display: inline; }

  /* Досьє спливає над шухлядою, а не з'їдає ширину мапи. */
  .dossier {
    left: 10px; right: 10px; width: auto; top: auto;
    bottom: calc(60px + env(safe-area-inset-bottom, 0px)); max-height: 52vh;
  }

}

/* Дуже вузькі екрани: чотири вкладки не вміщаються в один рядок. */
@media (max-width: 380px) {
  .console-tabs button { font-size: 9px; padding: 12px 1px 11px; }
  .readout .cell { padding: 0 6px; }
}

.post-pin {
  font-size: 12px; line-height: 14px; text-align: center;
  text-shadow: 0 0 4px #000, 0 0 2px #000;
}

.lyr-glyph {
  width: 14px; flex: none; text-align: center; color: var(--c);
  font-size: 12px; line-height: 1; text-shadow: 0 0 4px rgba(0,0,0,.7);
}
.lyr-n {
  margin-left: auto; font-family: var(--mono); font-size: 9.5px;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.lyr input:disabled ~ .lyr-name { opacity: .4; }

/* ─────────────────────────────────────── власні файли на мапі */

.imports { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.imp {
  display: grid; grid-template-columns: 1fr auto auto auto;
  align-items: center; gap: 4px; padding: 3px 4px; border-radius: 3px;
  transition: background 0.15s;
}
.imp:hover { background: var(--panel-2); }
.imp-main { display: flex; align-items: center; gap: 7px; min-width: 0; cursor: pointer; }
.imp-dot { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.imp-name {
  font-size: 11.5px; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.imp:hover .imp-name { color: var(--ink); }
.imp-n {
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.imp-btn {
  width: 20px; height: 20px; flex: none; cursor: pointer; border-radius: 3px;
  background: transparent; border: 1px solid transparent;
  color: var(--ink-3); font-size: 11px; line-height: 1; transition: 0.15s;
}
.imp-btn:hover { border-color: var(--rule-2); color: var(--ink); }
.imp-btn.danger:hover { border-color: var(--alert); color: var(--alert); }

.fine.bad { color: var(--alert); }

/* Підказка, що файл можна просто кинути на мапу. */
.canvas.dropping::after {
  content: 'відпустіть файл — KMZ, KML, GPX або GeoJSON';
  position: absolute; inset: 12px; z-index: 900; pointer-events: none;
  border: 2px dashed var(--signal); border-radius: 6px;
  background: rgba(255, 212, 0, 0.06);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 12px; color: var(--signal);
}

/* ─────────────────────────────────────────── малювання на мапі */

/* Колонок стільки ж, скільки в рядку файлу, тож сітку не переозначуємо:
   замість лічильника міток тут кнопка «перейменувати». */
.imp.shape.on { background: var(--raised); box-shadow: inset 2px 0 0 var(--signal); }
.imp-rename {
  width: 100%; font-family: var(--sans); font-size: 11.5px; padding: 2px 5px;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--signal); border-radius: 3px;
}
.ws-row input[type=search] {
  flex: 1; min-width: 0; font-family: var(--sans); font-size: 12px;
  padding: 6px 8px; background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 3px;
}
.ws-row input[type=search]:focus { outline: none; border-color: var(--signal); }

/* Ручка вузла: видимий кружок малий, а коробка divIcon — 28 або 34 px, щоб
   у неї можна було влучити пальцем. Різницю з'їдає прозорий margin. */
.draw-node {
  width: 12px; height: 12px; margin: 8px; border-radius: 50%; box-sizing: border-box;
  background: var(--signal); border: 2px solid #000;
}
.draw-node.mid { background: transparent; border: 2px dashed var(--signal); opacity: 0.55; }
.draw-node.on { background: var(--alert); border-color: #000; }
.draw-node.dragging { box-shadow: 0 0 0 8px rgba(255, 212, 0, 0.18); }
.draw-handle { touch-action: none; -webkit-touch-callout: none; }
.leaflet-marker-icon:focus-visible .draw-node {
  outline: 2px solid var(--signal); outline-offset: 2px;
}

/* Розмір і зсув ставить draw.js: панель Leaflet безрозмірна, і inset:0 дав би
   коробку 0×0, яка мовчки не ловить жодного кліку. */
.draw-catch {
  position: absolute; left: 0; top: 0; cursor: crosshair;
  touch-action: none; -webkit-touch-callout: none;
}

/* Рамка по краю мапи — ознака режиму, яку видно завжди й не можна прокрутити
   за межі екрана. Суцільна означає «креслимо», пунктирна — «фігуру вибрано». */
.canvas.drawing::after, .canvas.picking::after {
  content: ''; position: absolute; inset: 0; z-index: 520; pointer-events: none;
  border: 2px solid var(--signal); border-radius: 4px;
}
.canvas.picking::after { border-style: dashed; opacity: 0.55; }

.draw-hud {
  left: 50%; transform: translateX(-50%); bottom: 12px; z-index: 700;
  display: flex; align-items: center; gap: 6px; padding: 6px 8px;
}
.draw-hud-kind {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
  max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.draw-hud-read {
  font-family: var(--mono); font-size: 12px; color: var(--ink);
  font-variant-numeric: tabular-nums; padding: 0 4px; white-space: nowrap;
}
.draw-hud-acts { display: flex; align-items: center; gap: 6px; }

/* .choice і .draw-hud мають display:flex, який за специфічністю перемагає
   [hidden] з таблиці браузера. Без цих рядків жоден із блоків не ховається. */
.draw-hud[hidden], #drawLive[hidden], #drawExport[hidden] { display: none; }
#drawLive, #drawExport { margin-top: 4px; }
#drawClear { margin-top: 8px; width: 100%; }

.county-label {
  font-family: var(--mono); font-size: 11px; color: var(--ro);
  text-align: center; line-height: 16px;
  font-variant-numeric: tabular-nums; text-shadow: 0 0 5px #000, 0 0 2px #000;
}
/* П'ять комірок замість чотирьох — трохи тісніше, щоб шапка не переповнилась. */
.readout .cell { padding: 0 13px; }

/* ─────────────────────────────────────────────── перелік джерел */

.sources { display: flex; flex-direction: column; }
.src {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 8px;
  padding: 6px 0; border-bottom: 1px solid var(--rule);
}
.src:last-of-type { border-bottom: none; }
.src-name { font-size: 11.5px; color: var(--ink); }
.src-name a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--rule-2); }
.src-name a:hover { color: var(--signal); border-color: var(--signal); }
.src-what { grid-column: 1; font-size: 11px; color: var(--ink-3); }
.src-when {
  grid-row: 1 / span 2; align-self: center; text-align: right;
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); white-space: nowrap;
}

/* ────────────────────────────────────────────── досьє ділянки */

.dossier {
  left: 14px; bottom: 96px; width: 306px; max-height: 56vh; overflow-y: auto;
  padding: 12px 13px 10px;
}
.dossier-close {
  position: absolute; top: 8px; right: 8px; width: 20px; height: 20px;
  background: transparent; border: 1px solid transparent; border-radius: 3px;
  color: var(--ink-3); cursor: pointer; font-size: 11px; line-height: 1;
}
.dossier-close:hover { border-color: var(--rule-2); color: var(--ink); }
.dossier-title { font-family: var(--serif); font-size: 14px; color: var(--ink); }
.dossier-sub {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  margin: 2px 0 8px; padding-bottom: 8px; border-bottom: 1px solid var(--rule);
}
.dsr {
  display: grid; grid-template-columns: 1fr auto; gap: 10px;
  font-size: 11.5px; color: var(--ink-3); padding: 3px 0;
}
.dsr b { color: var(--ink); font-weight: 500; text-align: right; }
.dsr-sep {
  font-family: var(--mono); font-size: 9px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3);
  margin: 8px 0 4px; padding-top: 7px; border-top: 1px solid var(--rule);
}
.dsr-ep { font-size: 11px; color: var(--ink-2); padding: 2px 0; }

/* Смужка активності: один стовпчик на місяць корпусу, спільна вісь для всіх
   ділянок — інакше вузьке вікно розтяглося б і читалося як постійна робота. */
.actstrip {
  display: flex; align-items: flex-end; gap: 1px; height: 26px; margin: 2px 0 4px;
}
.actstrip i { flex: 1; background: var(--signal); opacity: .75; min-height: 0; }
.actstrip i[style*="height: 0%"] { background: var(--rule-2); opacity: 1; height: 2px; }
.actmeta {
  font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* ──────────────────────────────────────── хронологія 2022–2026 */

.tl { display: flex; flex-direction: column; gap: 7px; }
.tl-row { display: grid; grid-template-columns: 96px 1fr; align-items: center; gap: 8px; }
.tl-label { font-size: 10.5px; color: var(--ink-3); line-height: 1.2; }
.tl-track {
  position: relative; height: 20px;
  background: linear-gradient(var(--rule), var(--rule)) center/100% 1px no-repeat;
}
/* Клікабельний кружок відрізняється від просто підписаного: у першого є що
   натиснути, у другого — ні, і плутати їх не можна. */
.tl-dot.pick { cursor: pointer; }
.tl-dot.pick:hover { outline: 2px solid var(--ink); outline-offset: 2px; }

.tl-dot {
  position: absolute; top: 50%; border-radius: 50%;
  transform: translate(-50%, -50%); opacity: .85; cursor: help;
}
.tl-dot:hover { opacity: 1; box-shadow: 0 0 0 3px rgba(255,212,0,.25); }
.tl-span { position: absolute; top: 50%; height: 3px; transform: translateY(-50%); opacity: .5; }
.tl-axis {
  position: relative; height: 14px; margin-left: 104px;
  font-family: var(--mono); font-size: 9px; color: var(--ink-3);
}
.tl-axis span { position: absolute; transform: translateX(-50%); }

/* ───────────────────────────────────── порівняльна таблиця */

.cmp { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.cmp th {
  font-family: var(--mono); font-size: 9.5px; font-weight: 400;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3);
  text-align: right; padding-bottom: 5px;
}
.cmp th:first-child { text-align: left; }
.cmp td { padding: 3px 0; border-top: 1px solid var(--rule); color: var(--ink-3); }
.cmp td:not(:first-child) {
  text-align: right; color: var(--ink);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}

.imp-stats {
  grid-column: 1 / -1; font-family: var(--mono); font-size: 9.5px;
  color: var(--ink-3); padding: 1px 0 2px 16px;
  /* Числа фігури переписуються під пальцем на кожен кадр тягання — без
     табличних цифр вони стрибали б туди-сюди. */
  font-variant-numeric: tabular-nums;
}

/* Колонок три, а панель вузька — фіксуємо ширини й дозволяємо переноси. */
.cmp { table-layout: fixed; }
.cmp th:first-child, .cmp td:first-child { width: 44%; }
.cmp td:not(:first-child) { font-size: 10.5px; word-break: break-word; }

/* Роки на румунському боці — щоб було видно пік 2024-го, а не лише суму. */
.ro-years { display: flex; flex-direction: column; gap: 3px; margin: 8px 0 2px; }
.ro-year {
  display: grid; grid-template-columns: 62px 1fr 42px; align-items: center;
  gap: 7px; font-family: var(--mono); font-size: 10px; color: var(--ink-3);
}
.ro-year i { height: 6px; background: var(--ro); border-radius: 1px; opacity: .75; }
.ro-year b {
  text-align: right; color: var(--ink); font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* Кластери зовнішнього набору — іншим кольором, щоб не плутати з судовими. */
.cluster.alt {
  background: color-mix(in srgb, var(--c-noescape) 22%, rgba(6,8,11,0.72));
  border-color: color-mix(in srgb, var(--c-noescape) 80%, transparent);
}
.cluster.alt.cluster--dot { background: color-mix(in srgb, var(--c-noescape) 80%, transparent); }

/* Сезони — чотири стовпці однакової ширини, підпис знизу. */
.seasons {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
  align-items: end; height: 96px;
}
.season { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.season-bar { width: 70%; min-height: 3px; border-radius: 2px 2px 0 0;
  animation: grow 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.season-n { font-family: var(--mono); font-size: 10px; color: var(--ink); margin-top: 5px;
  font-variant-numeric: tabular-nums; }
.season-k { font-size: 10.5px; color: var(--ink-3); margin-top: 1px; }

/* Точка набору NoEscape — маленьке блакитне коло, клікабельне (divIcon). */
.arr-pin {
  width: 8px; height: 8px; border-radius: 50%;
  background: color-mix(in srgb, var(--c-noescape) 55%, transparent);
  border: 1.5px solid var(--c-noescape);
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
}
/* Колись колір і форма розрізняли наряд на лінії й пост на дорозі — тобто
   показували, де стоять пости. Розріз прибрано (рішення власника), і всі
   точки набору — однакові. */

/* Робочий простір: селектор і дві кнопки в один рядок. */
.ws-row { display: flex; gap: 4px; align-items: stretch; margin-bottom: 2px; }
.ws-row select {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 11px;
  padding: 6px 8px; background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 3px;
}
.ws-row select:focus { outline: none; border-color: var(--signal); }
.ws-row .ghost { flex: none; width: 30px; padding: 0; font-size: 15px; line-height: 1; }

/* ─────────────────────────── малювання на вузькому екрані

   Блок стоїть у самому кінці аркуша навмисно. Базові правила малювання лежать
   нижче за медіазапит на 760 px (так уже влаштований цей файл: після
   медіазапитів у ньому йде ще кількасот рядків звичайних правил), а за рівної
   ваги перемагає те, що написане пізніше. Мобільні правила, залишені всередині
   того медіазапиту, мовчки програвали базовим — HUD лишався посеред екрана. */

@media (max-width: 760px) {
  /* Смужка стоїть вище за все, що вже займає низ екрана: згорнуту шухляду
     (52), значок атрибуції (54) і масштаб (78). Другий аргумент env()
     обов'язковий: без нього весь calc() стає недійсним там, де вирізу немає. */
  .draw-hud {
    left: 10px; right: 10px; transform: none;
    flex-wrap: wrap; row-gap: 6px;
    bottom: calc(104px + env(safe-area-inset-bottom, 0px));
  }
  .draw-hud-kind { max-width: 10ch; }
  .draw-hud-read { flex: 1 1 auto; text-align: right; }
  /* Кнопки завжди займають увесь наступний рядок і тиснуться праворуч —
     під великий палець, і без залежності від довжини числа над ними. */
  .draw-hud-acts { flex: 1 0 100%; justify-content: flex-end; }
  .draw-hud .ghost { padding: 10px 12px; }

  /* Двадцять пікселів кнопки в рядку фігури пальцем не вціляються. */
  .imp.shape { padding: 5px 4px; gap: 6px; }
  .imp.shape .imp-btn { width: 34px; height: 34px; font-size: 13px; }
  .imp.shape input[type=checkbox] { width: 20px; height: 20px; }
}

/* Поки креслимо, низ вузького екрана має бути вільний під смужку керування.
   !important тут не примха: display у #scale виставляє інлайном сам app.js,
   коли перемальовує масштабну лінійку, а інлайновий стиль звичайним правилом
   не перебити. Клас вішає paint() у draw.js. */
.drawing-hide { display: none !important; }

/* ══════════════════════════════════════════ шари: список і каталог ══
   Дві поверхні, одна мова. Список активних шарів — щільний, робочий: у ньому
   живуть щодня. Каталог — розріджений, з обкладинками: у нього заходять
   вибирати й читати. Тому в списку рядок 30 пікселів заввишки, а в каталозі
   картка може дозволити собі три абзаци тексту. */

.lyr-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 2px 0 10px;
}
.lyr-bar-n {
  flex: 1; font-family: var(--mono); font-size: 11px;
  color: var(--ink-3); letter-spacing: 0.02em;
}

button.prime {
  background: var(--signal); color: #000; border: 0;
  font: 600 12px/1 var(--sans); letter-spacing: 0.01em;
  padding: 8px 13px; border-radius: 3px; cursor: pointer;
}
button.prime:hover { background: #ffe14d; }
button.prime:disabled { background: var(--rule-2); color: var(--ink-3); cursor: default; }

/* ─────────────────────────────────────────── список активних шарів */

.active { list-style: none; display: flex; flex-direction: column; gap: 2px; }

/* Той самий сигнал, що й у каталозі: шар на мапі — жовтий. Смужка ліворуч,
   а не рамка навколо, бо рядків буває півтора десятка й п'ятнадцять рамок
   перетворили б список на решітку. */
.ly-row {
  background: var(--panel-2);
  border: 1px solid transparent;
  border-left: 2px solid var(--signal);
  border-radius: 3px;
}
.ly-row.is-off { opacity: 0.42; border-left-color: var(--ink-3); }
.ly-row.is-drag { border-color: var(--signal); opacity: 0.9; }
.ly-row.is-slot { box-shadow: inset 0 2px 0 var(--signal); }

.row-head {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 7px;
}
.row-head > button {
  background: none; border: 0; color: var(--ink-3);
  cursor: pointer; padding: 0; line-height: 1;
  font-size: 12px; flex: none;
}
.row-head > button:hover { color: var(--ink); }
.row-grip { cursor: grab; touch-action: none; letter-spacing: -2px; }
.row-grip:active { cursor: grabbing; }
.row-eye { font-size: 9px; width: 12px; }
.row-name {
  flex: 1; min-width: 0; font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row-n {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.row-x:hover { color: var(--alert); }

.row-body {
  padding: 2px 10px 10px 26px;
  border-top: 1px solid var(--rule);
  margin-top: 2px;
}
.row-about, .card-about {
  font-size: 11.5px; line-height: 1.55; color: var(--ink-2);
  padding: 8px 0 2px;
}
.row-stat, .card-stat {
  font-size: 11px; line-height: 1.5; color: var(--ink-2);
  border-left: 2px solid var(--rule-2); padding: 2px 0 2px 8px; margin: 7px 0;
}
.row-stat b, .card-stat b { color: var(--ink); font-weight: 600; }
.row-src, .card-src {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  margin-top: 8px;
}

.active-empty {
  text-align: center; padding: 26px 12px;
  border: 1px dashed var(--rule-2); border-radius: 3px;
}
.active-empty p { color: var(--ink-3); font-size: 12px; margin-bottom: 10px; }

/* ─────────────────────────────────────────────── налаштування шару */

.set { margin: 9px 0; }
.set-lab {
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--ink-3); margin-bottom: 4px;
}
.set-val { color: var(--ink-2); }
.set-choice { display: flex; gap: 2px; }
.set-choice button {
  flex: 1; background: var(--panel); border: 1px solid var(--rule);
  color: var(--ink-2); font: 11px/1 var(--sans); padding: 6px 4px;
  cursor: pointer; border-radius: 2px;
}
.set-choice button:hover { border-color: var(--rule-2); color: var(--ink); }
.set-choice button.on {
  background: var(--signal); border-color: var(--signal); color: #000; font-weight: 600;
}
/* Підпис показує саме обраний варіант, а не всі одразу: інакше під кожним
   перемикачем стояло б два абзаци, з яких один завжди зайвий. */
.set-note {
  font-size: 10.5px; line-height: 1.5; color: var(--ink-3); margin-top: 5px;
}
.set-toggle { display: flex; align-items: center; gap: 7px; font-size: 11.5px; }
.row-op { width: 100%; }

/* ────────────────────────────────────────────────── значки шарів */

.ly-sw { flex: none; width: 10px; height: 10px; display: inline-block; }
.ly-sw.dot { border-radius: 50%; background: var(--c); }
.ly-sw.ring { border-radius: 50%; border: 1.5px solid var(--c); }
.ly-sw.diamond { background: var(--c); transform: rotate(45deg); width: 8px; height: 8px; }
.ly-sw.line { background: var(--c); height: 2px; width: 12px; }
.ly-sw.area { border: 1px solid var(--c); background: color-mix(in srgb, var(--c) 14%, transparent); }
.ly-sw.cells {
  background:
    linear-gradient(var(--c), var(--c)) 0 0 / 4px 4px no-repeat,
    linear-gradient(var(--c), var(--c)) 6px 6px / 4px 4px no-repeat;
  opacity: 0.8;
}
.ly-sw.grad { background: linear-gradient(90deg, #2a2610, #ffd400, #fff4b8); height: 4px; width: 14px; }
.ly-sw.heat { border-radius: 50%; background: radial-gradient(#fff4b8, #ffd400 45%, transparent 70%); width: 12px; height: 12px; }

/* Позначка основного шару — на картці каталогу й у списку активних. */
.card-main, .row-main {
  font-family: var(--mono); font-size: 9px; letter-spacing: .08em; text-transform: uppercase;
  color: #06080b; background: var(--c-case); border-radius: 3px; padding: 2px 5px 1px; line-height: 1.2;
}
.card-main { position: absolute; left: 7px; bottom: 7px; }
.row-main { flex: none; }
.ly-sw.glyph { color: var(--c); font-size: 11px; line-height: 10px; width: auto; }

/* ═════════════════════════════════════════════════════ каталог ══ */

/* display:flex перебиває вбудоване правило браузера для [hidden], тож
   ховати доводиться явно — інакше модал стоїть відкритим з першої секунди. */
.modal[hidden] { display: none; }

.modal {
  position: fixed; inset: 0; z-index: 4000;
  background: rgba(3, 5, 8, 0.72);
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  padding: 26px;
}
body.modal-open { overflow: hidden; }

.modal-box {
  width: min(1180px, 100%); max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--rule-2);
  border-radius: 4px; overflow: hidden;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.7);
}

.modal-top {
  display: flex; align-items: flex-start; gap: 24px;
  padding: 20px 22px 16px;
}
.modal-top h2 {
  font-family: var(--serif); font-size: 22px; font-weight: 500;
  letter-spacing: -0.01em; margin-bottom: 4px;
}
.modal-top p { color: var(--ink-3); font-size: 12px; max-width: 52ch; }

.cat-search {
  margin-left: auto; flex: none;
  display: flex; align-items: center; gap: 8px;
  background: var(--panel-2); border: 1px solid var(--rule);
  border-radius: 3px; padding: 0 12px; width: 320px; max-width: 42vw;
}
.cat-search span { color: var(--ink-3); font-size: 14px; }
.cat-search input {
  flex: 1; background: none; border: 0; outline: none;
  color: var(--ink); font: 13px var(--sans); padding: 10px 0;
}

.cat-chips {
  display: flex; flex-wrap: wrap; gap: 4px;
  padding: 0 22px 14px; border-bottom: 1px solid var(--rule);
}
.cat-chips button {
  background: var(--panel-2); border: 1px solid var(--rule);
  color: var(--ink-2); font: 11px var(--sans); padding: 5px 10px;
  border-radius: 999px; cursor: pointer;
}
.cat-chips button:hover { color: var(--ink); border-color: var(--rule-2); }
.cat-chips button.on { background: var(--raised); border-color: var(--signal); color: var(--ink); }

.cat-grid { overflow-y: auto; padding: 4px 22px 20px; flex: 1; }
.cat-empty { color: var(--ink-3); padding: 40px 0; text-align: center; }

.cat-group {
  font-family: var(--mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--ink-3);
  padding: 20px 0 10px; font-weight: 400;
}
.cat-row {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
}

.card {
  display: flex; flex-direction: column;
  background: var(--panel-2); border: 1px solid var(--rule);
  border-radius: 3px; overflow: hidden; cursor: pointer;
  transition: border-color 0.12s;
}
.card:hover { border-color: var(--rule-2); }
/* Шар у проєкті лишається підсвіченим жовтим постійно, а не лише в мить
   вибору: каталог відкривають серед роботи, і перше питання завжди «що вже
   на мапі». Обкладинка при цьому не гасне — вимкнений шар відрізняється від
   увімкненого рамкою й підписом, а не тим, що його гірше видно. */
.card.is-on {
  border-color: var(--signal);
  box-shadow: inset 0 0 0 1px rgba(255, 212, 0, 0.22);
}
.card.is-on .card-txt h3 { color: var(--signal); }
.card.is-on .card-act {
  background: rgba(255, 212, 0, 0.1); color: var(--signal);
  border-top-color: rgba(255, 212, 0, 0.3);
}
.card.is-on .card-act:hover { background: rgba(255, 212, 0, 0.18); }

.card-pv { position: relative; aspect-ratio: 2.15; background: #0b1220; }
.card-pv .pv { display: block; width: 100%; height: 100%; }
.card-flag, .card-n {
  position: absolute; top: 7px;
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.05em;
  padding: 3px 6px; border-radius: 2px;
}
.card-flag { left: 7px; background: var(--signal); color: #000; }
.card-n {
  right: 7px; background: rgba(6, 8, 11, 0.8); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.card-txt { padding: 11px 12px 12px; flex: 1; }
.card-txt h3 {
  display: flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 600; margin-bottom: 3px;
}
.card-blurb { font-size: 11.5px; color: var(--ink-2); }
.card-about { font-size: 11px; padding-top: 7px; color: var(--ink-3); }

.card-act {
  border: 0; border-top: 1px solid var(--rule);
  background: var(--panel); color: var(--ink-2);
  font: 11px var(--sans); padding: 9px; cursor: pointer; width: 100%;
}
.card-act:hover { background: var(--raised); color: var(--ink); }
.card.is-pick .card-act { background: var(--signal); color: #000; font-weight: 600; }

.modal-foot {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 22px; border-top: 1px solid var(--rule);
  background: var(--panel-2);
}
.cat-count {
  flex: 1; font-family: var(--mono); font-size: 11px; color: var(--ink-3);
}

/* Вузький екран: модал на весь екран, картки в один стовпець. Каталог тут
   робить те саме, але читати три абзаци поруч із превʼю на телефоні
   неможливо, тож довге пояснення ховається — воно лишається в списку
   активних шарів, де на нього є місце. */
@media (max-width: 720px) {
  .modal { padding: 0; }
  .modal-box { border: 0; border-radius: 0; height: 100%; }
  .modal-top { flex-direction: column; gap: 12px; padding: 14px 14px 12px; }
  .cat-search { margin-left: 0; width: 100%; max-width: none; }
  .cat-chips, .cat-grid, .modal-foot { padding-left: 14px; padding-right: 14px; }
  .cat-row { grid-template-columns: 1fr; }
  .card-about { display: none; }
}

/* Повзунок прозорості — та сама мова, що й повзунки періоду вгорі, але
   одиничний: там два бігунки на спільній доріжці, тому там абсолютне
   позиціювання, а тут воно тільки заважало б. */
.row-op {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 18px; margin: 0; background: transparent;
}
.row-op::-webkit-slider-runnable-track {
  height: 2px; background: var(--rule-2); border-radius: 1px;
}
.row-op::-webkit-slider-thumb {
  -webkit-appearance: none; cursor: grab;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--panel-2); margin-top: -5px;
}
.row-op::-webkit-slider-thumb:active { cursor: grabbing; background: var(--signal); }
.row-op::-moz-range-track { height: 2px; background: var(--rule-2); }
.row-op::-moz-range-thumb {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--panel-2);
}

/* ═════════════════════════════════════ фільтри й дашборд у шарі ══ */

/* Фільтри всередині рядка шару. Відступ, під яким стоїть решта тіла, тут
   знімається: фільтрів вісім блоків із двоколонковими заголовками, і зайві
   двадцять пікселів ліворуч ламали кожен із них. Лінія зверху лишається —
   це не ще одне налаштування, а окремий інструмент, який просто належить
   цьому шару. */
.row-panel {
  margin: 12px -8px 0 -22px; padding-top: 12px;
  border-top: 1px solid var(--rule);
  display: flex; flex-direction: column; gap: 20px;
}
.row-panel .unit:first-child, .row-panel .stack:first-child { margin-top: 0; }


/* Дашборд: майже весь екран, сітка з рівних клітинок.

   Клітинка фіксованої висоти, а не «за вмістом». Так вийшло не з естетики:
   щоб довгий перелік прокручувався всередині блока, його потрібен
   min-height: 0, а це дозволяє рядку сітки схлопнутися до самого заголовка.
   Фіксована висота знімає питання й заразом вирівнює сітку.

   Порожнечі всередині клітинки немає: заголовок і примітки не стискаються, а
   головне — графік чи перелік — росте на всю решту висоти. Саме тому графік
   на шістдесят пікселів більше не висить угорі порожнього блока.

   Висоту рядів задає не CSS, а fitDash() у catalog.js: кожен ряд отримує
   висоту за найбільшим вмістом у ньому, зі стелею, вище якої блок
   прокручується. Фіксоване число тут не працює за побудовою — кількість
   колонок залежить від ширини екрана, а отже й від того, які саме блоки
   опиняться в одному ряду. Ряд із трьох графіків має бути низьким, ряд із
   трьох переліків — високим, і на іншій ширині це вже інші ряди.

   Значення нижче лишаються запасними: вони діють до першого виміру й тоді,
   коли скрипт чомусь не відпрацював.

   grid-auto-flow: dense — щоб широкий блок, який не вліз у залишок рядка, не
   лишав по собі дірку: наступний вузький підтягується на її місце. */
/* position тут не декоративний: читач позиціюється відносно саме цієї
   коробки, а без нього — відносно всього модала. */
.dash-box { width: min(1720px, 100%); height: 100%; position: relative; }
.dash-box .modal-top { border-bottom: 1px solid var(--rule); align-items: center; }
.dash-box .modal-top > button { margin-left: auto; flex: none; }

.dash-grid {
  flex: 1; overflow-y: auto; padding: 16px 22px 24px;
  display: grid; gap: 14px; align-content: start;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  grid-auto-rows: 330px;
  grid-auto-flow: dense;
}
.dash-grid > .unit {
  margin: 0; background: var(--panel-2); min-width: 0; min-height: 0;
  border: 1px solid var(--rule); border-radius: 3px; padding: 12px 14px 14px;
  display: flex; flex-direction: column; gap: 8px;
}
.dash-grid > .unit.w2 { grid-column: span 2; }
.dash-grid > .unit.wfull { grid-column: 1 / -1; }

/* Що не росте: заголовок, перемикачі, вісь, пагінатор. Що росте: головний
   вміст блока — і саме він віддає місце примітці, а не навпаки.

   Примітці не ставиться стеля у відсотках: вона мовчки різала речення
   посередині, і скраю не було навіть смужки прокрутки, щоб це помітити.
   Натомість основний вміст має flex-basis 0 — тобто претендує лише на
   вільне місце, а примітка бере рівно стільки, скільки їй треба, і
   прокручується тільки коли клітинки не вистачає на обох. */
.dash-grid > .unit > .unit-head,
.dash-grid > .unit > .choice,
.dash-grid > .unit > .axis,
.dash-grid > .unit > .pager { flex: none; margin: 0; }
.dash-grid > .unit > .fine {
  flex: 0 1 auto; min-height: 0; overflow-y: auto; margin: 0;
}
.dash-grid > .unit > :not(.unit-head):not(.fine):not(.choice):not(.axis):not(.pager) {
  flex: 1 1 0; min-height: 0; overflow-y: auto;
}

/* Стовпчикові графіки тягнуться на всю висоту клітинки: у боковій колонці їм
   вистачало шістдесяти пікселів, тут це виглядало б загубленим. Сезони до
   цього переліку не входять: у них під стовпчиком стоїть підпис, і на
   довільній висоті він виїжджає за край. */
.dash-grid .timeline, .dash-grid .hours, .dash-grid .hours.dist {
  height: auto; min-height: 84px;
}
.dash-grid .seasons { flex: none; }
/* Хронологія — два ряди крапок фіксованої висоти. Розтягнути їх не можна,
   але й тулитися до верхнього краю нема чого: центруємо. */
.dash-grid .tl { justify-content: center; }

/* Перелік справ у дашборді. Пошук, розмір сторінки й CSV — у заголовку
   блока, бо це не дані, а інструменти над ними. */
.cases-tools { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }
.cases-tools input[type="search"] {
  width: 240px; background: var(--panel); border: 1px solid var(--rule);
  color: var(--ink); font: 12px var(--sans); padding: 5px 9px; border-radius: 3px;
}
.cases-tools input:focus { outline: none; border-color: var(--signal); }
.cases-tools select {
  background: var(--panel); border: 1px solid var(--rule); color: var(--ink-2);
  font: 11px var(--mono); padding: 5px 6px; border-radius: 3px; cursor: pointer;
}
#casesUnit table { width: 100%; }
.cases-body { min-height: 0; }

/* Виклик аналітики з мапи. Стоїть під пошуком ліворуч, де немає ні легенди,
   ні шкали, ні атрибуції — єдиний вільний кут. */
/* Нейтральна: акцент на мапі лишається один — кнопка асистента. Дві однакові
   жовті рамки одна під одною читалися б як пара рівнозначних. */
.dash-call {
  display: flex; align-items: center; gap: 7px;
  background: var(--panel); border: 1px solid var(--rule-2);
  color: var(--ink-2); font: 600 11.5px/1 var(--sans);
  padding: 9px 13px; border-radius: 4px; cursor: pointer;
}
.dash-call span { color: var(--ink-3); }
.dash-call:hover { background: var(--raised); border-color: var(--signal); }
.dash-call[hidden] { display: none; }

.pager {
  display: flex; align-items: center; gap: 6px; flex: none;
  padding-top: 8px; border-top: 1px solid var(--rule); margin: 0;
}
.pager-info {
  flex: 1; font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.pager button {
  background: var(--panel); border: 1px solid var(--rule); color: var(--ink-2);
  font: 11px var(--mono); padding: 4px 9px; border-radius: 3px; cursor: pointer;
}
.pager button:hover:not(:disabled) { color: var(--ink); border-color: var(--rule-2); }
.pager button:disabled { opacity: 0.35; cursor: default; }

@media (max-width: 1000px) {
  .dash-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 720px) {
  .dash-grid { grid-template-columns: 1fr; padding: 12px 14px 20px; }
  .dash-grid > .unit.w2 { grid-column: span 1; }
  .cases-tools input { width: 100%; }
  .cases-tools { width: 100%; margin-top: 6px; }
}

/* ═══════════════════════════════════════════════ читач справи ══
   Панель праворуч, перелік лишається ліворуч: у цьому й сенс — клацнув
   рядок, прочитав, натиснув «наступна», не втрачаючи місця у списку. */
/* Панель живе на верхньому рівні, а не всередині дашборда: справу відкривають
   і з переліку, і з попапа на мапі, і в другому випадку тягти за собою весь
   дашборд заради одного рішення не було б за що. z-index вищий за модал —
   читач лягає поверх нього, коли обидва відкриті. */
/* Ширина читалки — змінна, бо від неї напряму залежить ЧИТНІСТЬ тексту.
   Сторінка реєстру не переливається вужче за 1000 px, тож fitReaderFrame()
   показує її цілком і зменшує через transform: scale(k), де
   k = ширина_панелі / 1000. А масштаб діє на все, включно з тим невеликим
   скрол-контейнером, у який реєстр кладе текст постанови. При 58% на екрані
   1024 px виходило k = 0.60 — і те вікно ставало настільки дрібним, що
   гортати текст було майже неможливо.

   Тому на вужчих екранах панель займає більше місця: мапа під час читання
   все одно на другому плані, а k тримається не нижче ~0.85. Нижче 900 px
   читалка й так на весь екран (див. медіа-запит далі). */
:root { --reader-w: min(940px, 58%); }
@media (max-width: 1600px) { :root { --reader-w: min(940px, 76%); } }
@media (max-width: 1100px) { :root { --reader-w: min(940px, 92%); } }

.reader {
  position: fixed; top: var(--masthead-h); right: 0; bottom: 0; z-index: 4200;
  width: var(--reader-w);
  display: flex; flex-direction: column;
  background: var(--panel); border-left: 1px solid var(--rule-2);
  box-shadow: -20px 0 50px rgba(0, 0, 0, 0.45);
}
.reader[hidden] { display: none; }
/* Сітка звужується під панель, і fitDash() перераховує ряди під нову
   кількість колонок — тому виклик є в openReader і closeReader. */
body.is-reading .dash-grid { padding-right: calc(var(--reader-w) + 22px); }

.reader-top {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--rule); flex: none;
}
.reader-id { flex: 1; font-size: 12.5px; color: var(--ink-2); }
.reader-id b { color: var(--signal); font-family: var(--mono); }
.reader-x {
  background: none; border: 0; color: var(--ink-3);
  font-size: 13px; cursor: pointer; padding: 2px 4px;
}
.reader-x:hover { color: var(--alert); }

.reader-meta {
  flex: none; max-height: 34%; overflow-y: auto;
  padding: 11px 16px; border-bottom: 1px solid var(--rule);
  background: var(--panel-2);
}
.reader-meta dl {
  display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 0;
}
.reader-meta dt {
  font-family: var(--mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--ink-3);
}
.reader-meta dd { margin: 0; font-size: 12px; color: var(--ink); }
.reader-snip {
  margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--rule);
  font-size: 11.5px; line-height: 1.55; color: var(--ink-2);
}

/* Реєстр неквапливий, тож поки він їде — підпис, а не порожній прямокутник.
   Сама сторінка світла, і різкий білий на темному тлі б'є по очах; трохи
   приглушуємо, поки вона не в фокусі. */
.reader-frame { position: relative; flex: 1; min-height: 0; background: #fff;
  overflow: hidden; }
/* Ширину й масштаб виставляє fitReaderFrame(): сторінка реєстру не
   переливається нижче 988 px, тож її показуємо в повну ширину й зменшуємо
   цілком, замість гортати вбік. */
.reader-frame iframe {
  border: 0; display: block; transform-origin: 0 0;
  opacity: 0; transition: opacity 0.2s;
}
.reader-frame.ready iframe { opacity: 1; }
.reader-wait {
  position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center;
  background: var(--panel); color: var(--ink-3);
  font-family: var(--mono); font-size: 11px;
}
.reader-frame.ready .reader-wait { display: none; }

.reader-foot {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 10px 16px; border-top: 1px solid var(--rule);
}
.reader-foot button {
  background: var(--panel-2); border: 1px solid var(--rule); color: var(--ink-2);
  font: 11px var(--mono); padding: 5px 10px; border-radius: 3px; cursor: pointer;
}
.reader-foot button:hover:not(:disabled) { color: var(--ink); border-color: var(--rule-2); }
.reader-foot button:disabled { opacity: 0.35; cursor: default; }
.reader-pos {
  flex: 1; text-align: center; font-family: var(--mono);
  font-size: 10.5px; color: var(--ink-3);
}
.reader-foot a { font-family: var(--mono); font-size: 11px; color: var(--signal); }

#list tr.reading { background: rgba(255, 212, 0, 0.09); }
#list tr.reading td.no b { color: var(--signal); }
#list td.no b { font-family: var(--mono); font-weight: 400; color: var(--ink-2); }
#list td.go { width: 26px; text-align: right; }
.row-map {
  background: none; border: 0; color: var(--ink-3);
  cursor: pointer; font-size: 12px; padding: 0 2px;
}
.row-map:hover { color: var(--signal); }

/* На вузькому екрані читач займає все: тримати поруч перелік і сторінку
   реєстру на 375 пікселях однаково не вийде. */
@media (max-width: 900px) {
  .reader { width: 100%; top: 0; }
  body.is-reading .dash-grid { padding-right: 22px; }
}

/* Коли реєстр не відповів: підпис перестає бути просто підписом і дає вихід. */
.reader-wait.is-late { flex-direction: column; gap: 8px; text-align: center; }
.reader-wait.is-late a { color: var(--signal); font-family: var(--mono); }

/* Кнопка «читати тут» у попапі на мапі: виглядає як посилання, бо веде до
   тексту рішення, але нікуди не відводить — відкриває панель поруч. */
.leaflet-popup-content .open-case {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 11.5px; color: var(--ua);
  text-decoration: underline; text-underline-offset: 2px;
}
.leaflet-popup-content .open-case:hover { color: var(--signal); }

/* Мобільне положення кнопок мапи — навмисно в самому кінці аркуша.

   Медіазапит не додає специфічності, тож правило з блоку на 760 пікселів
   програє базовому `.dash-call`, який оголошений нижче за нього. Це вже
   ставалося в цьому файлі, тому мобільні перекриття для пізніх секцій
   живуть тут. */
@media (max-width: 760px) {
  .dash-call { padding: 8px 11px; }
}

/* ══════════════════════════════════════ кнопки масштабу мапи ══
   Leaflet уміє поставити їх лише в куток контейнера, а треба під легенду,
   висота якої змінюється разом із її вмістом. Тому сам елемент керування
   переноситься в праву напрямну (app.js), а тут йому дається вигляд решти
   накладок — типовий білий квадрат Leaflet у цій мапі виглядав чужим. */
.rail .leaflet-control-zoom {
  margin: 0; border: 0; box-shadow: none;
  display: flex; flex-direction: column; gap: 1px;
}
.rail .leaflet-control-zoom a {
  width: 30px; height: 30px; line-height: 28px;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  border: 1px solid var(--rule); border-radius: 5px;
  color: var(--ink-2); font-size: 17px; font-weight: 400;
  backdrop-filter: blur(8px);
}
.rail .leaflet-control-zoom a:hover {
  background: var(--raised); color: var(--ink); border-color: var(--rule-2);
}
.rail .leaflet-control-zoom a.leaflet-disabled {
  color: var(--rule-2); background: color-mix(in srgb, var(--panel) 70%, transparent);
}

/* ═══════════════════════════════════════════════════ ворота адміністратора */
/* Колись знак RTF ставав тут кнопкою воріт (.gate-key) і першою зупинкою
   Tab на сторінці. Тепер він посилання на Головну, а ворота відчиняє
   Alt-клік чи ?gate=1 (gate.js) — окремого вигляду їм не треба. */

.gate {
  position: fixed; z-index: 8000; width: 232px;
  background: var(--panel-2); border: 1px solid var(--rule-2);
  border-radius: 4px; padding: 12px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .55);
}
.gate-t {
  font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 9px;
}
.gate-row { display: flex; gap: 7px; }
.gate-in {
  flex: 1; min-width: 0; background: var(--void);
  border: 1px solid var(--rule-2); border-radius: 3px;
  color: var(--ink); font-family: var(--mono); font-size: 15px;
  letter-spacing: .22em; text-align: center; padding: 7px 8px;
}
.gate-in:focus { outline: none; border-color: var(--signal); }
.gate-go, .gate-lock {
  background: var(--signal); color: #000; border: 0; border-radius: 3px;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  padding: 0 12px; cursor: pointer; white-space: nowrap;
}
.gate-lock { background: var(--raised); color: var(--ink-2); padding: 8px 12px; }
.gate-go:disabled { opacity: .5; cursor: default; }
.gate-note {
  margin: 9px 0 0; font-family: var(--mono); font-size: 10px;
  color: var(--ink-3); min-height: 12px;
}

/* Усе, що з'явиться далі під замком, ховається одним правилом. Показане
   лишається показаним — публічне ми не чіпаємо. */
[data-admin] { display: none; }
.is-admin [data-admin] { display: revert; }

/* Позначка адмінського режиму. Червона й у шапці — підвищений доступ має бути
   видно, а не пригадуватись. Кнопка виходу поруч, а не в налаштуваннях:
   найчастіша причина вийти — «зараз хтось гляне на екран». */
.gate-flag {
  display: flex; align-items: center; gap: 8px;
  margin-left: 18px; padding-left: 18px;
  border-left: 1px solid var(--rule-2);
}
.gate-flag-on {
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: #fff; background: var(--alert);
  padding: 5px 8px 4px; border-radius: 3px; line-height: 1; white-space: nowrap;
}
.gate-flag-out {
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
  color: var(--alert); background: transparent;
  border: 1px solid var(--alert); border-radius: 3px;
  padding: 5px 9px 4px; cursor: pointer; white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.gate-flag-out:hover { background: var(--alert); color: #fff; }
.gate-flag-out:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* Вузька шапка: підпис зникає, лишається сама позначка й вихід. */
@media (max-width: 1180px) {
  .gate-flag { margin-left: 12px; padding-left: 12px; }
  .gate-flag-out { font-size: 0; padding: 5px 7px 4px; }
  .gate-flag-out::after { content: 'вийти'; font-size: 10px; }
}

/* Підпис зони гірської допомоги. Коло радіусом у десять кілометрів без назви
   читається як межа території — саме через це його двічі прийняли за кордон
   сусідньої держави. */
.zone-label {
  background: none; border: none; box-shadow: none;
  color: color-mix(in srgb, var(--ok, #22c55e) 80%, transparent);
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
  text-shadow: 0 0 5px #000, 0 0 3px #000; white-space: normal;
  max-width: 180px; text-align: center; pointer-events: none;
}
.zone-label::before { display: none; }

/* Підпис контуру ділянки. Без підкладки й рамки: контур і так великий, а
   плашка посеред нього читалася б як ще один об'єкт. */
.area-label {
  background: none; border: none; box-shadow: none;
  color: color-mix(in srgb, var(--c-muted) 70%, #fff);
  font-family: var(--mono); font-size: 10px; letter-spacing: .03em;
  text-shadow: 0 0 6px #000, 0 0 3px #000; white-space: normal;
  max-width: 150px; text-align: center; pointer-events: none;
}
.area-label::before { display: none; }

/* ─────────────────────────────── стопки й місця груп на мапі

   Два знаки, що несуть число, і обидва — не «кластер алгоритму», а факт даних.
   Коло з числом — кілька справ з ОДНАКОВОЮ координатою; його обвід повторює
   форму крапки (суцільний, кільце, пунктир), бо стопка обіцяє стільки ж,
   скільки її найслабша справа. Квадрат — місце групи NoEscape: квадрат, бо
   набір розкладав групу решіткою, і щоб жодного разу не сплутати його з
   крапкою людини. */
.stack {
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; color: #fff;
  background: color-mix(in srgb, var(--pin) 30%, rgba(6,8,11,0.78));
  border: 2px solid var(--pin);
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  font-variant-numeric: tabular-nums; line-height: 1;
  box-shadow: 0 0 0 1px rgba(6,8,11,0.7);
}
.stack--ring { background: color-mix(in srgb, var(--pin) 14%, rgba(6,8,11,0.6)); border-width: 1.5px; }
.stack--vague { background: color-mix(in srgb, var(--pin) 8%, rgba(6,8,11,0.5)); border: 1.5px dashed var(--pin); }
/* Місце групи — світлий відтінок кольору справ із темним обведенням. Колись
   квадрат був майже білий (--ink 88%), а білий за спільною палітрою означає
   «вибране»: 7 532 особи в місцях груп читалися як виділені. */
.blk {
  display: flex; align-items: center; justify-content: center;
  border-radius: 3px; color: #06080b;
  background: color-mix(in srgb, var(--c-case) 62%, #ffffff);
  border: 1.5px solid rgba(6,8,11,0.85);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--c-case) 70%, transparent);
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  font-variant-numeric: tabular-nums; line-height: 1;
}
/* Число, що налізло на більше сусіднє (app.js, declutterNumbers), —
   ховаємо; значок і підказка лишаються. */
.rtf-mk > .num-off { color: transparent !important; }
/* Місце групи NoEscape без справи — те саме, але відтінком NoEscape. */
.blk.blk-alt {
  background: color-mix(in srgb, var(--c-noescape) 62%, #ffffff);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--c-noescape) 70%, transparent);
}
.legend .sw.blk-sw {
  border-radius: 2px; width: 10px; height: 10px; margin-left: 0;
  background: color-mix(in srgb, var(--c-case) 62%, #ffffff); vertical-align: -1px;
}
.legend .sw.blk-sw.alt { background: color-mix(in srgb, var(--c-noescape) 62%, #ffffff); }
/* На огляді (z ≤ 8) знак місця групи — порожній контур, і ключ легенди теж. */
.legend .sw.blk-sw.is-lo {
  background: transparent; border: 1.5px solid color-mix(in srgb, var(--c-case) 70%, #ffffff);
}
.legend .sw.stack-sw {
  width: 10px; height: 10px; margin-left: 0; vertical-align: -1px;
  background: color-mix(in srgb, var(--c-case) 30%, #06080b); border: 2px solid var(--c-case);
}

/* Перелік справ у картці стопки чи місця групи. */
.leaflet-popup-content .pop-list {
  list-style: none; margin: 6px 0 4px; padding: 0;
  max-height: 180px; overflow-y: auto;
  border-top: 1px solid var(--rule);
}
.leaflet-popup-content .pop-list li {
  display: flex; justify-content: space-between; gap: 8px; align-items: baseline;
  padding: 3px 0; border-bottom: 1px solid var(--rule); font-size: 11px;
}
.leaflet-popup-content .pop-list li span { color: var(--ink-2); }
.leaflet-popup-content .pop-list .open-case { white-space: nowrap; font-size: 10.5px; }

/* ─────────────────────── рядок розкладки під шапкою

   Скільки справ вибірки стало точками і куди поділася решта. Стоїть у правій
   напрямній першим, одразу під числами шапки, які він уточнює. */
.shown-line {
  max-width: 320px; padding: 7px 10px;
  font-size: 10.5px; line-height: 1.5; color: var(--ink-2);
}
.shown-line b { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.shown-line .shown-go {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  color: var(--signal); text-align: left;
  text-decoration: underline dotted; text-underline-offset: 2px;
}
.shown-line .shown-go b { color: var(--signal); }
.shown-line .shown-go:hover { color: var(--ink); }
.shown-line[hidden] { display: none; }
body.light-base .shown-line { color: var(--ink-2); }

/* ───────────────────────────── повнота на хронології

   Останні місяці реєстр ще доповнює: заштриховано, над стовпцем — яку частку
   справ уже видно. 2023 рік у корпусі майже не зібраний — приглушено. Без
   цього спад наприкінці графіка й провал на початку читалися як події. */
.timeline .bar { position: relative; }
.timeline .bar.partial { overflow: visible; }
.timeline .bar.partial::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: 2px 2px 0 0;
  background: repeating-linear-gradient(135deg,
    rgba(6,8,11,0.6) 0 2px, transparent 2px 5px);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-2) 55%, transparent);
}
.timeline .bar em {
  position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
  margin-bottom: 2px; font-style: normal; white-space: nowrap;
  font-family: var(--mono); font-size: 8px; color: var(--ink-3);
  pointer-events: none;
}
.timeline .bar.thin { opacity: 0.4; }
.timeline .bar.thin.out { opacity: 0.2; }
.tl-span.thin {
  background: repeating-linear-gradient(90deg, var(--ink-3) 0 3px, transparent 3px 6px);
  height: 7px; opacity: .9;
}
.ro-year { grid-template-columns: 62px 1fr auto; }
.ro-year b em { font-style: normal; color: var(--ink-3); }

/* ═══════════════════════════════════ доступність: фокус, рух, схованки ══ */

/* Видимий фокус для всього, чим керують з клавіатури. :where — нульова
   специфічність: власні правила фокуса окремих елементів (поля пошуку з
   жовтою рамкою, кнопки шапки) важать більше й лишаються як були. */
:where(button, a[href], [role="button"], [tabindex]:not([tabindex="-1"]), select,
  input[type="range"], input[type="checkbox"], summary):focus-visible {
  outline: 2px solid var(--signal); outline-offset: 2px;
}
.cat-search:focus-within { border-color: var(--signal); }
/* Вікно чи картка, що отримали фокус програмно (tabindex="-1"): рамка
   навколо всього вікна тільки заважала б. */
.dash-box:focus, .dossier:focus { outline: none; }

/* Лише для екранного читача: підпис таблиці, назви порожніх стовпців. */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* «Перелік знаків у кадрі» — видно лише у фокусі, як посилання «до змісту».
   Ховаємо так само, як .sr-only (1×1 px, clip-path), а не зсувом угору:
   translateY(-200%) давав лише −56 px, а .canvas починається на 62 px, тож
   жовта плашка стояла на y = 18 поверх підзаголовка шапки (на телефоні — на
   y = 0 з-під «←» і «RTF»), хоча фокусу на ній не було. */
.sr-jump {
  position: absolute; left: 12px; top: 12px; z-index: 900;
  width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
  border-radius: 4px; cursor: pointer;
  background: var(--signal); color: #000;
  font: 600 12px/1 var(--sans);
}
.sr-jump:focus {
  width: auto; height: auto; padding: 8px 12px; margin: 0; overflow: visible; clip-path: none;
  outline: 2px solid var(--ink); outline-offset: 2px;
}

/* Посилання на справу, якої в даних немає (case=…): коротке пояснення
   поверх мапи замість мовчазного порожнього виду. */
.case-missing {
  position: absolute; z-index: 950; left: 50%; top: 16px; transform: translateX(-50%);
  max-width: min(92%, 420px); padding: 10px 14px; border-radius: 8px;
  background: var(--panel, #0d1217); color: var(--ink); border: 1px solid var(--c-muted);
  font: 500 13px/1.4 var(--sans); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
}

/* Системне «зменшити рух»: анімації стовпців, переходи панелей, плавна
   прокрутка — миттєво. Мапа перестає літати окремо (app.js, REDUCED). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}

/* ═══════════════════════════════ картка на мапі: місце, знак, перелік ══ */

/* Картка знака в #dossier (телефон, перелік у кадрі) — той самий зміст, що в
   попапі Leaflet, тож і вигляд той самий. */
.card-pop { font-size: 12px; line-height: 1.5; }
.card-pop h3 { font-family: var(--serif); font-size: 14px; margin: 0 26px 4px 0; }
.card-pop dl {
  display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; margin: 8px 0;
  padding: 8px 0; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.card-pop dt { color: var(--ink-3); font-size: 11px; }
.card-pop dd {
  text-align: right; font-family: var(--mono); font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.card-pop .open-case {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 11.5px; color: var(--ua);
  text-decoration: underline; text-underline-offset: 2px; text-align: left;
}
.card-pop .open-case:hover { color: var(--signal); }
.card-pop .pop-list {
  list-style: none; margin: 6px 0 4px; padding: 0; border-top: 1px solid var(--rule);
}
.card-pop .pop-list li {
  display: flex; justify-content: space-between; gap: 8px; align-items: baseline;
  padding: 3px 0; border-bottom: 1px solid var(--rule); font-size: 11px;
}
.card-pop .pop-list li span { color: var(--ink-2); }
.card-pop .pop-list .open-case { white-space: nowrap; font-size: 10.5px; }

/* Картка місця з пошуку. */
.card-split { font-size: 12px; color: var(--ink-2); line-height: 1.5; margin: 0 0 6px; }
.card-split b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.card-acts { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
.card-acts .ghost, .card-back {
  font: 11.5px var(--sans); padding: 6px 10px; border-radius: 3px; cursor: pointer;
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--rule-2);
}
.card-acts .ghost:hover, .card-back:hover { border-color: var(--signal); }
.card-back { margin: 0 0 8px; }
.dossier .dsr b { font-variant-numeric: tabular-nums; }

/* Перелік знаків у кадрі. */
.frame-list { list-style: none; margin: 4px 0 0; padding: 0; }
.frame-list li { border-bottom: 1px solid var(--rule); }
.frame-list button {
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 6px 2px; font: 12px/1.4 var(--sans); color: var(--ink-2);
}
.frame-list button:hover { color: var(--ink); }

/* Затемнення областей поза проєктом — ключ у легенді. */
.legend .sw.mask-sw {
  border-radius: 2px; width: 12px; height: 9px; margin-left: 0; vertical-align: -1px;
  background: repeating-linear-gradient(135deg, #2a3542 0 2px, #06080b 2px 4px);
  box-shadow: 0 0 0 1px var(--rule-2);
}

/* Лінійний масштаб Leaflet — у тон решти накладок. */
.leaflet-control-scale { margin-left: 12px !important; margin-bottom: 10px !important; }
.leaflet-control-scale-line {
  background: color-mix(in srgb, var(--panel) 80%, transparent);
  border-color: var(--ink-3); color: var(--ink-2);
  font-family: var(--mono); font-size: 10px; line-height: 1.4; padding: 0 5px;
}

/* ═══════════════════════════════════════ аналітика як дослідницький вигляд ══ */

/* Позначка блока, що не залежить від фільтрів. Колись підзаголовок казав
   «усе рахується за фільтрами», а сім блоків від них не залежали. */
.unit-static {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.04em;
  color: var(--ink-3); border: 1px dashed var(--rule-2); border-radius: 3px;
  padding: 1px 6px; white-space: nowrap;
}
/* Блок, на який вказує посилання dash=<id>, — коротко підсвічено. */
.dash-grid > .unit.is-target { border-color: var(--signal); box-shadow: 0 0 0 1px var(--signal); }
.dash-grid > .unit { transition: border-color .6s, box-shadow .6s; }

/* Злитий румунський блок: підзаголовки частин. */
.ro-merged { display: flex; flex-direction: column; gap: 6px; }
.ro-merged .sub-head {
  display: flex; justify-content: space-between; gap: 8px; align-items: baseline;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-3);
  border-top: 1px solid var(--rule); padding-top: 8px; margin-top: 4px;
}
.ro-merged .sub-head:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.ro-merged .tl { min-height: 70px; }

/* Заголовки таблиці справ — кнопки сортування. */
#list thead th {
  position: sticky; top: 0; z-index: 1; background: var(--panel-2);
  text-align: left; padding: 4px 10px; border-bottom: 1px solid var(--rule-2);
  font-family: var(--mono); font-size: 9.5px; font-weight: 400;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); white-space: nowrap;
}
#list thead th button {
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit;
}
#list thead th button::after { content: attr(data-arrow); margin-left: 4px; color: var(--signal); }
#list thead th.on { color: var(--ink); }
#list thead th button:hover { color: var(--ink); }
#list td.no .row-open {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 12px; color: var(--ink-2);
}
#list tr.reading td.no .row-open, #list td.no .row-open:hover { color: var(--signal); }
#list td.go .row-map {
  background: none; border: 0; cursor: pointer; color: var(--ink-3); font-size: 14px;
}
#list td.go .row-map:hover { color: var(--signal); }
