/* Оформлення медичного модуля. Окремим файлом, а не в styles.css: той зараз
   править інша сесія, і правка в чотири руки вже двічі коштувала часу.
   І не всередині med.js: CSS у рядку JS ламає перевірку осиротілих викликів —
   вона бачила var() і color-mix() як виклики неіснуючих функцій, 38 хибних тривог. */
/* ⚠ ВИРІЗ ТЕЛЕФОНА. Плашка стоїть найпершою в #app, тобто саме вона впирається
   в годинник і камеру. Без запасу зверху текст ховається під ними — власник
   показав знімком: видно «ПОКАЗОВИЙ ПРОХІД… о не зберігається», а заголовок
   екрана наполовину під вирізом.
   Той самий запас у застосунку вже стоїть на .header і .overlay — беремо ту саму
   змінну, щоб не розійтись. */
.med-flag{background:var(--text);color:var(--bg);font-size:11px;font-weight:700;
  text-align:center;padding:calc(5px + var(--safe-t)) 5px 5px;letter-spacing:.3px;
  position:relative;display:flex;align-items:center;justify-content:center;gap:8px}
/* Хрестик праворуч, поверх тексту: у вузькому екрані підпис займає всю ширину,
   і місця «поруч» для кнопки просто немає. */
.med-flag-x{position:absolute;right:4px;top:50%;transform:translateY(-50%);
  background:transparent;border:0;color:inherit;opacity:.75;cursor:pointer;
  display:flex;align-items:center;padding:6px}
.med-flag-x:hover{opacity:1}
.med-note{border-left:3px solid var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);
  padding:10px 12px;font-size:13px;margin-bottom:12px}
.med-note b{display:block;margin-bottom:3px}
.med-warn{border-left:3px solid var(--danger);background:color-mix(in srgb,var(--danger) 10%,transparent);
  padding:10px 12px;font-size:13px;margin-bottom:12px}
.med-warn b{display:block;margin-bottom:3px}
.med-pill{display:inline-flex;align-items:center;padding:3px 9px;border-radius:999px;
  font-size:11.5px;font-weight:700;white-space:nowrap}
.med-p-new{background:color-mix(in srgb,var(--accent) 18%,transparent);color:var(--accent-2)}
.med-p-work{background:color-mix(in srgb,var(--pend) 15%,transparent);color:var(--pend)}
.med-p-ok{background:color-mix(in srgb,var(--ok) 15%,transparent);color:var(--ok)}
.med-p-warn{background:color-mix(in srgb,var(--warn) 18%,transparent);color:var(--warn)}
.med-p-bad{background:color-mix(in srgb,var(--danger) 14%,transparent);color:var(--danger)}
.med-sla{font-size:11.5px;font-weight:700}
.med-sla.ok{color:var(--ok)}.med-sla.warn{color:var(--warn)}.med-sla.bad{color:var(--danger)}
.med-kv{display:flex;justify-content:space-between;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--line-2);font-size:14px}
.med-kv:last-child{border-bottom:none}
.med-kv span{color:var(--muted)}.med-kv b{font-weight:700;text-align:right}
/* Рядок, який можна правити: поле займає праву частину і ВИГЛЯДАЄ як поле —
   інакше ніхто не здогадається, що туди можна натиснути. */
.med-kv-edit{align-items:center}
.med-kv-edit input,.med-kv-edit select{flex:1 1 55%;min-width:0;max-width:62%;
  border:1px solid var(--line);background:var(--surface);color:var(--text);
  border-radius:0;padding:6px 8px;font:inherit;font-size:14px;text-align:right}
.med-kv-edit select{text-align:left}
.med-step{display:flex;gap:10px;padding:10px 0;border-bottom:1px solid var(--line-2);font-size:13.5px}
.med-step .n{flex:0 0 22px;height:22px;border-radius:999px;background:var(--surface-2);
  color:var(--muted);font-size:11px;font-weight:800;display:flex;align-items:center;justify-content:center}
.med-step.done .n{background:var(--ok);color:#fff}
.med-step.now .n{background:var(--accent);color:#fff}
.med-step b{display:block;font-weight:700}
.med-step i{font-style:normal;color:var(--muted);font-size:12.5px}
.med-fld{display:block;margin-bottom:12px}
.med-fld>span{display:block;font-size:12.5px;font-weight:700;color:var(--muted);margin-bottom:5px}
.med-fld input,.med-fld select,.med-fld textarea{width:100%;padding:12px;border:1px solid var(--line);
  background:var(--surface);font:inherit;font-size:15px;color:var(--text);border-radius:0}
.med-fld textarea{min-height:76px;resize:vertical}

/* ⚠ Рядок зі строком висів ПОСЕРЕДИНІ рядка, хоча решта тексту зліва.
   Причина: сам рядок — це <button>, а в кнопки типове вирівнювання по центру;
   решту тексту рятували вкладені блоки, а цей лежав прямо в кнопці.
   Побачив на знімку, а не в розмітці — у розмітці все виглядало правильно. */
.med-sla{text-align:left}

/* Картка хворого — історія візитів. Те, заради чого модуль існує і що я
   пропустив у першому показі: медик читає це ПЕРЕД тим, як щось призначати. */
/* Знімок рентгена в особовій справі. Той самий вигляд, що й запис візиту:
   для медика це такий самий рядок історії, тільки джерело — тека на Диску. */
.med-shot{border-left:2px solid var(--line);padding:8px 0 8px 12px;margin-top:10px}
.med-shot:first-of-type{border-left-color:var(--accent)}
.med-shot-top{display:flex;justify-content:space-between;gap:12px;align-items:baseline;margin-bottom:4px}
.med-shot-top b{font-weight:700;font-size:14px}
.med-shot-top span{color:var(--muted);font-size:12.5px;white-space:nowrap}
/* Назва файлу може бути довга і без пробілів — рвемо, а не розсуваємо картку. */
.med-shot-name{color:var(--muted);font-size:12.5px;margin-bottom:6px;overflow-wrap:anywhere}
.med-shot .btn{text-align:center;text-decoration:none}
.med-visit{border-left:2px solid var(--line);padding:8px 0 8px 12px;margin-top:10px}
.med-visit:first-of-type{border-left-color:var(--accent)}
.med-visit-top{display:flex;justify-content:space-between;gap:12px;align-items:baseline;margin-bottom:4px}
.med-visit-top b{font-weight:700;font-size:14px}
.med-visit-top span{color:var(--muted);font-size:12.5px;white-space:nowrap}
.med-visit-line{color:var(--muted);font-size:13px;line-height:1.5}
.med-p-grey{background:var(--surface-2);color:var(--muted)}

/* ── ДОШКА СТАТУСІВ. Стовпці як у CRM, але гортаються вбік ────────────────────
   ⚠ Тягати пальцем не даємо навмисно: на 375 пікселях це промах на промаху, а
   кожен промах міняє стан живої заявки. Переміщення — кнопкою. */
/* Зовнішня коробка лише гортається; рядок стовпців — усередині. */
.med-board-in { display: flex; gap: 10px; align-items: stretch; min-height: 100%; }
.med-board { padding: 4px 0 10px;
  -webkit-overflow-scrolling: touch; }
.med-col { flex: 0 0 210px; background: var(--surface-2); border: 1px solid var(--line);
  padding: 8px; display: flex; flex-direction: column; gap: 8px; }
/* ⚠ ШАПКА СТОВПЦЯ ЇДЕ ЗА ЛЮДИНОЮ. Власник: «коли я гортаю вниз, перший рядок
   має бути закріплений і крутитися разом зі мною». На довгому стовпці інакше
   незрозуміло, у якому ти статусі: назви лишились угорі, а картки під ними всі
   схожі.
   ⚠ top: 0 — бо прилипає вона до верху ДОШКИ, а не сторінки: саме дошка тепер
   те, що гортається. Спершу я поставив 55 (заміряна висота смуги пошуку) —
   і не спрацювало взагалі, бо рахунок іде не від сторінки.
   ⚠ Від'ємні поля компенсують падінг стовпця, щоб тло смуги дотягувалось до
   країв, — інакше крізь щілини по боках видно картки, що проїжджають під нею. */
.med-col-h { display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  position: sticky; top: 0; z-index: 6;
  /* ⚠ ТЕМНА, А НЕ СІРА. Власник: «першу строку ти закріпив, але давай її якось
     відділимо, чорною чи що, щоб виглядало нормально і око не ламало».
     Сіре тло шапки збігалося з тлом стовпця, і закріплений рядок читався як
     частина списку — картки просто зникали під ним без пояснення. Темна смуга
     каже сама за себе: це заголовок, а не ще одна картка. */
  background: var(--text); color: var(--bg);
  margin: -8px -8px 0; padding: 9px 10px; }
.med-col-h b { font-weight: 700; }
.med-col-h span { color: var(--bg); opacity: .65; font-weight: 700; }
.med-col-empty { color: var(--faint); font-size: 12px; padding: 10px 0; text-align: center; }
.med-cardlet { background: var(--surface); border: 1px solid var(--line); }
.med-cardlet.special { border-left: 3px solid var(--danger); }
.med-cardlet-b { display: block; width: 100%; text-align: left; background: transparent;
  border: none; font: inherit; color: inherit; padding: 9px 10px; cursor: pointer; }
.med-cardlet-b b { display: block; font-size: 13.5px; font-weight: 700; }
.med-cardlet-b span { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.med-cardlet-b i { display: block; font-size: 11.5px; color: var(--faint); font-style: normal; margin-top: 3px; }
.med-move { width: 100%; border: none; border-top: 1px solid var(--line); background: transparent;
  font: inherit; font-size: 11.5px; font-weight: 700; color: var(--accent-2); padding: 7px 8px;
  cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 4px; }
.med-move:active { background: var(--surface-2); }
.med-move svg { vertical-align: -2px; }

/* ── ГІСТОГРАМА: СТОВПЦІ, А НЕ СМУГИ ─────────────────────────────────────────
   ⚠ Спершу я зробив горизонтальні смуги і назвав це гістограмою. Власник
   поправив, і поправив по суті: горизонтальна смуга читається як «наскільки
   заповнено», а гістограма — це порівняння висот. Для питання «чого більше»
   потрібні саме стовпці: око порівнює висоти швидше за довжини, бо всі вони
   починаються з однієї лінії.
   Висота стовпця рахується в пікселях від сталої висоти поля, а не у відсотках:
   відсоток від батька, у якого висота задана вмістом, дає нуль. */
.med-cols { display: flex; align-items: flex-end; gap: 6px; padding: 6px 0 0; }
.med-col2 { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-width: 0; }
.med-col2 .v { font-size: 13px; font-weight: 800; line-height: 1.1; margin-bottom: 4px; }
.med-col2 .b { width: 100%; background: var(--accent); border-radius: 2px 2px 0 0; }
.med-col2 .b.bad { background: var(--danger); }
.med-col2 .b.zero { background: var(--line); }
.med-cols-base { height: 2px; background: var(--line); margin-top: 0; }
.med-cols-lbl { display: flex; gap: 6px; margin-top: 6px; }
.med-cols-lbl span { flex: 1 1 0; min-width: 0; font-size: 10px; line-height: 1.15;
  text-align: center; color: var(--muted); overflow-wrap: anywhere; }

/* Кільцева діаграма: показує ЧАСТКУ від цілого, і саме тому стоїть лише на
   «Звідки заявки». Загальне число — у центрі, щоб його не шукати по підписах. */
.med-donut { display: flex; justify-content: center; padding: 6px 0 10px; }
.med-share { color: var(--muted); font-weight: 400; }

/* ── ДОШКА НА ВЕСЬ ЕКРАН І РОБОТА З НОУТБУКА ──────────────────────────────────
   Власник: якщо обрано «Стовпцями», при вході в «Заявки» дошка має займати
   майже весь екран; і окремо — щоб застосунок був придатний з ноутбука.

   ⚠ ЗНІМАЄМО МЕЖУ ШИРИНИ ТІЛЬКИ ДЛЯ ДОШКИ, а не для всього застосунку. Списки
   лишаються вузькими навмисно: рядок на весь монітор читати важче, ніж рядок
   у колонці, і на телефоні вигляд не має відрізнятись. Дошка — інша річ: її
   сенс у тому, щоб бачити всі стовпці одразу. */
.page.med-wide { max-width: 100%; padding-left: 10px; padding-right: 10px; }
/* ⚠ ДОШКА ГОРТАЄТЬСЯ САМА, А НЕ РАЗОМ ЗІ СТОРІНКОЮ. Це не оформлення, а єдиний
   спосіб виконати вимогу «шапка стовпця закріплена і крутиться зі мною».
   Чому: у дошки вже стоїть overflow-x для гортання вбік, а елемент із overflow
   стає для своїх нащадків тим, відносно чого рахується прилипання. Тобто шапка
   всередині стовпця прилипала до ДОШКИ, а гортали ми сторінку — і шапка просто
   їхала вгору разом із усім. Заміряно: після прокрутки на 800 верх шапки був
   -588, тобто вона пішла за екран.
   Тому вертикальну прокрутку віддаємо самій дошці: висота фіксована, всередині
   гортається і вгору-вниз, і вбік, а шапки стовпців прилипають до її верху.
   ⚠ 300 — та сама межа, що була: шапка, пошук, нижнє меню і рядок підказки. */
/* ⚠ ВИСОТА БІЛЬШЕ НЕ ВІДНІМАЄТЬСЯ ЧИСЛОМ. Було calc(100dvh - 300px) — число,
   підібране під шапку, пошук, меню і підпис під дошкою. Підпис прибрали, і
   внизу лишилась порожня смуга; власник побачив це одразу: «таблиця не на весь
   екран іде». Будь-яке таке число застаріває при першій же зміні поруч.
   Тепер дошка просто займає ВСЕ, що лишилось: сторінка — колонка на всю висоту,
   дошка в ній тягнеться. min-height: 0 обовʼязково, інакше елемент, що
   розтягується, не дає собі стиснутись до розміру батька і прокрутка не
   зʼявляється взагалі. */
.page.med-wide { display: flex; flex-direction: column; height: 100%; }
.med-wide .med-board { flex: 1 1 auto; min-height: 0; overflow: auto; }
.med-wide .med-col { flex: 0 0 220px; }

/* На широкому екрані стовпці ділять ширину порівну і гортати не треба взагалі.
   220px — нижня межа, за якою підпис заявки перестає читатись. */
@media (min-width: 1000px) {
  .med-wide .med-col { flex: 1 1 0; min-width: 190px; }
}

/* ⚠ ГОРТАННЯ ВБІК ЛИШАЄТЬСЯ ЗАВЖДИ, і це виправлення справжньої вади, а не смак.
   Було `overflow-x: visible` від 1000 пікселів — на думку, що стовпці однаково
   вміщаються. Не вміщаються: сім стовпців по 200 плюс шість проміжків дають
   1460 при доступних 1420, і сьомий стовпець «Не вийшов на зв'язок» просто
   зрізало правим краєм — на знімку його не було видно цілком. З `auto` він або
   вміщається, або до нього можна догорнути; зникнути він не може.
   190 замість 200 — щоб на екрані 1440 сім стовпців таки вмістились без смуги
   гортання: 7×190 + 6×10 = 1390 при 1420 доступних. */
.med-wide .med-board { overflow-x: auto; }

/* ══════════════ КОЛИ ВІДКРИЛИ З НОУТБУКА ══════════════════════════════════
   ⚠ ЗАСТОСУНОК ЗРОБЛЕНО ПІД ТЕЛЕФОН, і на широкому екрані це видно одразу:
   вузька колонка 760 пікселів посередині, а обабіч — порожньо на пів екрана.
   Вміст при цьому не більший, лише поля довкола. Виглядає як розтягнутий
   телефон, а не як робочий застосунок.

   ⚠ ПРАВИЛА ЛИШЕ ДЛЯ МЕДИЧНОГО МОДУЛЯ. Оболонка спільна з УДЗ, і міняти її
   ширину означало б перемалювати чужий модуль без прохання. Тому чіпляємось
   за клас `.med-page`, який модуль кладе на свою сторінку сам.

   ⚠ МЕЖА 1100, А НЕ 760. На 800–1000 (планшет, півекрана на ноутбуці) дві
   колонки дають по 400 пікселів — картка з гістограмою в них не читається.
   Краще одна широка колонка, ніж дві тісні. */
@media (min-width: 1100px) {
  .med-page { max-width: 1240px; padding: 16px 20px 0; }

  /* ⚠ СПИСОК — ОДНА КОЛОНКА, І ЦЕ РІШЕННЯ ВЛАСНИКА, А НЕ ЗАМОВЧУВАННЯ.
     Я був зробив дві колонки, щоб «використати ширину». Власник подивився на
     проді і сказав прямо: «заявки не должни бить в два столбца, расширь в 1 и
     просто больше данних з заявки виведи». Тобто ширина потрібна не для того,
     щоб умістити ДВА рядки поруч, а щоб в ОДНОМУ рядку вміщалось більше про
     людину. Друга сесія попереджала про це до правки — і мала рацію.
     Тому тут не лишилось нічого: список успадковує звичайну одну колонку,
     просто ширшу разом зі сторінкою. */

  /* «Зведення» — дві колонки. Календар, гістограми і кільце стоять поруч, а не
     стрічкою на пів екрана вниз: власник дивиться на них разом, а не по черзі. */
  .med-page:has(.cal-card) {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 20px; align-content: start;
    /* ⚠ ЧОТИРИ КАРТКИ ОДНАКОВІ ЗА РОЗМІРОМ. Власник: «ці 4 блоки теж мають бути
       однакові, переробіть, щоб були одного розміру». Раніше тут стояло
       align-items: start, і кожна картка була заввишки рівно під свій вміст —
       гістограма вища, кільце нижче, склад ще нижчий. Виглядало як недороблена
       сітка.
       stretch вирівнює картки в межах рядка, а min-height — між рядками. Число
       підібране під найвищу з чотирьох, щоб жодну не обрізало. */
    align-items: stretch;
  }
  /* На всю ширину лишається те, що ділити не можна: плитки, заголовок розділу,
     пошук із фільтрами і підсумковий рядок. */
  .med-page:has(.cal-card) > .kpis,
  .med-page:has(.cal-card) > .stats-title,
  .med-page:has(.cal-card) > .filters,
  .med-page:has(.cal-card) > .list-meta,
  .med-page:has(.cal-card) > .hint,
  /* ⚠ КАЛЕНДАР — НА ОБИДВІ КОЛОНКИ. У половині ширини клітинка дня стискається
     до розміру, у якому число вже не прочитати, а сам місяць — головне, на що
     тут дивляться. Пряма вимога власника: «календарь все равно должен бить на
     всю ширину как 2 столбца. только он» — саме він, решта карток лишається
     у дві колонки. */
  .med-page:has(.cal-card) > .cal-card { grid-column: 1 / -1; }
  .med-page:has(.cal-card) > .card:not(.cal-card) { min-height: 330px; }

  /* ⚠ І ОДРАЗУ ВИСОТА КЛІТИНКИ. Клітинка дня квадратна (`aspect-ratio: 1`), і це
     правильно на телефоні: там ширина клітинки — сьома частина від 390. Коли
     календар розтягнувся на 1200, клітинка стала 165×165, а місяць — заввишки
     на півтора екрана, з величезними порожніми полями довкола числа. Знімок це
     показав одразу. Тому на широкому екрані клітинка перестає бути квадратом. */
  /* ⚠ ВИСОТА ВІД ЕКРАНА, А НЕ СТАЛА. Було 74 пікселі — на моєму знімку
     місяць уміщався, а у власника при 100% масштабі нижні тижні пішли під
     нижнє меню. Стала висота підходить рівно під ту висоту вікна, на якій її
     підбирали, і ні під яку іншу.
     Тепер клітинка міряється від висоти вікна: 5.5vh, але не менша за 30 і не
     більша за 56 — нижче числа не читаються, вище місяць знову не вміщається. */
  .med-page .cal-card .cal-cell { aspect-ratio: auto; height: clamp(30px, 5.5vh, 56px); }
  .med-page .kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* Панель фільтрів: чотири пікери в рядок замість сітки 2×2 — на широкому
     екрані вони й так уміщуються, а панель стає вдвічі нижчою. */
  .med-page .filter-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* ⚠ ДОДАТКОВІ ПОЛЯ ЗАЯВКИ. На телефоні їх немає взагалі (правило нижче ховає
     рядок), бо там кожен зайвий рядок відсуває наступну заявку за край екрана.
     На ноутбуці місце є — і замість порожнечі посередині рядка людина бачить
     номер, телефон, терміновість і звідки заявка прийшла. */
  .med-page .rec-wide { display: flex; }

  /* ⚠ У СТОРІНКИ ТУТ ІНШІ ПАДІНГИ (16/20 замість 12/12), тому від'ємні поля
     липкої смуги мусять збігтись із ними — інакше тло не дотягнеться до країв
     і крізь щілини по боках буде видно текст, що проїжджає під смугою. */
  .med-page .med-back { margin: -16px -20px 0; padding: 16px 20px 8px; }
  /* Падінг зверху тут 16, а не 12, тому смуга на чотири пікселі вища: 16+46+8. */
  .med-page .med-back + .filters { top: 70px; }

  /* Гістограми вищі: місце є, а вища смуга точніше показує різницю. */
  .med-page .med-cols { height: 180px !important; }
  .med-page .med-cols-lbl span { font-size: 11.5px; }

  /* Накладка (картка заявки, картка хворого) теж не має бути на весь екран:
     читати рядок завдовжки 1400 пікселів незручно. */
  /* ⚠ НАКЛАДКА НЕ ВСЕРЕДИНІ СТОРІНКИ. Її кладуть у `body`, а не в `.med-page`,
     тому `.med-page .overlay` не спрацював би НІКОЛИ — правило було б мертве.
     Чіпляємось за плашку показу: вона теж у body і теж тільки в медичного. */
  body:has(.med-page) .overlay .form-body > * {
    max-width: 900px; margin-left: auto; margin-right: auto;
  }
}

/* Миша, а не палець: підсвічування рядка під курсором. На телефоні цього блоку
   не буде взагалі — hover там або не існує, або «залипає» після дотику. */
@media (hover: hover) and (pointer: fine) {
  .med-page .rec:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
  .med-page .pill:hover,
  .med-page .field-sel:hover { border-color: var(--accent); }
  .med-page .med-cardlet:hover { border-color: var(--accent); }
}

/* ══════════════ ПЕРЕТЯГУВАННЯ КАРТОК ПО ДОШЦІ ═════════════════════════════
   Власник: «переделай етот вид, что би там можно било мишкой или с телефона
   рукой передвигать их. и кнопку убери она дает только в одну сторону».

   ⚠ touch-action: pan-y — НЕ ОФОРМЛЕННЯ, А УМОВА РОБОТИ ПАЛЬЦЕМ. Пояснення
   повністю — у коментарі до boardView() в med.js. Коротко: гортання
   вгору-вниз лишається браузеру, рух убік забирає застосунок. */
.med-cardlet.drag { touch-action: pan-y; cursor: grab; }

/* Картка, яку зараз тягнуть, лишається на місці бліда — щоб було видно,
   ЗВІДКИ забрали, поки двійник летить за пальцем. */
.med-cardlet.is-dragging { opacity: .3; border-style: dashed; }

/* Двійник, що летить за вказівником. pointer-events: none обовʼязково: інакше
   під пальцем завжди був би він сам, і стовпець-приймач не визначався б. */
.med-cardlet.drag-ghost {
  position: fixed; left: 0; top: 0; z-index: 70; pointer-events: none;
  opacity: .95; rotate: -1.5deg;
  box-shadow: 0 14px 30px rgba(0, 0, 0, .3);
}

/* Стовпець під вказівником. Підсвічування має бути помітним саме на телефоні,
   де палець закриває половину екрана, — тому рамка, а не лише відтінок. */
.med-col.is-over {
  outline: 2px dashed var(--accent); outline-offset: -2px;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface-2));
}

/* Поки тягнемо — не даємо браузеру виділяти текст під пальцем і мишкою. */
body.med-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }
body.med-dragging .med-cardlet.drag,
body.med-dragging .med-cardlet-b { cursor: grabbing; }

/* Рядок «Скасувати» після переміщення. Стоїть НАД дошкою, а не спливає знизу:
   спливне зникає само, а тут людина має встигнути помітити промах. */
.med-undo {
  display: flex; align-items: center; gap: 8px; margin: 0 0 8px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  font-size: 13px;
}
/* Той самий рядок, але про СПРАВЖНЮ заявку: попередження, а не підтвердження. */
.med-undo > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.med-undo-go {
  flex: 0 0 auto; background: transparent; border: 1px solid var(--accent);
  color: var(--accent); font-weight: 700; font-size: 12.5px;
  padding: 5px 10px; border-radius: 8px; cursor: pointer;
}
.med-undo-x {
  flex: 0 0 auto; background: transparent; border: 0; color: var(--muted);
  display: flex; align-items: center; padding: 4px; cursor: pointer;
}

/* Додаткові поля в рядку заявки. Схований за замовчуванням — показує його лише
   правило для широкого екрана вище. */
.rec-wide {
  display: none; flex-wrap: wrap; gap: 4px 18px; margin-top: 6px;
  font-size: 12px; color: var(--muted);
}
.rec-wide > span { white-space: nowrap; }
.rec-wide > span > b { font-weight: 700; color: var(--text); }
/* Підпис поля. `i` тут не курсив, а просто другий рівень тексту — саме так
   зроблено в решті модуля (див. .med-cardlet-b i). */
.rec-wide > span > i { font-style: normal; }

/* Позначка справжньої заявки — щоб вона не губилась серед показових. */

/* ══════════════ ЛИПКА КНОПКА «НАЗАД» ══════════════════════════════════════
   Прокрутка живе в `.content` (flex: 1; overflow-y: auto), тому `top: 0` — це
   верх видимої частини сторінки, одразу під шапкою модуля. Смуга з тлом
   сторінки, а не прозора: інакше під кнопкою просвічував би текст, що їде. */
.med-back {
  position: sticky; top: 0; z-index: 26;
  margin: -12px -12px 0;            /* компенсуємо падінги .page, щоб тло було на всю ширину */
  padding: 12px 12px 8px;
  background: var(--bg);
}
.med-back .btn { display: inline-flex; align-items: center; gap: 6px; }

/* ⚠ ДВІ ЛИПКІ СМУГИ НА ОДНОМУ НУЛІ. У картотеці одразу за кнопкою йде пошук із
   фільтрами, і він теж липкий з `top: 0`. Без зміщення вони накладаються — я це
   вже отримав: смуга закінчувалась на 146, а фільтри починались на 131.
   Числа заміряні в браузері, не на око: 12 + 46 (висота кнопки) + 8 = 66. */
.med-back + .filters { top: 66px; }

/* Позначка на картці дошки: заявка справжня, і статус їй поки нікуди зберігати.
   Стоїть ДО перетягування, а не після — див. коментар у boardView(). */

/* ── ЗАЯВКА — ОКРЕМА КАРТКА, А НЕ РЯДОК У СТРІЧЦІ ─────────────────────────────
   Власник: «заявки слитие в одну кашу». І він правий: спільний вигляд списку
   малює лише тонку риску знизу, а в медичній заявці чотири-пʼять рядків тексту
   різного розміру — риски між ними не видно взагалі, усе читається як один
   суцільний абзац.
   Тому в медичному модулі кожна заявка — картка з власною межею і проміжком.
   ⚠ Правило звужене до `.med-page`: спільний список УДЗ виглядає так, як і був. */
.med-page .rec-list { display: flex; flex-direction: column; gap: 10px; }
.med-page .rec.med-rec {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 12px 14px;
  box-shadow: var(--shadow);
}
.med-page .rec.med-rec:active { background: var(--surface-2); }

/* Смуга збоку відповідає на питання «чи це справжня людина» ще до читання. */
/* ⚠ Смуги «справжня заявка» більше немає: власник сказав, що всі заявки мають
   іти як справжні. Лишилась тільки червона — особливий випадок. */
.med-page .rec.med-rec.special { border-left: 3px solid var(--danger); }

/* ══════════════ ДОСТУПНІСТЬ ═══════════════════════════════════════════════
   Розбір за скілом `accessibility-craft` дав три справжні провали, і всі три —
   наслідок того, що кнопку-стрілку замінили жестом.

   ⚠ 1. ТЕКСТ ЛИШЕ ДЛЯ ПРОГРАМИ ЧИТАННЯ ЕКРАНА. Не `display: none` і не
   `visibility: hidden` — обидва ховають вміст і від читалки теж. Потрібен саме
   цей прийом: вузол лишається в дереві доступності, але не займає місця. */
.med-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  border: 0;
}

/* ⚠ 2. ВИДИМОГО ФОКУСА В ЗАСТОСУНКУ НЕ БУЛО ВЗАГАЛІ. У styles.css є лише
   `.inp:focus` — тобто людина, яка ходить із клавіатури, не бачила, ДЕ вона
   зараз, на жодній кнопці, вкладці чи картці. Це вимога WCAG 2.4.7, і без неї
   перетягування з клавіатури безглузде: перш ніж натиснути стрілку, треба
   бачити, яку картку тримаєш.
   `:focus-visible`, а не `:focus` — щоб рамка не спалахувала від миші.
   Обмежено медичним модулем: styles.css спільний з УДЗ, а міняти чужий модуль
   без прохання не можна. Про те, що діра загальна, сказано власнику окремо. */
.med-page :focus-visible,
.med-back :focus-visible {
  outline: 3px solid var(--accent-2);
  outline-offset: 2px;
}

/* ⚠ 3. КАРТКА, ЯКУ ТРИМАЄ КЛАВІАТУРА, має бути помітна не лише рамкою: на
   дошці з сімома стовпцями рамка губиться серед меж стовпців. */
.med-cardlet:has(.med-cardlet-b:focus-visible) {
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

/* Статус і галочка CRM — в одному стовпчику справа, як у списку УДЗ. */
.med-page .med-rec-right { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }

/* ══════════ ЩО ЗГОРТАЄТЬСЯ — МАЄ ПРО ЦЕ СКАЗАТИ ═══════════════════════════
   ⚠ Власник: «тут має бути намальована стрілка вниз, щоб зрозуміло, що якщо
   натиснути — розкриється». Він правий: заголовок без жодної позначки нічим не
   відрізняється від звичайного підпису, і натиснути на нього нікому не спаде.
   Рідну позначку браузера ховаємо і малюємо свою: вона однакова в усіх
   браузерах і повертається при розкритті, тобто показує ще й ПОТОЧНИЙ стан. */

/* ══════════ СТАЛА СІТКА В РЯДКУ ЗАЯВКИ ══════════════════════════════════════
   ⚠ Головне тут — що поле НЕ ЗНИКАЄ, коли воно порожнє. Раніше правило
   «порожнє не показуємо» давало картки різної висоти: заявка з QR-коду мала
   одні поля, з CRM інші, і список читався як набір різних карток. Тепер
   чотири комірки стоять завжди, а порожня показує прочерк. */
.rec-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 14px; margin-top: 6px; }
.rec-cell { min-width: 0; display: flex; gap: 6px; align-items: baseline;
  font-size: 12.5px; overflow: hidden; }
.rec-cell > i { font-style: normal; color: var(--faint); flex: 0 0 auto; }
/* ⚠ НА ТЕЛЕФОНІ ЗНАЧЕННЯ ПЕРЕНОСИТЬСЯ, А НЕ ОБРІЗАЄТЬСЯ. У комірці 154 пікселі,
   і «Найближчими днями» з обрізанням перетворювалось на «Найближ…» — тобто поле
   є, а прочитати його не можна. Хай краще картка буде на рядок вища. */
.rec-cell > b { font-weight: 600; color: var(--text); min-width: 0;
  overflow-wrap: anywhere; }
/* На широкому екрані місця вистачає, і однорядкові комірки тримають сітку
   рівною. */
@media (min-width: 1100px) {
  .med-page .rec-cell > b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* Прочерк не має важити стільки ж, скільки значення: інакше око читає його
   як дані. */
.rec-cell > b.none { color: var(--faint); font-weight: 400; }

/* На ноутбуці місця більше — чотири поля в один ряд. */
@media (min-width: 1100px) {
  .med-page .rec-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ══════════ РИСКА МІЖ РОБОЧИМИ І ЗАКРИТИМИ ══════════════════════════════════
   Власник: закриті мають бути видні, але окремо — «щоб було видно, що нових
   заявок немає, а це старі». Тому не просто відступ: горизонтальна лінія з
   підписом посередині читається як межа, а відступ — як випадкова порожнеча. */
.med-split { display: flex; align-items: center; gap: 10px; margin: 18px 0 6px; }
.med-split::before, .med-split::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--line);
}
.med-split > span {
  flex: 0 0 auto; font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--faint);
}
/* Закриті трохи приглушені: вони на екрані для довідки, а не для роботи. */
.med-closed .rec-name { color: var(--muted); }
.med-closed .rec { opacity: .82; }

/* ══════════ ПОЛЕ ДІАГНОЗУ З ПІДКАЗКОЮ МКХ-10 ════════════════════════════════
   Зроблено як стаття засудження в УДЗ: набираєш — бачиш збіги, обираєш —
   підтягується код і повна назва. Перелік лежить НАД полем за потоком, тому
   ховається при втраті фокуса: інакше він висить над рештою форми. */
/* 🔴 ТУТ БУВ ВЛАСНИЙ ВИПАДНИЙ ПЕРЕЛІК ДІАГНОЗІВ (.med-diag*). Прибрано
   24.08.2026 разом із самим віджетом: поле «Діагноз» тепер відкриває те саме
   вікно вибору, що й «Стаття засудження» в УДЗ (Options.openPicker), а його
   стилі живуть у styles.css як .picker-btn / .picker-list / .picker-row.
   Свій віджет коштував пів дня і трьох невдалих спроб власника вибрати діагноз:
   спершу `display:''` вмикав `display:none` звідси ж, потім перелік мовчав, поки
   не надрукуєш два знаки. Довелось викинути і зробити так, як просили спочатку. */

/* ══════════ ОБЛІК ЛІКІВ У НАЙМЕНШИХ ОДИНИЦЯХ ════════════════════════════════
   Власник 24.08.2026: «в упаковці може бути 50 таблеток, у ній 5 пластинок.
   вони дали не пластинку, а 4 з них вирізали — а це воно не враховує».
   Звідси три речі на екрані, яких раніше не було: одиниця біля числа, швидкі
   кнопки «пластинка / упаковка» і рядок складу з будовою під назвою. */
.med-qty { display: flex; align-items: center; gap: 8px; }
.med-qty > input { flex: 1 1 auto; min-width: 0; }
.med-qty > select { flex: 1 1 auto; min-width: 0; }
.med-qty-u { flex: 0 0 auto; color: var(--muted); font-size: 13px; font-weight: 700; }
.med-qty-fast { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* Дрібна кнопка: у застосунку її не було, а тут потрібна — «пластинка · 10»
   поруч із полем не може важити стільки ж, скільки «Створити заявку». */
.btn.small { padding: 5px 10px; font-size: 12.5px; width: auto; display: inline-flex; }

.med-stock-row { padding: 8px 0; border-bottom: 1px solid var(--line-2); }
.med-stock-row:last-child { border-bottom: none; }
.med-stock-row .hint { margin-top: 2px; }
/* Позиція без описаної упаковки — не помилка, але й не норма: видно, що її ще
   не описали, і це не змішується зі звичайним поясненням. */
.med-faint { color: var(--faint); font-style: italic; }

/* Телефон в анкеті — рівно як у публічній формі за QR: прибитий «+38» і десять
   цифр. Раніше тут стояло вільне поле на 20 знаків, куди лізли дужки й пробіли,
   і «+380 (67) 12» виглядало заповненим. */
.med-tel { display: flex; align-items: stretch; }
.med-tel-pre { display: flex; align-items: center; padding: 0 13px;
  border: 1px solid var(--line); border-right: none; background: var(--surface-2);
  color: var(--muted); font-weight: 700; font-size: 15px; }
.med-fld .med-tel input { border-left: none; letter-spacing: .08em; }

/* Захист від повторення 24.08.2026: клас `.field-sel` з УДЗ прибиває висоту
   38px і display:flex (він писався для div, не для справжнього select), а
   `.med-fld select` додає 12px відступу всередину. Разом це обрізало текст у
   полях вікна «Комбінований тест». Якщо колись знову зійдуться — не обріже. */
.med-fld select.field-sel, .modal-body select.field-sel {
  display: block; height: auto; padding: 12px; }

/* Кілька препаратів за один прийом. Власник: «потрібно після вибраного щоб
   зʼявлявся плюс, щоб додати ще». Рядки додаються, а не перемальовуються —
   інакше стерли б уже вписане в попередніх. */
.med-meds-row { padding-bottom: 6px; }
.med-meds-row + .med-meds-row { border-top: 1px dashed var(--line-2); padding-top: 10px; }
.med-meds > .btn.small { margin-top: 2px; }

/* Рентген: поле знімка зʼявляється лише після «робили». */
.med-xray { margin-top: 8px; }
.med-xray-prev { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.med-xray-prev img { max-width: 100%; max-height: 220px; border: 1px solid var(--line); }

/* ══════════ ВИДАЧА ЛІКІВ: ОДИН РЯДОК ЗАМІСТЬ ТРЬОХ ══════════════════════════
   Власник 24.08.2026 прислав знімок: під полем «Скільки видали» стояли кнопка
   упаковки, окремим рядком підказка і ще нижче «Додати ще». Три рядки на те, що
   читається за секунду. Тепер усе в одну лінію з переносом. */
.med-qty-fast { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 6px; }
.med-qty-note { margin: 0; }
/* «＋ Додати ще» окремим рядком під довідкою — власник 24.08.2026 по знімку.
   Перший рядок відповідає на «скільки в упаковці і скільки лишилось», другий —
   це вже інша дія, про інший препарат. */
.med-qty-more { margin-top: 6px; }

/* 🔴 ОДНАКОВІ КНОПКИ. Власник: «упаковка і додати ще не одного розміру».
   Так і було: обидві мали клас .btn.small, але «Додати ще» ще й font-weight:700,
   а різна жирність при однаковому padding дає різну ширину напису і різну
   висоту рядка. Тому висоту і відступи прибиваємо однаковими явно, а виділення
   лишається кольором — воно й було потрібне. */
.med-qty-fast .btn.small, .med-qty-more .btn.small {
  min-height: 30px; padding: 5px 12px; line-height: 18px;
  align-items: center; justify-content: center; }

/* «Додати ще» — єдина дія в цьому рядку, тому вона й виділена кольором.
   Решта поруч — довідка, а не дія. */
.btn.small.med-add-more { color: var(--accent); border-color: var(--accent); font-weight: 700; }
.btn.small.med-add-more:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* ══════════ ЧЕРНЕТКА АНКЕТИ ═════════════════════════════════════════════════
   Власник 24.08.2026: анкета має памʼятати набране при перемиканні вкладок.
   Смуга потрібна не для краси: без неї людина не розуміє, ЧОМУ в полях уже щось
   стоїть, і може прийняти чужу чернетку за нову анкету. */
.med-draft { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 0 0 12px; padding: 10px 12px; font-size: 13px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-left: 3px solid var(--accent); color: var(--text); }
.med-draft > span { flex: 1 1 220px; min-width: 0; }

/* Дві дії про ту саму людину в одному рядку, кожна на пів ширини — власник
   24.08.2026. На вузькому екрані стають одна під одною самі: два написи по
   25 знаків поруч на телефоні не вміщаються. */
.med-two { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
.med-two > .btn { width: 100%; margin: 0; white-space: normal; min-height: 44px; }
/* 🔴 БУЛО: нижче 560 px пара кнопок ставала стовпчиком. Власник просив саме
   рядок — «на половину ширини, а на другу половину постав». Накладка картки
   вужча за 560, тому правило спрацьовувало ЗАВЖДИ і його прохання не
   виконувалось ніколи. Лишаємо два стовпці; переносимо на стовпчик лише на
   зовсім вузьких екранах, де 44 px висоти вже не вистачить на підпис. */
@media (max-width: 340px) { .med-two { grid-template-columns: 1fr; } }

/* Поле з помилкою — червона рамка. Показуємо лише коли дата вже повна:
   сваритись на кожен набраний знак означає сваритись увесь час. */
.med-bad input { border-color: var(--danger, #dc2626); }

/* ══════════ ДВІ ДІЇ ВНИЗУ АНКЕТИ ════════════════════════════════════════════
   Власник 24.08.2026: «в кінці там де створити анкету зроби на пів ширини і
   додай другий варіант "Очистити анкету"».
   Обидві по половині — це не косметика: рівна ширина каже, що вибір справжній,
   а не «головна кнопка і щось дрібне поруч». На вузькому екрані стають одна під
   одною, бо дві кнопки по 45 пікселів завширшки не натиснути пальцем. */
.med-actions { display: flex; gap: 10px; }
.med-actions > .btn { flex: 1 1 0; min-width: 0; margin: 0; }
@media (max-width: 380px) {
  .med-actions { flex-direction: column; }
}

/* ══════════ ВІКНО З ФОРМОЮ — ШИРШЕ ══════════════════════════════════════════
   Власник 24.08.2026 прислав знімок вікна «Нове звернення · Мельник Андрій
   Вікторович» і сказав: «шире сделай». На знімку видно чому — заголовок
   переноситься на два рядки, поля стиснуті, збоку смуга прокрутки. У вікні при
   цьому ціла анкета: діагноз, рентген, ліки.
   ⚠ Ширшими стають ЛИШЕ вікна з полями форми. Підтвердження на один рядок
     («Очистити анкету?») розтягнуте на пів екрана читалось би гірше, а не краще.
     Тому :has(.med-fld), а не загальна ширина всіх вікон. `:has` у цьому файлі
     уже вживається в десяти місцях, нової залежності не зʼявляється. */
/* 🔴 ПЕРЕПИСАНО 24.08.2026 ЗА ПРЯМИМ СЛОВОМ ВЛАСНИКА. Спершу він сказав
   «зроби ширше в півтора раза для ноута і 90 відсотків екрана для телефона»,
   а тоді сам себе виправив: «хоча ні. давай скрізь на 90 відсотків від
   максимуму скрізь».
   Тому 90 відсотків ширини екрана — УСІМ вікнам, а не лише тим, що з формою.
   ⚠ Це стосується і вікна підтвердження: на широкому моніторі питання на один
     рядок теж стане на 90 відсотків екрана. Я вважав це зайвим і зробив був
     інакше — але це його екран і його рішення, а моє «краще знаю» тут не
     аргумент. Сказав йому наслідок вголос; захоче назад — один рядок.
   ⚠ max-width, а не width: у .modal-card уже стоїть width:100%, і саме
     max-width досі тримав його на 420. Міняємо межу, а не спосіб. */
.modal-card,
.modal-card:has(.med-fld) { max-width: 90vw; }

/* ══════════ ТЕЛЕФОН — ВОРОТА АНКЕТИ ═════════════════════════════════════════
   Власник 24.08.2026: «поки це поле не заповнене, жодне інше поле в анкеті
   заповнювати не можна, крім ПІБ» і «перевіряти, чи немає вже такого за
   номером — якщо знайшлось, пропонувати перейти в його анкету».
   Сенс, який він назвав сам: не заповнювати повну анкету навпроти живої
   людини, щоб аж наприкінці зʼясувати, що заявка на неї вже є. */
.med-gate { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: -4px 0 12px; padding: 9px 12px; font-size: 13px;
  background: var(--surface-2); border-left: 3px solid var(--line);
  color: var(--muted); }
.med-gate > span { flex: 1 1 220px; min-width: 0; }
/* Знайшли людину — це вже не підказка, а причина зупинитись. */
.med-gate.found { background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-left-color: var(--accent); color: var(--text); font-weight: 500; }
/* Перевірити не вдалось — окремий стан, не плутати з «нікого немає». */
.med-gate.warn { background: color-mix(in srgb, var(--danger, #dc2626) 10%, transparent);
  border-left-color: var(--danger, #dc2626); color: var(--text); }

/* ⚠ Закрите поле видно ОЧИМА, а не лише по тому, що воно не натискається.
   Екран, який виглядає робочим і мовчить у відповідь, гірший за явно закритий.
   Гасимо саме ПОЛЯ, не картки: у першій картці поруч лежать ПІБ і телефон, які
   лишаються доступними. */
.med-fld.med-locked { opacity: .45; }
.med-fld.med-locked > span { color: var(--muted); }

/* ══════════ ТАБЕЛЬ ЧЕРГУВАНЬ ════════════════════════════════════════════════
   Власник 24.08.2026 зі знімком шкільного табеля: місяць, люди в рядках, дні в
   стовпцях, зафарбовані клітинки. Було — перелік із написом «на зміні». */
.med-month { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.med-month-t { font-size: 16px; text-transform: capitalize; }

/* На місяці з 31 дня таблиця не вміщається — гортається вбік. Перший стовпець
   при цьому лишається на місці, інакше не видно, чий це рядок. */
.med-tab-wrap { overflow-x: auto; border: 1px solid var(--line); background: var(--surface); }
.med-tab { border-collapse: collapse; width: max-content; min-width: 100%; }
.med-tab th, .med-tab td { border: 1px solid var(--line-2); padding: 0; text-align: center; }
.med-tab th { font-size: 12px; font-weight: 700; color: var(--muted);
  padding: 6px 0; min-width: 26px; background: var(--surface-2); }
.med-tab td { height: 30px; min-width: 26px; }

.med-tab-name { position: sticky; left: 0; z-index: 2; background: var(--surface);
  text-align: left !important; padding: 6px 10px !important; min-width: 190px;
  border-right: 2px solid var(--line) !important; }
.med-tab th.med-tab-name { background: var(--surface-2); }
.med-tab-name b { display: block; font-size: 14px; }
.med-tab-name span { display: block; font-size: 11.5px; color: var(--muted); }

/* Зафарбована клітинка — це і є чергування. Колір той самий, що у застосунку
   означає дію, а не тривогу. */
.med-tab td.on { background: var(--accent); }
.med-tab th.wknd, .med-tab td.wknd { background: color-mix(in srgb, var(--muted) 12%, transparent); }
.med-tab td.on.wknd { background: var(--accent); }
.med-tab th.today, .med-tab td.today { outline: 2px solid var(--accent-2); outline-offset: -2px; }
.med-tab td:hover { background: color-mix(in srgb, var(--accent) 25%, transparent); }
.med-tab td.on:hover { background: color-mix(in srgb, var(--accent) 70%, transparent); }

/* ══════════ СТОРІНКА НЕ ЇДЕ ВБІК — ТІЛЬКИ НА ТЕЛЕФОНІ ═══════════════════════
   🔴 Власник 25.08.2026 прислав знімок із телефона: уся сторінка зсунута —
      шапка, поле пошуку, стовпці і нижнє меню поїхали ліворуч.
      «щоб воно не могло так. щоб було жорстко закріплено».

   🔴 І ОДРАЗУ МОЯ ПОМИЛКА, ЯКУ ВІН СПІЙМАВ: перша версія цього правила діяла на
      ВСІХ ширинах. Він сказав прямо: «я говорил только за вид с телефона. с
      ноута все било хорошо а щас с ноута стало только хуже».
      Я взяв вузьку скаргу і полагодив ширше, ніж просили, — і зіпсував те, що
      працювало. Тому тепер усе, що стосується зсуву, живе ВСЕРЕДИНІ медіа-запиту
      для вузьких екранів, а ноутбук лишається точно таким, яким був.

   ЗАМІРЯНО, А НЕ ВГАДАНО: у вигляді «Стовпцями» на вузькому екрані документ
   ширший за екран і сторінку реально можна посунути; у вигляді «Списком» —
   рівно нуль. Тобто справа саме в дошці.

   ⚠ clip, А НЕ hidden. `hidden` зробив би документ контейнером прокрутки і
     зламав `position: sticky` у шапок стовпців — власник просив їх окремо.
   ⚠ ГОРТАННЯ ДОШКИ ЛИШАЄТЬСЯ: стовпці гортаються ВСЕРЕДИНІ .med-board. Це
     єдиний спосіб побачити сім статусів на телефоні. */
@media (max-width: 700px) {
  html:has(.med-page), body:has(.med-page) { overflow-x: clip; }
  /* Дошка не ширша за своє місце, а ряд стовпців усередині займає рівно стільки,
     скільки треба, і гортається в межах дошки — тобто розсувати документ їй
     просто нічим. */
  .med-board { max-width: 100%; width: 100%; overflow-x: auto;
    /* 🔴 ОСЬ ЦЕ — НАЙІМОВІРНІША СПРАВЖНЯ ПРИЧИНА, і вона не та, яку я лагодив
       учора. Власник: «іноді може так зсуватись» — саме ІНОДІ, не завжди.
       На iOS, коли гортаєш вбік і впираєшся в кінець, жест не зупиняється: він
       «перетікає» на батьківський елемент, а далі на документ. Тобто гортання
       дошки штовхає всю сторінку — разом із шапкою і нижнім меню. Саме тому
       зсув випадковий: він трапляється лише коли догортав до краю і смикнув ще.
       `contain` обриває це перетікання на самій дошці.
       ⚠ У проєкті цей прийом уже вживається: у `.content` стоїть
         `overscroll-behavior: contain` рівно з тієї ж причини. Я просто не
         поставив його дошці, коли робив гортання стовпців.
       ⚠ ЧЕСНО: відтворити зсув у себе я НЕ ЗМІГ. Контрольний дослід показав, що
         моя перевірка не бачить різниці ні з учорашнім замком, ні без нього —
         тобто вчорашня правка нічого не доводила. Тому це названо найімовірнішою
         причиною, а не полагодженим. Підтвердити може лише телефон власника. */
    overscroll-behavior-x: contain; }
  .med-board-in { width: max-content; }
  /* Той самий обрив на рівні документа: якщо жест усе-таки дійшов сюди,
     сторінці нема куди «відскакувати» вбік. */
  body:has(.med-page) { overscroll-behavior-x: none; }
}

/* ══════════ КАРТКА ЛЮДИНИ: ВКЛАДКИ ══════════════════════════════════════════
   Власник 25.08.2026 прислав знімок картки студента: вкладки згори, блоки
   всередині. Заявка стала однією з вкладок, а не всім екраном. */
/* 🔴 БУЛА ГОРИЗОНТАЛЬНА ПРОКРУТКА — 26.08.2026, скарга власника: «вкладки з
   телефона не влазять і слітають, крутяться». Так і було: flex + nowrap +
   overflow-x. Чотири підписи по 14px жирним із полями 14px дають близько 420 px,
   а екран телефона — 360. Смуга їхала вбік, активна вкладка виїжджала за край,
   і кожен дотик по сусідній спершу гортав, а не перемикав.

   Тепер СІТКА рівними частками: скільки вкладок — стільки колонок, і жодна не
   виходить за екран. Ширину колонки задає minmax(0, 1fr), інакше довгий підпис
   роздуває колонку і сітка знову тікає вбік.
   Підпис переноситься на два рядки замість того, щоб штовхати сусіда, а розмір
   спадає плавно через clamp: на вузькому телефоні 11.5px, на широкому — ті самі
   14px, що й були. Кількість колонок ставить JS у --tabs: вкладки будуються
   з переліку, і зашите число розійшлося б із ним при першій же новій вкладці. */
/* 🔴 ВКЛАДКИ — КНОПКИ, І ВОНИ ЇДУТЬ ЗА ЕКРАНОМ. Власник 26.08.2026: «4 вкладки
   раздели как на скрине и сделай кнопками и что би они вверху били прикреплени
   и когда вниз идем они шли за мной».
   ⚠ position: sticky, а не fixed. Картка відкривається накладкою, яка гортається
   всередині себе; fixed прибив би смугу до вікна браузера і вона висіла б поверх
   інших екранів. sticky тримає її вгорі САМЕ цього вмісту.
   ⚠ top: 0 і фон обовʼязкові разом: без фону вміст просвічує крізь смугу, і на
   гортанні літери накладаються на літери. */
.med-tabs { position: sticky; top: 0; z-index: 5;
  display: grid; grid-template-columns: repeat(var(--tabs, 4), minmax(0, 1fr));
  gap: 6px; background: var(--bg); padding: 8px 0 10px; margin: -12px 0 12px;
  border-bottom: 2px solid var(--line); }
/* ⚠ КНОПКИ, А НЕ ПІДКРЕСЛЕНІ НАПИСИ — так просив власник, і так вони РОЗДІЛЕНІ
   між собою: на знімку він обвів кожну окремо і провів межі. Раніше вкладки
   стояли впритул і читались як один сірий рядок. */
.med-tab-b { min-width: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; padding: 10px 4px; font: inherit;
  font-size: clamp(10.5px, 2.8vw, 14px);
  font-weight: 700; line-height: 1.15; text-align: center;
  white-space: normal; overflow-wrap: anywhere; word-break: break-word;
  color: var(--muted); cursor: pointer; }
/* ⚠ ЧИСЛА ТУТ ПІДІБРАНІ ЗАМІРОМ, А НЕ НА ОКО. На 360px смуга дає 84px на вкладку;
   при полях 6px і шрифті 11.5px найдовший підпис «Відвідування» виходив за свою
   клітинку і наїжджав на сусідню — це видно було на знімку, а не в коді. Поля 3px
   і 10.5px лишають на текст 78px, і він вміщається. */
.med-tab-b:hover { color: var(--text); }
.med-tab-b.active { color: #fff; background: var(--accent); border-color: var(--accent); }
.med-tabs-pane > .card:first-child { margin-top: 0; }

/* Порожня вкладка — сіра. Власник 25.08.2026: «Відвідування зроби сірим, якщо
   немає історії». Натиснути можна: заборонити відкрити означало б сховати сам
   факт, що історії немає. */
.med-tab-b.empty { color: var(--faint); }
.med-tab-b.empty::after { content: ' · порожньо'; font-size: 11px; font-weight: 400; }
/* На телефоні слово «порожньо» подвоює довжину підпису і з'їдає ту саму ширину,
   заради якої й робилась сітка. Сірий колір цю ж річ каже без жодного місця. */
@media (max-width: 430px) { .med-tab-b.empty::after { content: ''; } }
.med-tab-b.empty.active { color: var(--muted); border-bottom-color: var(--line); }


/* Шапка людини стоїть НАД смугою вкладок і видна на будь-якій із них: алергію
   не можна ховати за дотик, бо ліки видають на цьому ж екрані. */
/* Шапка: хто це, одним поглядом. Розмір спадає згори вниз — так око читає
   природно, і не треба жодних підписів «Вік:», «Звання:». */
.med-head { padding-bottom: 12px; }
.med-head-1 { font-size: 15px; font-weight: 700; color: var(--text); }
.med-head-2 { font-size: 13.5px; color: var(--muted); margin-top: 3px; }
.med-head-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.med-state { font-size: 12px; font-weight: 700; padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); color: var(--text); }
.med-tel-a { font-size: 13.5px; color: var(--muted); text-decoration: none; }
.med-tel-a:hover { color: var(--text); }

/* Прапорці — тільки те, що змінює рішення просто зараз. Порожніх немає взагалі:
   рядок «Контузії: —» забирає місце і не додає нічого. Алергія червона, бо ліки
   видають на цьому ж екрані. */
.med-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.med-flag { font-size: 12px; padding: 3px 8px; border-radius: 6px;
  background: var(--surface-2); color: var(--muted); }
.med-flag.bad { background: color-mix(in srgb, var(--danger, #dc2626) 16%, transparent);
  color: var(--danger, #dc2626); font-weight: 700; }

/* Підпис розділу — це підпис, а не крик. КАПС із розрідженням на вузькому
   екрані читається гірше і перетягує увагу на себе. */
.med-sec-t { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 10px; }

/* Видалення заявки — дрібна кнопка праворуч, а не смуга на всю ширину.
   Розмір відповідає тому, як часто її тиснуть; незворотність стереже
   підтвердження двома натисками. */
/* 🔴 БУЛА ЧЕРВОНА КНОПКА З РАМКОЮ — 26.08.2026, власник: «виглядає криво і не
   до чого». Обведена червона кнопка внизу картки читається як заклик: око
   чіпляється за неї, хоч тиснуть її раз на місяць. Рамка ще й не збігалася з
   рештою екрана — там суцільні кнопки або чистий текст, обведених немає ніде.

   Тепер це ТИХА ДІЯ: сірий текст із ледь помітним червонястим підкресленням,
   без рамки і без тла. Червоною вона стає РІВНО в ту мить, коли справді
   небезпечна — після першого натиску, коли підпис міняється на «Точно? Ще раз».
   Тобто колір показує стан, а не існування кнопки. */
/* Дві дії в одному рядку: головна 70%, незворотна 30%.
   ⚠ Ширина тут несе зміст, а не красу: більша кнопка та, яку тиснуть щодня,
   менша та, яку тиснуть раз і назавжди. Власник назвав саме ці числа. */
/* ⚠ ОДНАКОВА ВИСОТА — не оформлення, а вада, яку власник бачив двічі, перш ніж
   сказати вголос. Причина: ліворуч у парі посилання (тег a), праворуч кнопка
   (тег button). Різні типові поля і різна базова лінія тексту, тому при
   однакових ширинах висоти розходились. align-items тут мало: висоту задає
   вміст, тому вирівнюємо і його. */
.med-pair { display: flex; align-items: stretch; gap: 8px; margin-top: 10px; }
/* Заголовок розділу з дією праворуч. Значок притиснутий до правого краю,
   бо дія тут другорядна: головне в розділі — самі знімки. */
.med-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.med-sec-head .section-title { margin: 0; }
.med-refresh { flex: 0 0 auto; }
/* ⚠ Обертання лише поки триває запит. Без нього людина не відрізняє «думає»
   від «нічого не сталось» і тисне ще раз — саме так і народжуються шість
   однакових звернень у журналі. */
.med-refresh.крутиться svg { animation: med-spin 0.9s linear infinite; }
@keyframes med-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .med-refresh.крутиться svg { animation: none; opacity: 0.5; }
}
.med-pair-main { flex: 0 1 70%; }
.med-pair-side { flex: 0 1 30%; }
/* На вузькому екрані підпис «Відкрити заявку M-1044» не влазить у 70% —
   даємо йому переносити слова, а не виїжджати за край картки. */
.med-pair .btn { white-space: normal; line-height: 1.2;
  display: flex; align-items: center; justify-content: center;
  min-height: 44px; box-sizing: border-box; margin: 0; }

.med-del-row { display: flex; justify-content: flex-end; margin: 10px 0 2px; }
.med-del-row .btn.small.danger {
  border: none; background: transparent; box-shadow: none;
  padding: 6px 2px; font-size: 13px; font-weight: 600; color: var(--muted);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--danger, #dc2626) 40%, transparent); }
.med-del-row .btn.small.danger:hover,
.med-del-row .btn.small.danger:focus-visible {
  color: var(--danger, #dc2626); background: transparent;
  text-decoration-color: var(--danger, #dc2626); }
/* Мить підтвердження — єдина, коли дія справді за один дотик від незворотності. */
.med-del-row .btn.small.danger.armed {
  color: #fff; font-weight: 700; text-decoration: none;
  background: var(--danger, #dc2626); border-radius: 8px; padding: 6px 12px; }
.med-del-row .btn.small.danger[disabled] {
  color: var(--faint); text-decoration: none; background: transparent; }

/* Скарга — головний текст картки. Підпис дрібний згори, значення на всю
   ширину: медик відкриває картку саме заради цього рядка. */
.med-lead { padding: 4px 0 12px; border-bottom: 1px solid var(--line-2); }
.med-lead-l { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--faint); margin-bottom: 6px; }
.med-lead-v { font-size: 16px; line-height: 1.45; color: var(--text); }
.med-lead-i { width: 100%; box-sizing: border-box; resize: vertical;
  border: 1px solid var(--line); background: var(--surface); color: var(--text);
  border-radius: 0; padding: 8px 10px; font: inherit; font-size: 15px; line-height: 1.45; }

/* Голосом замість набирання. Кнопка ПІД полем, а не над ним: над полем вона
   читалась би як «наговоріть, і не чіпайте руками», а тут — як «можна ще й
   голосом». Заповнює воно, стверджує людина. */
.med-voice{display:flex;flex-direction:column;gap:6px}
.med-voice-b{align-self:flex-start}
/* Увімкнений мікрофон має бути видно з іншого кінця кімнати: медик тримає
   телефон у витягнутій руці і говорить, а не дивиться в екран. */
.med-voice-b.on{background:var(--accent);color:#fff;border-color:var(--accent)}
/* Чорновий текст — те, що воно ЗАРАЗ чує. Без нього кнопка на пʼять секунд
   завмирає і виглядає як зависла. */
.med-voice-live{min-height:1em;font-style:italic;overflow-wrap:anywhere}
.med-voice-no{color:var(--muted)}
.med-voice-meds{display:flex;flex-direction:column;gap:6px;margin-top:10px}
