:root {
  color-scheme: light;

  /* Existing public aliases stay stable while components migrate to semantic tokens. */
  --bg: #f0f4f8;
  --sidebar: #1a2b4a;
  --accent: #2563eb;
  --accent2: #16a34a;
  --danger: #dc2626;
  --warn: #d97706;
  --card: #ffffff;
  --border: #e2e8f0;
  --text: #1e293b;
  --muted: #6c7b91;
  --font-sans: 'Roboto', Arial, Helvetica, sans-serif;

  --ui-surface-page: var(--bg);
  --ui-surface-card: var(--card);
  --ui-surface-elevated: #ffffff;
  --ui-surface-muted: #f3f7fb;
  --ui-surface-subtle: #f8fafc;
  --ui-surface-hover: #f1f5f9;
  --ui-surface-accent-soft: #eff6ff;
  --ui-surface-accent-muted: #e7f1ff;
  --ui-surface-accent-strong: var(--accent);
  --ui-text: var(--text);
  --ui-text-secondary: #64748b;
  --ui-text-muted: var(--muted);
  --ui-text-placeholder: #94a3b8;

  /*
   * Тихая пара: вспомогательная строка ячейки и графика рядом с ней —
   * иконка канала, индикатор операции. Один тон на обоих (требование
   * владельца 26.08.2026: «уравнять по цвету»), и живёт он здесь, а не
   * копией в каждом файле, где такая пара встречается.
   *
   * Величина выбрана по порогу ТЕКСТА, потому что текст в паре есть:
   * #64748b даёт 4.76:1. Прежний --muted (#6c7b91) — 4.30:1, то есть порог
   * уже не проходил, а --ui-text-placeholder (#94a3b8) — 2.56:1, не дотягивал
   * даже до графического.
   */
  --ui-text-quiet: var(--ui-text-secondary);

  /*
   * Обводка тихого контрола — переключателя с белой дорожкой. Это не часть
   * пары выше: у контрола свой порог (3:1), и тон текста на нём читался
   * кричаще-тёмным (замечание владельца 26.08.2026). #8390a2 — 3.24:1,
   * вплотную к порогу и заметно мягче.
   */
  --ui-border-quiet: color-mix(in srgb, var(--ui-text-secondary) 80%, var(--ui-surface-card));
  --ui-text-disabled: #96a3b3;
  --ui-text-inverse: #ffffff;
  --ui-text-accent: #1d4ed8;
  --ui-border: var(--border);
  --ui-border-strong: #cbd5e1;
  --ui-border-panel: #bac8d8;
  --ui-border-accent: #93c5fd;
  --ui-border-accent-soft: #bfdbfe;
  --ui-focus: #93c5fd;
  --ui-focus-ring: rgba(37, 99, 235, .28);


  /*
   * Статусные тройки surface/border/text.  Правило контраста, общее для всех
   * состояний бейджей TableKit: текст к собственному фону держится в коридоре
   * 5.5–7.0:1 по WCAG.  Нижняя граница — запас над AA 4.5:1 для мелкого
   * шрифта бейджа (.75rem), верхняя — чтобы бейдж оставался акцентом «чуть
   * заметнее вторичного текста» (--ui-text-secondary даёт 4.8:1 на карточке),
   * а не спорил с обычным текстом ячейки (--ui-text — 14.6:1).  Ни один цвет
   * не объявляется только внутри media/[data-theme]-блока: приложение
   * однотемное (color-scheme: light), тёмной палитры в проекте нет.
   */
  --ui-success-surface: #e7fbea;
  --ui-success-border: #b7e4c7;
  --ui-success-text: #1f6f3e;
  --ui-success-solid: #22c55e;
  --ui-success-strong: #16a34a;
  --ui-success-glow: rgba(34, 197, 94, .14);

  --ui-warning-surface: #fff4d6;
  --ui-warning-surface-soft: #fffbeb;
  --ui-warning-border: #e5ca84;
  --ui-warning-border-soft: #fde68a;
  /* 5.9:1 на --ui-warning-surface: было #8b5a10 (5.4:1) — единственное
     состояние, кроме muted, выпадавшее из коридора вниз. */
  --ui-warning-text: #83540e;
  --ui-warning-strong: #b45309;
  --ui-warning-solid: #d99a2b;
  --ui-warning-glow: rgba(217, 154, 43, .14);

  --ui-danger-surface: #ffebeb;
  --ui-danger-surface-soft: #fef2f2;
  --ui-danger-border: #e5baba;
  --ui-danger-border-soft: #fecaca;
  --ui-danger-text: #943232;
  --ui-danger-solid: #ef4444;
  --ui-danger-strong: #dc2626;
  --ui-danger-glow: rgba(239, 68, 68, .13);

  --ui-info-surface: #e7f1ff;
  --ui-info-border: #bfd4f0;
  --ui-info-text: #285aa0;
  --ui-info-solid: #38bdf8;
  --ui-info-strong: #0ea5e9;
  --ui-info-glow: rgba(56, 189, 248, .18);

  --ui-overlay-soft: rgba(15, 23, 42, .38);
  --ui-overlay: rgba(15, 23, 42, .5);
  --ui-overlay-strong: rgba(15, 23, 42, .7);

  --ui-space-1: 4px;
  --ui-space-2: 8px;
  --ui-space-3: 12px;
  --ui-space-4: 16px;
  --ui-space-5: 20px;
  --ui-space-6: 24px;
  --ui-space-7: 28px;

  --ui-radius-sm: 7px;
  --ui-radius-md: 8px;
  --ui-radius-lg: 11px;
  --ui-radius-xl: 12px;
  --ui-radius-pill: 999px;

  --ui-shadow-xs: 0 1px 2px rgba(15, 23, 42, .06);
  --ui-shadow-panel: 0 2px 5px rgba(30, 64, 104, .08);
  --ui-shadow-sm: 0 2px 8px rgba(15, 23, 42, .1);
  --ui-shadow-md: 0 8px 24px rgba(15, 23, 42, .12);
  --ui-shadow-lg: 0 18px 48px rgba(15, 23, 42, .22);
  --ui-shadow-modal: 0 20px 60px rgba(15, 23, 42, .2);

  --ui-control-height: 36px;
  --ui-control-height-touch: 44px;
  --ui-control-radius: 8px;
  --ui-font-size-control: .875rem;
  --ui-font-size-control-touch: 1rem;
  --ui-duration-fast: 150ms;

  --z-content: 1;
  --z-sticky: 120;
  --z-header: 320;
  --z-navigation: 360;
  --z-popover: 600;
  --z-modal: 1000;
  --z-modal-nested: 1200;
  --z-context-menu: 1400;
  --z-toast: 1600;


  /*
   * Responsive ladder. Ровно три мобильные ступени, единые для всего UI:
   *   L1  max-width: 1024px  планшет/узкий десктоп — сплиты в одну колонку, шапка в бургер
   *   L2  max-width:  768px  телефон/касание — карточные таблицы, полноэкранные диалоги,
   *                          контролы 44px, поля 16px. Совпадает с
   *                          @container tablekit (inline-size <= 768px) и с порталом ContextMenu.
   *   L3  max-width:  380px  узкий телефон — действия в столбец, поджатые отступы
   * Тип ввода (pointer: coarse) и высота вьюпорта (max-height) — ортогональные условия,
   * а не дополнительные ступени.
   */
  /*
   * Диаметр точки-индикатора состояния: зелёная/красная точка в чипе
   * планировщика и точка активности на кнопках «Настройки поиска»/«Фильтр».
   * Одна величина на оба места, чтобы калибры не разошлись. Это НЕ статусные
   * точки строк таблиц — у них свой --status-dot-size.
   */
  --ui-indicator-dot-size: 8px;

  /*
   * Размерная сетка иконок в кнопках: 16px в 36px-кнопке десктопа, 18px на
   * телефоне (значение переопределяет mobile-ui.css на ступени L2). Один
   * источник на .btn и на кнопки верхней панели — иначе шапка живёт по своей
   * шкале и её иконки заметно крупнее соседних.
   */
  --ui-button-icon-size: 16px;

  /*
   * Кегль текста верхней панели. Одна величина на пять мест: пункт навигации,
   * подпункт его выпадающего списка, пункт списка учётной записи и сами кнопки
   * «Меню» и пользователя. Почему отдельный токен, а не --ui-font-size-control
   * (.875rem): шапка стоит на тёмно-синем фоне, где мелкий светлый текст
   * заметно теряется, поэтому её шкала на шаг крупнее общей кнопочной. Пунктам
   * и подпунктам разъезжаться нельзя — они читаются как одна система, и держит
   * их именно эта переменная.
   */
  --ui-header-font-size: 14px;

  --ui-tap-target: 44px;
  --ui-font-size-secondary-min: 13px;

  /*
   * Воздух в шапке окна. Один набор на все шапки: `.close-button-row`
   * (Фильтр, Настройки поиска, контекстное меню), `.modal-head`/`.mf-head`
   * и `.wk-head` мастера. Раньше каждая шапка называла свои числа, и на
   * телефоне окна отличались на четыре пикселя — рядом это читалось как
   * дефект. Здешние значения десктопные и повторяют прежнюю геометрию
   * `.wk-head` (18px сверху и снизу при кнопке 36px = 68px); мобильные
   * объявлены в mobile-ui.css внутри L2, где кнопка вырастает до 44px.
   * Порог применения — не эти токены, а сам блок ступени.
   *
   * `--ui-window-pad-x` называет боковую рамку окна ЦЕЛИКОМ — и шапки, и
   * содержимого: тело окна, поля «Фильтра» и список «Настроек поиска»
   * считают её от того же значения, поэтому текст содержимого стоит ровно
   * под заголовком. Прежнее имя `--ui-window-head-pad-x` обещало только
   * шапку и мешало этому увидеть.
   */
  --ui-window-head-pad-y: 16px;
  --ui-window-pad-x: 20px;
  /* Глиф крестика окна. Отдельный токен, а не --ui-button-icon-size:
     крестик не растёт вместе с зоной нажатия, у него своя шкала. */
  --ui-close-glyph-size: 16px;
  --ui-window-head-min-height: 68px;

  --ui-safe-top: env(safe-area-inset-top, 0px);
  --ui-safe-right: env(safe-area-inset-right, 0px);
  --ui-safe-bottom: env(safe-area-inset-bottom, 0px);
  --ui-safe-left: env(safe-area-inset-left, 0px);

  /*
   * Ширина резерва под полосу прокрутки страницы (scrollbar-gutter: stable в
   * app-base.css). Вьюпорт — а с ним `right:0` и `100vw` у position:fixed —
   * кончается ПЕРЕД резервом, поэтому полноэкранные окна сдвигают на эту
   * величину свой правый край, иначе позади них видна полоса фона. Значение
   * здесь нулевое: настоящее меряет зондом app-header.js и кладёт на :root.
   * В CSS её не вычислить — при включённом резерве 100vw равен ширине БЕЗ
   * полосы, то есть тому же вьюпорту.
   */
  --ui-viewport-gutter: 0px;

  /*
   * Общий mobile-контракт контролов. Значения на :root соответствуют десктопу,
   * чтобы var() резолвился вне мобильных медиазапросов; сами мобильные величины
   * задаёт mobile-ui.css на ступени L2.
   */
  --mobile-control-height: var(--ui-control-height);
  --mobile-control-radius: var(--ui-control-radius);
  --mobile-font-size: 1rem;
  --mobile-page-gutter: 26px;

  /*
   * Боковой отступ страницы — один для всех трёх полос, которые тянутся во всю
   * ширину: синей шапки, топбара с названием и области контента. Раньше каждая
   * задавала его сама (24 / 26 / 24 на десктопе, 14 / 16 / 16 на планшете), и
   * знак приложения, заголовок страницы и карточки начинались с разных
   * координат — левый край страницы «плыл». Ступени переопределяют значение в
   * mobile-ui.css.
   */
  --ui-page-gutter: 24px;

  /*
   * Единственный источник высоты закреплённой зоны страницы.
   *
   * При прокрутке держатся две полосы: синяя шапка (--app-header-h) и полоса
   * с названием страницы под ней (--page-titlebar-h). Шапка однострочная на
   * любой ширине — названия страницы в ней нет, поэтому высота одна и без
   * переопределений по ступеням. Любое sticky-смещение страницы (тулбар
   * TableKit, липкий thead, боковая панель parser-map-kit) считается от их
   * суммы через --table-toolbar-top. Хардкод px у sticky-элементов уровня
   * страницы запрещён: высоты меняются здесь, в одном месте.
   */
  --app-header-h: 56px;
  --page-titlebar-h: 38px;
  --table-toolbar-top: calc(var(--app-header-h) + var(--page-titlebar-h));
}

/*
 * L2 — телефон: полоса шапки соразмерна блоку вкладок под ней. У вкладок
 * контрол 44px в рамке воздуха 8px с каждой стороны — 60px всего; шапка
 * повторяет ту же пропорцию вокруг своей кнопки «Меню», иначе две соседние
 * полосы читаются как случайные разные величины.
 */
@media (max-width: 768px) {
  :root {
    --app-header-h: 60px;

    /*
     * Нижняя граница вторичного текста на телефоне — 14px, а не 13px
     * (замечание владельца 26.08.2026: пояснение под «Умным поиском» и
     * подпись «Искать в столбцах» читались мелко). Ручка одна на всё
     * приложение: весь мелкий текст размечен этим токеном, и одна строка
     * поднимает его разом.
     *
     * Значение живёт ЗДЕСЬ, а не в mobile-ui.css, хотя это и мобильная
     * величина. Кабинет поставщика — вторая оболочка приложения
     * (templates/portal/base.html), и mobile-ui.css она не подключает: пока
     * значение лежало там, «одна ручка» до портала не доходила, и его
     * мелкий текст оставался тринадцатым. Токен объявляет тот файл, который
     * им владеет.
     *
     * Контракт закреплён tests/test_mobile_minimum_font_size_contract.py.
     */
    --ui-font-size-secondary-min: 14px;

    /* На телефоне крестик чуть крупнее: в зоне 44px глиф в 16px терялся
       (замечание владельца 26.08.2026). */
    --ui-close-glyph-size: 20px;

    /*
     * Кегль навигации на телефоне — общий touch-размер, 16px.
     * Замер: панель разделов набрана .9rem = 14.4px, тогда как поля ввода
     * рядом на этой ступени 16px, а строки самой панели высотой 48px. Пункт
     * навигации — главный элемент экрана, пока панель открыта, и читаться
     * мельче поля ввода ему незачем (замечание владельца 26.08.2026).
     */
    --ui-header-font-size: var(--ui-font-size-control-touch, 16px);
  }
}
