/* ═══════════════════════════════════════════════════════════════════════════
   ZV DESIGN TOKENS — єдине джерело візуальних констант платформи.
   Змінюєш значення тут → підтягується скрізь, де змінну застосовано через var().

   НАПРЯМ: A «чисті лінії» (обрано). Структуру тримають тонкі hairline-роздільники
   + повітря + типографіка, а НЕ обведені картки-коробки. Поверхні пласкі, без
   важких тіней/градієнтів. Акценти кольором — точково (статуси, ключові кнопки).

   Щільність — помірна (щільний профіль за замовчуванням; .comfort — для робочих
   місць, за якими сидять годинами). Кольори бренду незмінні. Логіку не чіпаємо.

   ЄДИНЕ ДЖЕРЕЛО (зведення 02.08.2026). До цього дня палітра жила в ШІСТНАДЦЯТИ
   місцях: тут, у `portal.css`, і ще в одинадцяти шаблонах, кожен зі своєю
   копією `:root`. Значення при цьому були тотожні до байта — перевірено
   `tools/token_audit.py` (13 копій `--oxblood:#6E1A18`, 13 `--gold:#BE9A50`
   і так далі, жодного розходження). Тому зведення було чистою дедуплікацією,
   без жодного рішення про колір.
   Єдине розходження, яке довелось вирішувати, — `--card-shadow`: `portal.css`
   давав легкий drop, цей файл `none`. Перемогло `none`: напрям A вище — це
   свідоме рішення платформи, а тінь у `portal.css` була його залишком.

   ПРАВИЛО НАДАЛІ: `:root` у платформі рівно один — цей. Шаблон, якому бракує
   змінної, додає її СЮДИ, а не заводить свій `:root`. Перевіряється
   `test_tokens.py` (він порахує `:root` і впаде на другому).
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  /* ── Кольори (бренд «Золоті Ворота») ──────────────────────────────────── */
  --oxblood:#6E1A18; --oxblood-deep:#551210;
  --gold:#BE9A50; --gold-bright:#D8B871; --gold-soft:#EFE2C4;
  --cream:#FBF7EF; --paper:#FFFFFF; --ink:#2B201C; --muted:#8C7E73; --line:#EAE0CE;
  /* Аліаси до імен portal.css — щоб злиття токенів було без розсинхрону. */
  --bg:var(--cream); --fg:var(--ink);

  /* ── Кольори станів (прийшли з portal.css при зведенні) ───────────────── */
  --hover:#F4EDDE;                    /* підсвітка рядка/кнопки під курсором */
  --input-bg:#FFFFFF; --input-bd:#E0D6C2;
  --ok:#2F7D4F;   --ok-soft:#E6F2E9;
  --bad:#8a2320;  --bad-soft:#F3E2E1;
  /* `--danger` вживався в `access.html` ЛИШЕ як `var(--danger,#B4524C)`, тобто
     ніде не був оголошений і завжди падав у запасне значення. Оголошуємо саме
     #B4524C, щоб вигляд не змінився ні на піксель. Те, що це ДРУГИЙ червоний
     поруч із `--bad:#8a2320`, — успадкована неохайність; зводити їх у один
     означає змінити колір на екрані, а це вже рішення власника, не дедуплікація. */
  --danger:#B4524C;
  /* ── ЗВІЛЬНЕНИЙ ПРАЦІВНИК ─────────────────────────────────────────────────
     ЗВИЧАЙНИЙ червоний, не бордовий: `--bad:#8a2320` і `--danger:#B4524C` — це
     кольори ПОМИЛКИ, а звільнення не помилка, це стан. Плутати їх означало б
     кричати там, де треба лише позначити.

     Відтінок підібрано ЗАМІРОМ, не на око. Найгірший контраст #CC0000 — 4.87:1
     на рядку «Разом» (золото 22% поверх паперу); на кремі 5.51, на зебрі 5.32,
     на hover 4.96. Усі вище порога 4.5.

     Теплокарта в перелік фонів НЕ входить, і це перевірено, а не припущено:
     заливку отримують лише числові клітинки (`portalHeat.fill` у dash.js і
     dash-realtors.js), а ім'я ріелтора завжди стоїть у підписі рядка
     (`td.l` у РАД, перша колонка матриці) — під ним фон рядка, не теплокарта. */
  --fired-fg:#CC0000;

  /* ── КОЛІР БЛОКУ КАРТКИ КЛІЄНТА ───────────────────────────────────────────
     Працівник знаходить блок за кольором, не читаючи заголовка. Чотири тони
     однієї ваги: підібрані НЕ на око, а за ЯСКРАВІСТЮ — вона в усіх чотирьох
     збігається з `--oxblood` (0.0412) з точністю до сотих. Саме тому вони
     виглядають набором, а не наліпками: око зчитує спільну «вагу» раніше, ніж
     різницю тонів.

         --oxblood  #6E1A18  L 0.0412   крем на ньому 10.77:1
         --sect-zk  #52285C  L 0.0408   крем на ньому 10.82:1
         --sect-eff #1E3A5F  L 0.0413   крем на ньому 10.76:1
         --sect-cal #0F4447  L 0.0469   крем на ньому 10.14:1

     Колір маркує БЛОК: фон шапки таблиці й заголовок секції. Дані, зебра й
     рядки лишаються нейтральними — колір не має заважати читати числа. */
  --sect-lead:var(--oxblood);   /* «Дзвінки по рекламі» — фірмовий, як був */
  --sect-zk:#52285C;            /* «Журнал ЖК» — фіолетовий */
  --sect-eff:#1E3A5F;           /* «Зусилля» — синій */
  --sect-cal:#0F4447;           /* «Дзвінки» — бірюзовий */
  /* Шапка досьє — НЕЙТРАЛЬНА: вона має підкреслювати кольорові секції нижче,
     а не змагатися з ними. Сірий теплий (у ньому червоного більше, ніж
     синього), щоб лежав у одній гамі з бордо й кремом, а не виглядав
     «холодною» вставкою. Яскравість 0.0455 — та сама вага, що в решти
     тонів; крем на ньому 10.29:1. */
  --sect-head:#3A3330;

  /* ── ДВІ ОЦІНКИ «БАЗИ РОЗПОДІЛУ» ──────────────────────────────────────────
     Потенціал і зрілість — не просто «зелене й жовте»: це два стовпчики, які
     читають ПОРУЧ, тому вони мусять бути одного роду з рештою платформи, а не
     парою наліпок. Підібрані тим самим способом, що чотири тони картки
     клієнта, — за ЯСКРАВІСТЮ, і обидва лягли рівно на `--oxblood` (0.0412):

         --oxblood   #6E1A18  L 0.0412   крем на ньому 10.77:1
         --sect-pot  #1A4031  L 0.0411   крем на ньому 10.79:1
         --sect-mat  #4C3511  L 0.0412   крем на ньому 10.77:1

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

     ЗАЛИВКА КЛІТИНОК — світла, текст на ній `--ink` (мінімум 10.2:1 на
     найтемнішому кроці, при порозі 4.5). Темною її робити не можна: у цих
     колонках стоять числа, а не позначки, і читати їх доводиться рядок за
     рядком. Градієнт зроблено кроками, а не прозорістю: прозорість змішала б
     колір із фоном рядка (зебра, підсвітка перезвону) і зіпсувала б контраст
     саме там, де рядок і без того помітний. */
  --sect-pot:#1A4031;           /* «Потенціал» — темно-зелений */
  --sect-mat:#4C3511;           /* «Зрілість» — темно-бурштиновий */
  /* Потенціал 1..8: 1 — найвищий, тому найнасиченіший. Порядок обернений до
     звичного, і саме тому шкала йде згори вниз, а не навпаки. */
  --pot-1:#8EC3A7; --pot-2:#9BCAB1; --pot-3:#A8D1BB; --pot-4:#B5D8C5;
  --pot-5:#C2DFCF; --pot-6:#CFE6D9; --pot-7:#DCEDE3; --pot-8:#E8F4EC;
  /* Зрілість: чим давніша активність, тим густіший бурштин. `mat-0` — свіжий
     (заливки немає взагалі, звичайний фон), `mat-arch` — за стелею. */
  --mat-1:#FDF6E3; --mat-2:#FBEDC8; --mat-3:#F8E3AD; --mat-4:#F5D992;
  --mat-arch:#EFE2C4;

  /* `--mast-h` навмисно НЕ оголошена: її ставить JS із фактичної висоти шапки
     (`document.documentElement.style.setProperty`), а в CSS вона вживається
     тільки як `var(--mast-h,64px)`. Оголосити її тут означало б підмінити
     живий вимір константою. */

  /* ── Типографіка ──────────────────────────────────────────────────────── */
  /* Два сімейства, обидва локальні (@font-face — у `fonts.css`):
       --font        PT Sans — інтерфейс: підписи, кнопки, поля, заголовки;
       --font-narrow PT Sans Narrow — широкі таблиці, де важлива щільність.
     Inter лишається ПЕРШИМ запасним у обох: він теж локальний, тож підміна
     нічого не тягне ззовні, а символи, яких немає в PT Sans (✕ ▲ ▼ ↙ ↗),
     як і раніше беруться з наступного рівня — системного шрифта. */
  --font:'PT Sans', 'Inter', system-ui, -apple-system, sans-serif;
  --font-narrow:'PT Sans Narrow', 'PT Sans', 'Inter', system-ui, sans-serif;
  --fs-base:13px;   /* body */
  --fs-xs:11px;     /* мікро-лейбли, UPPERCASE-заголовки таблиць/секцій */
  --fs-sm:12px;     /* дрібні підписи, вторинна навігація, чіпи */
  --fs-md:13px;     /* таблиці, кнопки, поля вводу */
  --fs-lg:15px;     /* заголовки секцій h2 */
  --fs-xl:19px;     /* wordmark у шапці / h1 сторінки */
  --fs-kpi:30px;    /* велика цифра KPI */
  --lh:1.45;

  /* ── Відступи (шкала кроком 2px) ──────────────────────────────────────── */
  --sp-1:4px;  --sp-2:6px;  --sp-3:8px;  --sp-4:10px;
  --sp-5:12px; --sp-6:14px; --sp-7:18px; --sp-8:22px;
  --gap:14px;               /* дрібний проміжок між елементами */
  --wrap-pad-y:16px;        /* вертикальні поля контейнера */
  --wrap-pad-x:26px;        /* горизонтальні поля контейнера */
  --section-gap:22px;       /* повітря між секціями (A тримає ритм ним + лінією) */

  /* ── Радіуси (стримані) ───────────────────────────────────────────────── */
  --r-sm:4px;    /* поля, кнопки, сегменти */
  --r-md:6px;    /* дрібні поверхні, де радіус доречний */
  --r-pill:20px; /* чіпи-пігулки */

  /* ── Лінії та роздільники (серце напряму A) ───────────────────────────── */
  --bd-w:1px;
  --bd:var(--bd-w) solid var(--line);
  --hair:1px solid var(--line);              /* тонкий роздільник секцій/рядків */
  --hair-accent:1px solid var(--gold-soft);  /* легкий акцентний роздільник (шапки) */
  --focus-ring:0 0 0 3px rgba(190,154,80,.16);

  /* ── Поверхні (A: пласко, без коробок і тіней) ────────────────────────── */
  --surface:transparent;    /* «картки» стають пласкими — тло сторінки */
  --card-shadow:none;       /* A: без тіней (був легкий drop — прибрано) */
  --toolbar-bg:var(--cream);/* липкі тулбари непрозорі, але пласкі (= тло) */

  /* ── Кнопки ───────────────────────────────────────────────────────────── */
  --btn-py:7px; --btn-px:16px; --btn-fs:var(--fs-md);

  /* ── Поля вводу / select ──────────────────────────────────────────────── */
  --inp-py:7px; --inp-px:10px;

  /* ── «Картки»-секції (A: без рамки/тіні; лишається лише внутрішнє повітря) ── */
  --card-py:14px; --card-px:16px;

  /* ── Таблиці — ЩІЛЬНІ рядки з ЛЕГКОЮ сіткою (A ≠ прибрати всі лінії!) ───── */
  --cell-py:7px; --cell-px:11px;

  /* ── ЧОТИРИ СТУПЕНІ ТАБЛИЦЬ ───────────────────────────────────────────────
     Таблиці платформи ЗАКОНОМІРНО різні: список задач із довгим текстом і
     матриця РАД на 30 колонок не можуть бути однаково щільними. До 06.08.2026
     ця різниця жила ПІКСЕЛЯМИ в дванадцяти шаблонах (5/7 у РАД, 5/8 у ЛМ, 6/9
     у Бінотелі, 10/12 у Задачах…), і кожен новий розділ дописував свою пару.

     Тепер різниця виражена СТУПЕНЕМ, а не числом. Таблиця оголошує, до якого
     ступеня належить; самі числа лишаються тут, в одному місці. Наслідок, за
     яким усе й затівалось: щоб змінити кегль або щільність УСІХ таблиць
     одразу, треба зрушити цю шкалу, а не обійти дванадцять файлів — і різниця
     між списком і матрицею при цьому збережеться, бо вона в ступені.

     ЧОМУ ШКАЛА, А НЕ ДОВІЛЬНЕ ЧИСЛО. Ширини колонок міряні canvas'ом під
     конкретний кегль (див. fitWidths у portal-table.js). Довільне значення
     означало б, що збережена ширина стає непридатною на невідому величину;
     ступінь дає скінченний перелік станів, під які ширини можна перерахувати.

     ЧОМУ НЕ calc() ВІД БАЗОВОГО. Спокусливо написати «матриця = база − 2px»,
     але на тісному кінці шкали така арифметика дає від'ємні падінги, а на
     широкому — розганяє матрицю сильніше за список. Кожен ступінь заданий
     ЯВНО: він проєктується, а не обчислюється. */

  /* кегель тіла */
  --tbl-fs:13px;      /* списки: Записи, Журнал, Дірект, когорти, картка   */
  --tbl-fs-c:12px;    /* компактні: FIN, ЛМ, Штат, Бінотел, довідники      */
  --tbl-fs-x:11.5px;  /* матриці: РАД — 30 колонок, кожен піксель на рахунку */
  /* кегель шапки */
  --tbl-fs-h:11px;    /* шапка списків і компактних (= колишній --fs-xs)   */
  --tbl-fs-hx:9px;    /* шапка матриць                                     */

  /* падінги клітинки: --cell-* вище — це ступінь «список», базовий */
  --cell-py-r:9px; --cell-px-r:12px;  /* просторі: довгий текст, мало колонок */
  --cell-py-c:5px; --cell-px-c:8px;   /* компактні                            */
  --cell-py-x:5px; --cell-px-x:7px;   /* матриці                              */

  /* ── Шапка таблиці: ІНВЕРСІЯ (02.08.2026) ─────────────────────────────────
     Бордо фон + кремовий текст. Раніше шапка була світла й відрізнялась від
     тіла лише кольором тексту — на щільній сітці межа «де закінчились назви
     колонок і почались дані» читалась погано. Зразок узято з довідників
     (`journal_ref`): там інверсія стояла ще з 29.07 і себе виправдала.
     Акцент — золото: стрілка сортування, підсвітка посилання під курсором. */
  --th-bg:var(--oxblood);
  --th-fg:var(--cream);
  --th-accent:var(--gold-bright);
  --th-bg-sorted:var(--oxblood-deep);
  --th-border:2px solid var(--gold);
  /* Роздільник між ГРУПАМИ колонок (дворядкова шапка РАД). Світліший за
     золото рамки — він ділить шапку всередині, а не відбиває її від тіла. */
  --th-group-sep:1px solid var(--gold-soft);
  /* `--th-row1-h` тут БІЛЬШЕ НЕМАЄ (знято 06.08.2026). Це була висота першого
     ряду дворядкової шапки — 25px, узяті під кегль РАД. Число не пережило
     другого розділу: FIN довелось завести власну (29px), бо спільна
     давала наїзд рядів на 4px. Тепер висоту МІРЯЄ рушій і кладе в `--pt-th1`
     на саму таблицю (portal-table.js, measureHeadOffset) — так само, як JS
     міряє `--mast-h` для шапки сайту. Оголосити її тут знову означало б
     повернути ту саму помилку: sticky справді вимагає числа, але це число
     мусить бути ВИМІРЯНИМ, а не записаним. */

  /* ── Рядки таблиці ────────────────────────────────────────────────────── */
  --row-alt:rgba(190,154,80,.045);   /* зебра — ледь тепліша за паперовий фон */
  --row-hover:rgba(190,154,80,.13);  /* наведення — помітно, але не кричить */
  --row-total-bg:rgba(190,154,80,.16);
  --row-total-fg:var(--oxblood-deep);

  /* Нуль у таблиці: приглушений, але ЧИТАБЕЛЬНИЙ. Заливки він не отримує
     взагалі (нуль — це відсутність події, а не «дуже мало»), тож лишається
     сам текст. Раніше на Дашборді він був #CFC4B4 — це **1.72:1** на папері,
     тобто фактично невидимий, а в РАД до `--muted` ще й додавалась
     `opacity:.45`. Виміряно, не на око: цей тон дає 5.07:1 на папері й 4.74:1
     на кремі, тобто проходить поріг WCAG AA (4.5:1) на обох тлах платформи.
     Перевіряється в `test_heat.py`. */
  --zero-fg:#7A6C61;

  /* ── ТЕКСТ НА ТЕМНИХ ПОВЕРХНЯХ ────────────────────────────────────────────
     Темних поверхонь у платформі багато: шапка сайту, інвертовані шапки
     таблиць, бульбашки вихідних повідомлень, кнопки primary, бейджі й чипи в
     активному стані, випадайка навігації. На всіх них діє ОДНА шкала — оця.

     ПРАВИЛО: `--muted`, `--ink`, `--zero-fg` та інші кольори світлого тла на
     темному НЕ ВЖИВАЮТЬСЯ ніколи. Вони рахувались від паперу, і на бордо
     дають від 1.5 до 3:1 — текст зливається з фоном.

     І ОКРЕМО: вторинний текст на темному приглушують КОЛЬОРОМ, а не
     `opacity`. Прозорість змішує текст із фоном, тобто тягне контраст рівно
     туди, звідки ми його рятуємо. Заміряно на живих сторінках: `.colhint` у
     довідниках (`--cream` × `opacity:.55`) давав **4.24:1**, а бейдж `.acc .n`
     у Чаті (`--gold-bright` × `opacity:.7`) — **3.69:1**. Обидва нижче порога,
     обидва виглядали «просто приглушеними».

     Заміряно на `--oxblood` / `--oxblood-deep` (два фони, темніших за які в
     платформі немає):
       --on-dark      10.77:1 / 13.28:1
       --on-dark-dim   7.11:1 /  8.76:1
     Обидва з великим запасом над WCAG AA (4.5:1), бо на темному тлі часто
     стоїть саме дрібний текст — бейджі, підписи колонок, лічильники.
     Перевіряється фактом: `tools/contrast_check.js` (живий DOM) і `test_contrast.py`. */
  --on-dark:var(--cream);
  --on-dark-dim:#DCC9A8;
}

/* ═══ ПРОФІЛЬ ЩІЛЬНОСТІ ═══════════════════════════════════════════════════
   :root вище — ЩІЛЬНО (дашборд, довідники, таблиці: вмістити максимум даних).
   .comfort — КОМФОРТНО: робочі місця, за якими сидять годинами (Чат — читання
   переписок; ОП — введення даних). Трохи більший шрифт і повітря заради
   читабельності. Ставиться класом на <body>. Ті самі токени — компоненти
   автоматично беруть комфортні значення. Напрям A (пласко) — спільний для обох. */
body.comfort, .comfort{
  --fs-base:14px; --fs-md:14px; --fs-sm:13px; --fs-lg:16px;
  --lh:1.55;
  --btn-py:9px;  --btn-px:18px;
  --inp-py:9px;  --inp-px:12px;
  --card-py:18px; --card-px:20px;
  --cell-py:9px;  --cell-px:13px;
  --gap:16px; --section-gap:26px;
  --r-sm:5px; --r-md:7px;

  /* Чотири ступені таблиць зсуваються РАЗОМ із рештою профілю. Без цього
     `.comfort` піднімав би лише базовий ступінь, а компактні й матриці
     лишались би там, де були — тобто профіль діяв би на частину таблиць. */
  --tbl-fs:14px; --tbl-fs-c:13px; --tbl-fs-x:12.5px;
  --tbl-fs-h:12px; --tbl-fs-hx:10px;
  --cell-py-r:11px; --cell-px-r:14px;
  --cell-py-c:7px;  --cell-px-c:10px;
  --cell-py-x:7px;  --cell-px-x:9px;
}

/* ═══ ⚙️ ОСОБИСТІ НАЛАШТУВАННЯ ВИГЛЯДУ ТАБЛИЦЬ ═════════════════════════════
 *
 * Класи ставляться на <html> синхронним скриптом із `_nav.html` — тобто ще до
 * того, як браузер дійде до таблиць. Тому нічого не блимає й не переїжджає:
 * до першого малювання значення вже ті, які людина обрала.
 *
 * ЧОМУ КЛАСИ, А НЕ ІНЛАЙНОВІ ЗМІННІ. Інлайн довелось би виписувати всі
 * одинадцять токенів на кожній сторінці й тримати їх у синхроні з JS. Клас
 * називає СТАН, а числа лишаються тут — там же, де решта шкали.
 *
 * ЧОМУ ШКАЛА, А НЕ ПОВЗУНОК. Ширини колонок міряні під конкретний кегль
 * (fitWidths), і кожен перехід між станами коштує перерахунку. Скінченний
 * перелік станів робить цей перерахунок передбачуваним; довільне число
 * означало б, що збережені ширини стають непридатними на невідому величину.
 * ─────────────────────────────────────────────────────────────────────────── */

/* ── ШРИФТ ТАБЛИЦЬ ────────────────────────────────────────────────────────
   Міняється РІВНО `--font-narrow` — шрифт інтерфейсу (підписи, кнопки, поля)
   лишається PT Sans завжди. Це не забудькуватість: у таблиці обирають
   щільність і читабельність даних, а хром платформи має лишатись упізнаваним,
   інакше кожен вибір ставав би зміною всього порталу.
   Запасні в кожному рядку ті самі, що були: своє сімейство → PT Sans → Inter →
   системний. Обране не завантажилось — текст лишається читабельним. */
:root.tfont-ptsn  { --font-narrow:'PT Sans Narrow', 'PT Sans', 'Inter', system-ui, sans-serif; }
:root.tfont-robo  { --font-narrow:'Roboto Condensed', 'PT Sans', 'Inter', system-ui, sans-serif; }
:root.tfont-pts   { --font-narrow:'PT Sans', 'Inter', system-ui, sans-serif; }
:root.tfont-inter { --font-narrow:'Inter', 'PT Sans', system-ui, sans-serif; }
:root.tfont-noto  { --font-narrow:'Noto Sans', 'PT Sans', 'Inter', system-ui, sans-serif; }

/* ── КЕГЕЛЬ ТАБЛИЦЬ ───────────────────────────────────────────────────────
   П'ять сходинок. Кожна задає ВСІ ступені явно, а не «базовий ± дельта»:
   різниця між списком і матрицею на 12px і на 16px не однакова — на дрібному
   кеглі матриця має триматись ближче до списку, бо інакше стає нечитабельною,
   а на великому може відпустити далі. Це проєктується, а не обчислюється.
   13px — те, що було до ⚙️; відкривши налаштування вперше, людина бачить саме
   свій нинішній вигляд. */
:root.tfs-12{ --tbl-fs:12px;   --tbl-fs-c:11.5px; --tbl-fs-x:11px;
              --tbl-fs-h:10px; --tbl-fs-hx:9px; }
:root.tfs-13{ --tbl-fs:13px;   --tbl-fs-c:12px;   --tbl-fs-x:11.5px;
              --tbl-fs-h:11px; --tbl-fs-hx:9px; }
:root.tfs-14{ --tbl-fs:14px;   --tbl-fs-c:13px;   --tbl-fs-x:12.5px;
              --tbl-fs-h:11px; --tbl-fs-hx:10px; }
:root.tfs-15{ --tbl-fs:15px;   --tbl-fs-c:14px;   --tbl-fs-x:13.5px;
              --tbl-fs-h:12px; --tbl-fs-hx:10.5px; }
:root.tfs-16{ --tbl-fs:16px;   --tbl-fs-c:15px;   --tbl-fs-x:14.5px;
              --tbl-fs-h:13px; --tbl-fs-hx:11px; }
/* 17 і 18 — верх шкали. Різниця між ступенями тут НАВМИСНО менша, ніж унизу:
   на дрібному кеглі матриця мусить триматись ближче до списку, щоб лишатись
   читабельною, а на великому вона вже й так велика, і додатковий розрив лише
   виштовхував би колонки за екран. */
:root.tfs-17{ --tbl-fs:17px;   --tbl-fs-c:16px;   --tbl-fs-x:15.5px;
              --tbl-fs-h:14px; --tbl-fs-hx:12px; }
:root.tfs-18{ --tbl-fs:18px;   --tbl-fs-c:17px;   --tbl-fs-x:16.5px;
              --tbl-fs-h:15px; --tbl-fs-hx:12.5px; }

/* ── КЕГЕЛЬ ШАПКИ ОКРЕМО ──────────────────────────────────────────────────
   Типово шапка їде за тілом (значення вище). Але це два різні завдання:
   тіло — читати числа, шапка — знайти колонку. Кому дрібні підписи заважають
   орієнтуватись, потрібен більший заголовок при тому самому тілі; кому
   навпаки — тихіша шапка, щоб не сперечалась із даними.

   Ці правила стоять ПІСЛЯ `.tfs-*` і мають ту саму специфічність, тож
   перебивають їх — без `!important` і без окремої змінної-перемикача.

   Пара «звичайна / матрична» рухається разом: різниця між ними (2px) — це та
   сама різниця, що й у решті шкали, і розводити її на два контроли означало б
   дати людині крутити те, чого вона не бачить окремо. */
:root.tfsh-9  { --tbl-fs-h:9px;  --tbl-fs-hx:8px; }
:root.tfsh-10 { --tbl-fs-h:10px; --tbl-fs-hx:8.5px; }
:root.tfsh-11 { --tbl-fs-h:11px; --tbl-fs-hx:9px; }
:root.tfsh-12 { --tbl-fs-h:12px; --tbl-fs-hx:10px; }
:root.tfsh-13 { --tbl-fs-h:13px; --tbl-fs-hx:11px; }
:root.tfsh-14 { --tbl-fs-h:14px; --tbl-fs-hx:12px; }

/* ── ЩІЛЬНІСТЬ ────────────────────────────────────────────────────────────
   Ті самі чотири ступені, що вже є, зсунуті цілою шкалою. Заміряно на матриці
   РАД (30 колонок, екран 1440): між «щільно» і «просторо» різниця близько
   восьми видимих колонок і п'яти рядків — це і є те, за що платять.
   `--cell-py/px` (ступінь «список») лишається базовим і тут теж головний:
   решта три рухаються разом із ним, зберігаючи задуману різницю. */
:root.tdens-tight{
  --cell-py:5px;  --cell-px:8px;
  --cell-py-r:7px; --cell-px-r:10px;
  --cell-py-c:4px; --cell-px-c:6px;
  --cell-py-x:4px; --cell-px-x:5px;
}
:root.tdens-normal{
  --cell-py:7px;  --cell-px:11px;
  --cell-py-r:9px; --cell-px-r:12px;
  --cell-py-c:5px; --cell-px-c:8px;
  --cell-py-x:5px; --cell-px-x:7px;
}
:root.tdens-loose{
  --cell-py:10px; --cell-px:15px;
  --cell-py-r:13px; --cell-px-r:18px;
  --cell-py-c:8px;  --cell-px-c:12px;
  --cell-py-x:7px;  --cell-px-x:10px;
}

/* ═══ БАЗОВИЙ ШАР ═════════════════════════════════════════════════════════
   Три правила, які до зведення були скопійовані в одинадцять шаблонів слово в
   слово. Тримати їх тут — не «зручність», а те саме, що й з `:root`: поки
   копій було одинадцять, будь-яка правка або розходилась, або не доїжджала.

   Специфічність нульова (елементні селектори), а підключається файл у <head>
   ПЕРЕД інлайновим <style> розділу — тож будь-яке власне правило сторінки
   спокійно перебиває базу. Розділ, якому потрібен інший `body`, просто пише
   свій; так і лишилось у `login.html`. */
*{box-sizing:border-box;margin:0;padding:0}

body{
  font-family:var(--font);
  font-size:var(--fs-base);
  line-height:var(--lh);
  background:var(--bg);
  color:var(--fg);
  -webkit-font-smoothing:antialiased;

  /* ЦИФРИ ОДНАКОВОЇ ШИРИНИ — СКРІЗЬ, а не лише в таблицях.
     Перевірено по самих файлах шрифтів (fontTools, не на око):
       · PT Sans і PT Sans Narrow — цифри вже табличні (усі десять по 545/1000
         і 450/1000 відповідно), фічі `tnum` у них НЕМАЄ й не треба;
       · Inter — цифри ПРОПОРЦІЙНІ (ширини від 833 до 1323 при upm 2048), але
         фіча `tnum` є.
     Тобто оголошення працює саме на Inter — на запасному шрифті й на всьому,
     що ще не переведено на PT Sans. Раніше воно стояло тільки на `table`, і
     числа поза таблицями (KPI, лічильники, підписи періодів) стрибали
     при кожній зміні цифри. */
  font-variant-numeric:tabular-nums;
}
