/*
 * Базовый структурный скин движка SharedKeyboard. Задаёт РАСКЛАДКУ и ПОВЕДЕНИЕ клавиш (flex-ряды,
 * ширина из --w, состояние нажатия, попап лонг-пресса, адаптив), но НЕ конкретный вид: цвета,
 * радиусы, тени, шрифт и размеры берутся из токенов --kb-* с нейтральными дефолтами. Инструмент
 * переопределяет токены в своём css/skin.css — так один движок носит разные скины.
 */

.kb {
    --kb-gap: 6px;
    --kb-key-h: 44px;
    --kb-radius: 8px;
    --kb-font: inherit;
    --kb-font-size: 18px;
    --kb-key-bg: #fff;
    --kb-key-fg: #1c1e21;
    --kb-key-border: #e2e5ea;
    --kb-key-shadow: 0 1px 0 rgba(0,0,0,.12);
    --kb-special-bg: #e9edf3;
    --kb-special-fg: #3a3f47;
    --kb-press-bg: #dfe6ef;
    --kb-hint-fg: #9aa1ab;
    --kb-corner-fg: #6a727e;
    --kb-stack-gap: 3px;
    --kb-stack-basis: 2px;   /* рамка обычной клавиши слева+справа — см. .kb__stack */
    --kb-pop-bg: #fff;
    --kb-active-indicator: #3a3f47;
    --kb-lock-indicator: #3a3f47;
    /* Всплывающая буква (key preview) — по умолчанию цвета клавиши, скин переопределяет при нужде. */
    --kb-preview-bg: var(--kb-key-bg);
    --kb-preview-fg: var(--kb-key-fg);
    --kb-preview-border: var(--kb-key-border);
    --kb-preview-shadow: 0 6px 16px rgba(0,0,0,.24);

    display: flex;
    flex-direction: column;
    gap: var(--kb-gap);
    user-select: none;
    -webkit-user-select: none;
    /* `none`, а не `manipulation`: на клавиатуре жест пальцем — это выбор варианта зажатия, и
       браузер не должен принимать его за прокрутку страницы. С `manipulation` он именно так и
       делал — экран уезжал, а нажатие обрывалось событием pointercancel. */
    touch-action: none;
    /* Размерный контейнер: тач-грань считает высоту клавиши из ШИРИНЫ клавиатуры (единицы cqw),
       см. блок `.kb[data-face="mobile"]` ниже. */
    container-type: inline-size;
}

.kb__row {
    display: flex;
    gap: var(--kb-gap);
    justify-content: center;
}

.kb__key {
    flex: var(--w, 1) 1 0;
    min-width: 0;
    height: var(--kb-key-h);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    padding: 0;
    margin: 0;
    border: 1px solid var(--kb-key-border);
    border-radius: var(--kb-radius);
    background: var(--kb-key-bg);
    color: var(--kb-key-fg);
    box-shadow: var(--kb-key-shadow);
    font-family: var(--kb-font);
    font-size: var(--kb-font-size);
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* ПЕРЕХОД ТОЛЬКО У transform — он композитный, его браузер делает на видеокарте, не перерисовывая
       клавишу. Раньше здесь плавно менялись ещё и фон с тенью: каждый кадр такого перехода —
       перерисовка клавиши с градиентом и размытой тенью, и на слабом телефоне это часть задержки
       между нажатием и буквой (замер: ~24 мс из 130 при CPU x20). Смена фона и тени осталась, но
       происходит мгновенно — одним кадром вместо серии. */
    transition: transform .04s;
    /* Изоляция раскладки: изменение внутри клавиши (подпись, попап, состояние) не заставляет
       браузер пересчитывать соседние клавиши. `paint` сюда добавлять НЕЛЬЗЯ — он обрежет попап
       зажатия, который выходит за границы клавиши вверх. */
    contain: layout style;
}

/* Ни браузерного, ни bootstrap-обрамления при фокусе/нажатии (глобальное правило сайта). */
.kb__key:focus,
.kb__key:focus-visible {
    outline: none;
    box-shadow: var(--kb-key-shadow);
}

/* НО КЛАВИАТУРНЫЙ ФОКУС ВИДЕН. Клавиши обходят стрелками (Tab входит в клавиатуру, стрелки водят
   по ней, Enter/пробел нажимают) — не видя, где стоишь, целиться некуда. Кольцо рисуется ТОЛЬКО
   на `:focus-visible`: браузер показывает его при работе с клавиатуры и НЕ показывает при клике
   мышью или пальцем, поэтому раздражающего обрамления при обычном нажатии не появляется.
   Цвет — currentColor клавиши (виден на любом скине), скин может задать свой `--kb-focus-ring`. */
.kb__key:focus-visible {
    box-shadow: var(--kb-key-shadow), inset 0 0 0 2px var(--kb-focus-ring, currentColor);
}

.kb__key[data-type="action"],
.kb__key[data-type="layer"] {
    background: var(--kb-special-bg);
    color: var(--kb-special-fg);
    font-size: calc(var(--kb-font-size) * .8);
}

/* Пустой заполнитель (пропуск в ряду keyman или целый пустой ряд, которым слои добираются до общей
   высоты): держит место, но не рисуется и не нажимается. Высота — как у клавиши: иначе пустой ряд
   схлопнулся бы, и высота клавиатуры всё равно менялась бы от слоя к слою. */
.kb__spacer {
    flex: var(--w, 1) 1 0;
    min-width: 0;
    height: var(--kb-key-h);
}

/* Клавиша БЕЗ СИМВОЛА: место на железной клавиатуре занято, но раскладка ему ничего не назначила
   (руническая, слоговые письменности — они не покрывают все клавиши). Выглядит как клавиша, только
   приглушённая, и не нажимается. Без неё ряд «схлопывался», и рамочная клавиша добирала пустоту:
   у футарка Backspace растягивался на 12 юнитов из 15 (нашёл владелец, 2026-07-28). */
.kb__key--blank {
    opacity: .45;
    box-shadow: none;
    cursor: default;
    pointer-events: none;
}

.kb__key[data-press] {
    background: var(--kb-press-bg);
    transform: translateY(1px);
    box-shadow: none;
}

/* НА ТАЧ-ГРАНИ НАЖАТИЕ РИСУЕТСЯ ДЁШЕВО: меняется только фон, клавиша не едет и тень не гаснет.
   Замер на слабом телефоне (CPU x20): подсветка нажатия занимала 32 мс из 40 мс всей задержки
   `pointerdown` — сдвиг и смена тени заставляют браузер перерисовывать клавишу вместе с размытой
   тенью вокруг неё. Со сменой одного фона выходит 32 мс вместо 48 на нажатие и 72 вместо 88 на
   отпускание, то есть примерно −30 мс на каждый символ. Пальцем разницу в оформлении не видно —
   палец и так закрывает клавишу, — а вот задержку видно всем.
   Скин, который рисует нажатие по-своему, обязан повторить это правило у себя: у его селектора
   специфичность выше (см. css/skin-*.css инструмента). */
.kb[data-face="mobile"] .kb__key[data-press] {
    transform: none;
    box-shadow: var(--kb-key-shadow);
}

/* Включённый регистр. ДВА состояния, и они РАЗНЫЕ на вид:
     [data-active="shift"] — одноразовый регистр: клавиша вдавлена, в углу точка;
     [data-active="lock"]  — замок (Caps, или двойной тап по Shift там, где Caps нет): вдобавок
                             закрашивается сама стрелка — чтобы «одна заглавная» и «залипло
                             насовсем» не выглядели одинаково.
   Атрибут ставит движок (KB._markActive) сразу на ВСЕ клавиши действия: Shift на полной раскладке
   два. Размеры — в em, чтобы жили при любом кегле. */
.kb__key[data-active] {
    background: var(--kb-press-bg);
    box-shadow: none;
}
/* Красится САМА СТРЕЛКА, без плашки-подложки: коробка вокруг иконки выглядела инородно
   (владелец, 2026-07-20). Никакого фона, радиуса и паддинга тут быть не должно. */
.kb__key[data-active="lock"] .kb__glyph {
    color: var(--kb-lock-indicator);
    font-weight: 700;
}
/* Точка — в УГЛУ, а не у левого края по центру: на мобайле клавиша регистра узкая и глиф стоит
   по центру, точка у края наезжала прямо на стрелку (проверено скрином 390px). В углу она не
   спорит с подписью ни при какой ширине — и читается как светодиод живой клавиатуры. */
.kb__key[data-active]::before {
    content: "";
    position: absolute;
    left: .42em;
    top: .42em;
    width: .42em;
    height: .42em;
    border-radius: 50%;
    background: var(--kb-active-indicator);
}
/* В режиме замка точки НЕТ: заливка стрелки сама всё говорит, а на узкой тач-клавише точка
   наезжала на плашку. Правило стоит ПОСЛЕ точки нарочно — специфичность у них одинаковая,
   и решает порядок (переставишь выше — точка вернётся). */
.kb__key[data-active="lock"]::before { content: none; }

.kb__cap {
    display: inline-flex;
    align-items: center;
    gap: .35em;
    pointer-events: none;
    max-width: 100%;
    /* overflow скрывает длинную подпись, вылезающую за узкую клавишу ВБОК. Но он же режет и то, что
       свисает ВНИЗ, — а `line-height: 1` у клавиши делает строку ровно в размер шрифта, тогда как
       глифу нужно больше: у «у» (как и у «р», «щ», «y») есть хвост под базовой линией, и его срезало
       (2026-07-17: буква выглядела как «v» с обрубком). `normal` берёт высоту из метрик САМОГО шрифта,
       поэтому хвост влезает при любой письменности — это важно для тиража (тайский, деванагари и
       прочие с глубокими выносными). Числом тут не обойтись: у каждого шрифта своя глубина. */
    line-height: normal;
    overflow: hidden;
    /* Подпись приподнята, чтобы БУКВА стояла по центру клавиши, а не строка текста: середина строки
       приходится на середину заглавной, и строчная («ы», «н») проваливалась ниже центра. На сколько
       поднять — считает движок по метрикам шрифта и буквам самой раскладки (--kb-ink-shift): числом
       тут нельзя, рост букв свой у каждого шрифта и письменности.
       `--kb-cap-nudge` — ДОБАВКА РЕЖИМА (по умолчанию 0): в тесной карте центр приходится опустить,
       иначе верх буквы упирается в угловую подпись. Это оптическая правка одного режима, а не отмена
       расчёта: базовый сдвиг остаётся тем же. */
    transform: translateY(calc(var(--kb-ink-shift, 0px) + var(--kb-cap-nudge, 0px)));
}

/* ─────────── ПАНЕЛЬ ЗНАКОВ: управляющие ряды закреплены, прокручивается содержимое ───────────
   Ряд может объявить роль (`data-role`), и тогда движок оставляет его прямым ребёнком клавиатуры,
   а всё, что до него, складывает в `.kb__scroll`. Так выход из панели, страницы, пробел и забой
   видны ВСЕГДА, а длинные вкладки (у символьного экрана их до 126 знаков) прокручиваются внутри
   себя — не утаскивая страницу и не вырастая за экран (требование владельца 2026-08-17).
   Раскладка без ролей эту разметку не получает: у неё `.kb__scroll` не создаётся, и правила ниже
   ни на что не действуют. Размеры клавиш, кегль и подписи здесь НЕ трогаются. */
.kb:has(> .kb__scroll) { display: flex; flex-direction: column; }
.kb__scroll {
    display: flex;
    flex-direction: column;
    gap: var(--kb-gap);
    min-height: 0;                 /* иначе flex-ребёнок не даёт себя сжать и прокрутки не будет */
    overflow-y: auto;
    overscroll-behavior: contain;  /* прокрутка не «протекает» на страницу сайта */
    -webkit-overflow-scrolling: touch;
}
.kb__row[data-role] { flex: 0 0 auto; }

.kb__glyph { font-size: 1.05em; }
.kb__lab   { font-size: .82em; white-space: nowrap; }

/* Пробел, по которому свайпом меняют язык: стрелки-указатели по бокам названия — единственный
   намёк, что жест вообще существует (так подписан пробел на телефонах). Это не текст интерфейса,
   а глифы-указатели, поэтому им место в стиле, а не в локализации. */
.kb__key[data-swipe="lang"] .kb__lab::before { content: "‹\00a0"; opacity: .55; }
.kb__key[data-swipe="lang"] .kb__lab::after  { content: "\00a0›"; opacity: .55; }

/* Подпись-хинт (поле hint раскладки). На тач-грани — намёк зажатия («ё» на «е») в правом верхнем
   углу. На десктопе тот же угол занят шифт-символом (.kb__corner), поэтому хинт уходит в правый
   НИЖНИЙ угол — так размечены вторые легенды на физических тайваньских клавиатурах (чжуинь/цанцзе),
   ради которых десктопная подпись и появилась (2026-07-29). */
.kb__hint {
    position: absolute;
    top: 3px;
    right: 5px;
    font-size: .5em;
    color: var(--kb-hint-fg);
    pointer-events: none;
}
/* НАТИВНЫЙ ВВОД (фонетики/транслиты на телефоне): наша клавиатура — уменьшенная карта соответствия.
   Плашка сверху сворачивает её в строку «⌨ имя ▸» и разворачивает обратно. Нажатия с нативной
   клавиатуры подсвечиваются штатным data-press — отдельного стиля вспышке не нужно. */
/* Три режима: min — только плашка; small (по умолчанию) — МАЛЕНЬКАЯ карта-декор в потоке страницы;
   full — полноценная клавиатура один в один со стандартной (нативная снова подавлена). */
.kb__minibar {
    display: none;
    width: 100%;
    align-items: stretch;
    gap: .4em;
    margin: 0 0 .35em;
}
.kb[data-native="1"] .kb__minibar { display: flex; }
.kb__minibar-main {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: .5em;
    padding: .45em .7em;
    border: 1px solid var(--tls-border, #d9d4c8);
    border-radius: .55em;
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
}
.kb__minibar-size {
    flex: 0 0 auto;
    padding: .45em .8em;
    border: 1px solid var(--tls-border, #d9d4c8);
    border-radius: .55em;
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
}
.kb__minibar-ico  { font-size: 1.15em; line-height: 1; }
.kb__minibar-name { font-weight: 600; }
.kb__minibar-chev { margin-left: auto; opacity: .6; }
.kb[data-mode="min"] .kb__row { display: none; }
/* «small» — уменьшенная карта соответствия: размер задают ТОКЕНЫ движка (высота клавиш/кегль/зазоры
   px), одним font-size её не ужать. Полноценный режим токены не трогает — он один в один со
   стандартной.

   ВЫСОТА 34px, А НЕ 24 (2026-08-10). При 24px угловая подпись налезала на букву почти на каждой
   клавише — замер по фактическим чернилам (ширина из Range, вертикаль из метрик шрифта) давал
   пересечения у 29 из 62 раскладок даже при 34px клавише в прежней геометрии, а на 320px до 88%
   площади подписи. Скрывать подписи нельзя: в этом режиме человек печатает НАТИВНОЙ клавиатурой, и
   карта нужна ровно затем, чтобы показать, какая латинская буква даёт какую букву письма.
   Тройка «34px + подпись на 1px выше + центр на 3px ниже» — минимальная: снятие любого из трёх
   возвращает пересечение (проверено 372 замерами по всем 62 раскладкам на 320/360/390, base и Shift).
   Высота выбрана так, чтобы карта не переросла полноразмерный режим: у него на 320px клавиша те же
   34px, на 360px — 36.8, на 390px — 40.4. */
.rkbd__kb .kb[data-mode="small"],
.kb[data-mode="small"] {
    --kb-key-h: 34px !important;
    --kb-font-size: 11px !important;
    --kb-gap: 3px !important;
    --kb-radius: 6px;
    --kb-cap-nudge: 3px;      /* центр ниже: место под угловую подпись */
    opacity: .95;
}

.rkbd[data-face="desktop"] .kb__hint {
    top: auto;
    bottom: 2px;
    right: 5px;
    font-size: .52em;
}

/* Фонетики/транслиты: латинская подпись «что нажимать» — ГЛАВНАЯ легенда угла (шифт-символ движок
   на таких клавишах не рисует). Живёт в правом верхнем углу читаемым кеглем на обеих гранях. */
.rkbd[data-face="desktop"] .kb__hint--corner,
.kb__hint--corner {
    top: 2px;
    bottom: auto;
    right: 5px;
    font-size: .56em;
}

/* Легенда AltGr (третий уровень) — нижний ЛЕВЫЙ угол, как на живых клавиатурах. Печатается
   физическим AltGr или кликом по экранному AltGr; зажатие клавиши — дополнительный дубль. */
.kb__altlegend {
    position: absolute;
    bottom: 2px;
    left: 5px;
    font-size: .52em;
    line-height: normal;
    color: var(--kb-corner-fg);
    pointer-events: none;
}

/* ISO-Enter — одна Г-образная клавиша из двух частей (верх в ряду D, низ в ряду C). Части склеены:
   у верхней погашены нижние углы и дорисован «мостик» через межрядный зазор, у нижней погашены
   верхние. Прежде обе рисовались отдельными кнопками «Enter» — читалось как две клавиши. */
.rkbd .kb .kb__key[data-part="top"] {
    position: relative;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    border-bottom-color: transparent;   /* стык — ВНУТРИ клавиши, контура там быть не должно */
}
.rkbd .kb .kb__key[data-part="top"]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    /* Мостик закрывает ВЕСЬ межрядный зазор И «подошву» клавиши (у скина это тень `0 4px 0`, она
       рисуется ниже клавиши и рассекала Г-образный Enter пополам: верхняя часть читалась отдельной
       пустой клавишей — владелец, 2026-07-30, арабская). Поэтому начинаем выше низа клавиши и
       перекрываем подошву, а сам мостик кладём НАД ней (`z-index`). */
    top: calc(100% - var(--kb-sole, 4px));
    height: calc(var(--kb-gap, 4px) + var(--kb-sole, 4px));
    background: inherit;
    z-index: 1;
}
.rkbd .kb .kb__key[data-part="bottom"] {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    border-top-color: transparent;
}

/* Шифт-символ печатной клавиши (десктоп) — как нарисован на живой клавиатуре: 1 → !, 8 → *.
   Читаемее подсказки зажатия: это ЛЕГЕНДА клавиши, а не намёк. Что именно тут стоит, приходит из
   шифт-слоя текущей раскладки — при смене языка уголки меняются сами. */
.kb__corner {
    position: absolute;
    top: 2px;
    right: 5px;
    font-size: .56em;
    line-height: normal;
    color: var(--kb-corner-fg);
    pointer-events: none;
}

/* Раздвоенная клавиша (↑ сверху, ↓ снизу) в ширине одной — как курсорный блок ноутбучной клавиатуры.
   Держит ширину ряда (--w), внутри две самостоятельные клавиши в полроста. */
.kb__stack {
    /* Базовый размер НЕ нулевой, а в рамку клавиши (--kb-stack-basis = левая + правая границы
       обычной клавиши). Иначе стопка выходит ровно на эти 2px уже соседей: у клавиш рамка входит
       в базовый размер флекса, у контейнера-стопки её нет, и свободное место делится не поровну.
       Замерено: сосед 73.75px против 71.75px у стопки. Меняешь толщину рамки клавиш в скине —
       поправь и этот токен. */
    flex: var(--w, 1) 1 var(--kb-stack-basis);
    min-width: 0;
    height: var(--kb-key-h);
    display: flex;
    flex-direction: column;
    gap: var(--kb-stack-gap);
}
.kb__stack .kb__key--half {
    height: auto;
    flex: 1 1 0;
    min-height: 0;
    font-size: calc(var(--kb-font-size) * .72);
}

/* ПОПАП АЛЬТЕРНАТИВ ЛОНГ-ПРЕССА — ТОГО ЖЕ ДИЗАЙНА, ЧТО ВСПЛЫВАЮЩАЯ БУКВА (владелец, 2026-07-24).
   Когда после preview всплывают варианты, они не должны «схлопываться» в мелкий квадратик: контейнер
   и шрифт варианта — как у `.kb__preview` (тот же фон, скругление, тень, подъём и крупная буква).
   Разница одна: ячейка-вариант ПОУЖЕ капельки (когда вариантов несколько, они встают в ряд), а сама
   буква — ТА ЖЕ по размеру. Так переход preview → попап идёт без скачка кегля, как на Android. */
.kb__pop {
    position: absolute;
    bottom: calc(100% + 6px);           /* поднят близко к preview — при переходе не прыгает */
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 2px;
    padding: 4px;
    background: var(--kb-pop-bg);
    border: 1px solid var(--kb-key-border);
    border-radius: var(--kb-radius);
    box-shadow: 0 6px 18px rgba(0,0,0,.18);
    z-index: 30;
}
/* Вариант в попапе — НЕ кнопка, а просто ячейка: выбор ведёт сама клавиша по координатам пальца
   (см. KB._popPick). Своих событий у ячейки нет, поэтому и pointer-events ей ни к чему.
   Буква ПОМЕНЬШЕ, чем в капельке preview, а поле ячейки УЗКОЕ (тесные отступы по ширине) — иначе
   8+ вариантов (акценты латиницы) не влезают в экран (владелец, 2026-07-24). Фон ячейки светлый
   (контейнера), подсвечен только выбранный — синим. */
.kb__pop-key {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: .95em;
    padding: .3em .12em;
    border-radius: 6px;
    background: transparent;
    color: var(--kb-key-fg);
    font-size: calc(var(--kb-font-size) * 1.4);
    line-height: 1.1;
    pointer-events: none;
}
/* Выбор языка зажатием пробела: языки стоят СТОЛБИКОМ, текущий — нижним, у самого пробела (он же
   подсвечен). Чтобы сменить язык, палец уводят вверх — это осознанное действие, а не побочный
   эффект долгого нажатия. Названиям нужна своя ширина и кегль поменьше, иначе «English (US)»
   растянет попап на пол-экрана. */
.kb__pop--lang { flex-direction: column; }
.kb__pop--lang .kb__pop-key {
    min-width: 0;
    padding: .5em 12px;
    font-size: calc(var(--kb-font-size) * .7);
    line-height: 1.15;
    white-space: nowrap;
}
/* Подсвечен ровно один вариант — тот, что напечатается, если отпустить палец сейчас (синим). */
.kb__pop-key[data-sel] {
    background: var(--kb-pop-sel-bg, var(--kb-press-bg));
    color: var(--kb-pop-sel-fg, var(--kb-key-fg));
}
.kb__key[data-open] { z-index: 31; }

/* ВСПЛЫВАЮЩАЯ БУКВА (key preview) — как на клавиатурах телефонов: по касанию печатной клавиши над
   ней всплывает КРУПНАЯ КОПИЯ СИМВОЛА ЦЕЛИКОМ ВЫШЕ КЛАВИШИ (над пальцем), чтобы её не закрывал
   палец и не срезала кромка. Ставит движок только на тач-грани и только у печатных клавиш
   (KB._showPreview).

   Пузырь стоит ПОЛНОСТЬЮ НАД клавишей (bottom > 100%, есть зазор) и ШИРЕ её — бока свешиваются над
   соседями. Между пузырём и клавишей — ПРОСТО ПУСТОТА, без «ножки»-соединителя (владелец, 2026-07-24:
   белый стебель мешал). Буква с воздухом со всех сторон — низ НЕ прижат к кромке.
   Виден он только на тач-грани, но правило общее — на десктопе всплывашку движок не создаёт. */
.kb__preview {
    position: absolute;
    left: 50%;
    bottom: calc(100% + 9px);          /* ПОЛНОСТЬЮ над клавишей, с зазором под «стебель» */
    transform: translateX(-50%);
    min-width: 158%;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Воздух вокруг буквы, снизу НЕ меньше, чем сверху — иначе низ («у», хвост «д», «ц») срезался бы
       нижней кромкой (жалоба владельца 2026-07-24). */
    padding: .22em .34em .26em;
    background: var(--kb-preview-bg);
    color: var(--kb-preview-fg);
    border: 1px solid var(--kb-preview-border);
    border-radius: calc(var(--kb-radius) * 1.5);
    box-shadow: var(--kb-preview-shadow);
    font-size: calc(var(--kb-font-size) * 2.4);   /* КРУПНО: буква видна целиком над пальцем */
    line-height: 1.12;
    white-space: nowrap;
    pointer-events: none;
    z-index: 41;
    /* Мягкое проявление. ТОЛЬКО opacity: transform занят краевым сдвигом (translateX из JS), и
       анимировать его — значит драться с inline-стилем и дёргать пузырь в конце у крайних клавиш. */
    animation: kb-preview-in .06s ease-out;
}
/* Клавиша с всплывашкой поднимается над соседями — иначе пузырь крайней слева уходит ПОД клавишу
   справа (все клавиши position:relative и кроются по порядку в DOM). */
.kb__key[data-preview] { z-index: 41; }
@keyframes kb-preview-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .kb__preview { animation: none; }
}

/* ─────────────────────────── Тач-вид ───────────────────────────
   ВЫСОТА КЛАВИШИ СЧИТАЕТСЯ ИЗ ЕЁ ШИРИНЫ, а не задаётся числом. Ширина на тач-грани адаптивная
   (11 клавиш делят экран), поэтому фиксированная высота даёт колонны: замер до правки на экране
   360px — клавиша 28.3 × 50 px, то есть в 1.77 раза выше, чем шире, при радиусе 10px. На живых
   клавиатурах пропорция около единицы (замер по скринам: Samsung ≈ 1.1, iOS ≈ 1.17, Gboard ≈ 1.33).

   Ширину контейнера берём в единицах контейнера (cqw) — поэтому пересчётов на JS при смене ширины
   окна не нужно. clamp держит клавишу в разумных пределах на очень узких и очень широких экранах.

   ЧИСЛО КОЛОНОК В ФОРМУЛЕ — ПОСТОЯННОЕ (`--kb-cols-base`), а не фактическое у раскладки. Высота
   ряда — свойство КЛАВИАТУРЫ, а не языка: у русской в ряду 11 клавиш, у английской 10, и от
   фактического числа клавиатура скакала в размере при каждом переключении языка (владелец,
   2026-07-22: «английская больше, русская меньше — размер должен быть один»). Эталон — 10 колонок,
   как у латиницы. У раскладки с 11+ клавишами они просто уже, ровно как на телефонах. */
.kb[data-face="mobile"] {
    --kb-cols-base: 10;       /* эталон высоты ряда — НЕ фактическое число клавиш у раскладки */
    --kb-key-ratio: 1.2;      /* высота ряда в ширинах эталонной клавиши */
    --kb-key-min-h: 34px;
    --kb-key-max-h: 58px;
    --kb-gap: 5px;
    --kb-row-gap: 8px;        /* между рядами зазор БОЛЬШЕ, чем между клавишами — как на телефонах */
    /* Радиус — В ДОЛЯХ ОТ КЛАВИШИ, а не числом: клавиша тут узкая, и 10px десктопного скина делали
       из неё капсулу. Замер по живым клавиатурам: скругление около шестой части высоты клавиши. */
    --kb-radius-ratio: .17;
    --kb-radius: calc(var(--kb-key-h) * var(--kb-radius-ratio));
    --kb-font-size: 20px;
    --kb-key-h: clamp(
        var(--kb-key-min-h),
        calc((100cqw - (var(--kb-cols-base) - 1) * var(--kb-gap)) / var(--kb-cols-base) * var(--kb-key-ratio)),
        var(--kb-key-max-h)
    );
    gap: var(--kb-row-gap);
}

@media (max-width: 480px) {
    .kb[data-face="mobile"] { --kb-gap: 4px; --kb-row-gap: 7px; --kb-font-size: 19px; }
}

/* ═══════════ НАМПАД (ДЕСКТОП) — сторонняя панель справа от клавиатуры ═══════════
   Клавиатура НЕ двигается: нампад абсолютно позиционирован СПРАВА от контейнера, в поле страницы.
   Свёрнут (data-np="closed") → видна только торчалка-иконка. Мало места (JS: data-np-fit="below")
   → нампад уходит ВНИЗ отдельным ЦИФРОВЫМ РЯДОМ 1…0. На мобайле нампада нет (движок его не рисует). */
.rkbd__kb .kb { position: relative; }   /* якорь для абсолютного нампада (токены --kb-* тоже тут) */

.kb__numpad {
    position: absolute;
    top: 0;
    left: 100%;
    margin-left: 20px;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    z-index: 2;
}
.kb__np-toggle {
    flex: 0 0 auto;
    height: var(--kb-key-h, 52px);
    min-width: 28px;
    padding: 0 7px;
    display: flex; align-items: center; justify-content: center; gap: 4px;
    border: 1px solid var(--kb-key-border);
    border-radius: var(--kb-radius, 10px);
    background: var(--kb-special-bg);
    color: var(--kb-special-fg);
    box-shadow: var(--kb-key-shadow);
    cursor: pointer; font-size: 20px; line-height: 1;
    -webkit-tap-highlight-color: transparent;
}
.kb__np-toggle svg { display: block; }
/* Стрелка действия: свёрнут — «›» (развернуть), развёрнут — «‹» (свернуть). Кегль чуть крупнее иконки,
   чтобы шеврон читался, но не спорил с сеткой-нампадом рядом. */
.kb__np-arrow { display: block; font-size: 20px; line-height: 1; }
.kb__np-grid {
    display: grid;
    grid-template-columns: repeat(3, var(--kb-key-h, 52px));
    grid-auto-rows: var(--kb-key-h, 52px);
    gap: var(--kb-gap, 8px);
}
.kb__np-grid > .kb__key { flex: none; width: auto; font-size: var(--kb-font-size, 20px); }
.kb__np-grid > .kb__key[data-k="0"] { grid-column: 1 / -1; }   /* «0» на всю нижнюю строку */

/* Свёрнут: сетки нет, торчалка = иконка нампада */
.rkbd__kb[data-np="closed"] .kb__np-grid { display: none; }

/* РАЗВЁРНУТ — закрывашка принадлежит НАМПАДУ, а не клавиатуре:
   (1) она СВЕТЛАЯ, как обычная клавиша: в служебном (тёмном) цвете и на одной линии с Backspace она
       читалась его продолжением — «вторым Backspace», тем более что стрелка тоже смотрит влево
       (владелец, 2026-07-27);
   (2) стоит по ЦЕНТРУ высоты нампада и прижата к нему (зазор = шагу клавиш), а от клавиатуры
       отодвинута — иначе висела в пустоте ближе к клавиатуре, чем к панели, которой управляет.
   Селектор длиннее скинового (`.rkbd[data-skin=…] .kb__np-toggle`) намеренно: цвет обычной клавиши
   берётся из токенов и должен перебивать «служебную» подошву скина. */
.rkbd__kb[data-np="open"] .kb__numpad {
    align-items: center;
    margin-left: 26px;
    gap: var(--kb-gap, 8px);
}
.rkbd__kb[data-np="open"] .kb__numpad .kb__np-toggle {
    background: var(--kb-key-bg);
    color: var(--kb-key-fg);
    border-color: var(--kb-key-border);
    box-shadow: var(--kb-key-shadow);
}

/* Мало места справа — нампад ВНИЗ отдельным цифровым рядом 1…0 (JS ставит data-np-fit="below"). */
.rkbd__kb[data-np-fit="below"] .kb__numpad {
    position: static;
    margin: 14px auto 0;
    justify-content: center;
    width: 100%;
}
/* `[data-np="open"]` тут обязателен: без него это правило (оно идёт ПОЗЖЕ и той же специфичности)
   перебивало `display: none` свёрнутого нампада — внизу ряд 1…0 не сворачивался вовсе. */
.rkbd__kb[data-np-fit="below"][data-np="open"] .kb__np-grid {
    display: flex;
    gap: var(--kb-gap, 8px);
    flex: 1 1 auto;
}
/* Свёрнут ВНИЗУ — одна торчалка: держим её у левого края, там же, где она стоит у развёрнутого ряда,
   иначе при сворачивании кнопка прыгала бы на середину. */
.rkbd__kb[data-np-fit="below"][data-np="closed"] .kb__numpad { justify-content: flex-start; }
.rkbd__kb[data-np-fit="below"] .kb__np-grid > .kb__key { flex: 1 1 0; order: var(--d, 1); }
.rkbd__kb[data-np-fit="below"] .kb__np-grid > .kb__key[data-k="0"] { grid-column: auto; }

/* ── СТРОКА КАНДИДАТОВ (IME: цанцзе, пиньинь, ханча) ─────────────────────────────────────────
   Набранный код и иероглифы, из которых человек выбирает. Живёт НАД контейнером клавиатуры:
   внутри рядов ей нельзя — высота клавиатуры не должна меняться от того, набирает человек или нет. */
.kb__ime {
    display: flex;
    align-items: center;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 6px 8px;
    margin-bottom: 4px;
    border-radius: var(--kb-radius, 8px);
    background: var(--kb-key-bg, #f4f2ee);
    scrollbar-width: thin;
}
.kb__ime[hidden] { display: none; }
.kb__ime-code {
    flex: 0 0 auto;
    padding: 2px 8px;
    border-radius: 6px;
    font: 600 15px/1.4 var(--kb-font, inherit);
    letter-spacing: .08em;
    color: var(--kb-hint, #8a8177);
    background: var(--kb-bg, #fff);
}
.kb__ime-cand {
    flex: 0 0 auto;
    min-width: 40px;
    padding: 4px 10px;
    border: 0;
    border-radius: 6px;
    font: 22px/1.3 var(--kb-font, inherit);
    color: var(--kb-key-fg, #1a1f26);
    background: var(--kb-bg, #fff);
    cursor: pointer;
    box-shadow: 0 1px 0 rgba(0, 0, 0, .12);
}
.kb__ime-cand:active { transform: translateY(1px); box-shadow: none; }
/* НОМЕР КАНДИДАТА — только там, где кандидата этой же цифрой и выбирают с клавиатуры (полоса
   получает флаг от раскладки, см. `convert.select_digits`). Живые продукты рисуют номер рядом с
   кандидатом, иначе о работе цифр никто не догадается. Номер мелкий и приглушённый: главное на
   фишке — сам знак, а не его порядковый номер. */
.kb__ime-cand[data-num]::before {
    content: attr(data-num);
    margin-right: 5px;
    font-size: 12px;
    line-height: 1;
    vertical-align: 3px;
    color: var(--kb-hint, #8a8177);
}
.kb__ime-cand.is-sel[data-num]::before { color: var(--kb-key-fg, #1a1f26); }
/* ВЫДЕЛЕННЫЙ КАНДИДАТ — только у кандидатной сессии (конверсия набранного текста): её триггер,
   нажатый второй раз, ведёт по списку, и человек обязан видеть, что подтвердит Enter. У набора по
   коду выделения нет вовсе — там этот класс не появляется, и полоса выглядит ровно как прежде. */
.kb__ime-cand.is-sel {
    background: var(--kb-key-active, #e8e4dc);
    box-shadow: inset 0 0 0 2px var(--kb-accent, #3b5998);
}
.kb__ime-none { color: var(--kb-hint, #8a8177); font-size: 15px; }
/* Листалка кандидатов: у частых чтений их сотни, на полосу помещается дюжина. Стрелки и счётчик
   страниц — единственный способ добраться до остальных, поэтому они видимы всегда, когда страниц
   больше одной, и работают пальцем, мышью и с клавиатуры. */
/* Блок листания липнет к левому краю прокручиваемой полосы: иначе на телефоне стрелка «вперёд»
   оказывается за краем экрана вместе с концом ленты кандидатов. */
.kb__ime-pager {
    position: sticky;
    left: 0;
    z-index: 1;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
    padding-right: 4px;
    background: var(--kb-key-bg, #f4f2ee);
}
.kb__ime-nav {
    flex: 0 0 auto;
    min-width: 28px;
    padding: 4px 8px;
    border: 0;
    border-radius: 6px;
    font: 20px/1 var(--kb-font, inherit);
    color: var(--kb-key-fg, #1a1f26);
    background: var(--kb-bg, #fff);
    cursor: pointer;
    box-shadow: 0 1px 0 rgba(0, 0, 0, .12);
}
.kb__ime-nav[disabled] { opacity: .35; cursor: default; box-shadow: none; }
.kb__ime-nav:not([disabled]):active { transform: translateY(1px); box-shadow: none; }
.kb__ime-page {
    flex: 0 0 auto;
    font: 12px/1.4 var(--kb-font, inherit);
    color: var(--kb-hint, #8a8177);
    padding-left: 2px;
}
@media (hover: hover) {
    .kb__ime-cand:hover { background: var(--kb-key-hover, #fbfaf8); }
    .kb__ime-nav:not([disabled]):hover { background: var(--kb-key-hover, #fbfaf8); }
}

/* В маленькой карте подписи должны ЧИТАТЬСЯ: при 11px кегле клавиш .5em превращал их в 5px. */
.rkbd__kb .kb[data-mode="small"] .kb__hint { font-size: 8px; }
/* И стоять ВЫШЕ на пиксель — вместе с опущенным центром это разводит их чернила окончательно.
   Ровно 1px, а не 0: при 0 подпись, которая сама является знаком письма (деванагарская «औ» в углу
   у непальской и хинди), вылезала на пиксель за верхнюю кромку клавиши. */
.rkbd__kb .kb[data-mode="small"] .kb__hint,
.rkbd__kb .kb[data-mode="small"] .kb__hint--corner { top: 1px; }

/* ─────────────────── ПОЛНОРАЗМЕРНАЯ КАРТА НА ТЕЛЕФОНЕ (`data-mode="full"`) ───────────────────
 * Режим «да ну этот транслит, наберу тапами»: клавиатура тут рабочая, а не декоративная, и её
 * геометрия считалась замером, а не на глаз (preflight 2026-08-10, kbtest/visualfocus.js).
 *
 * ЧТО БЫЛО. На 320px клавиша выходила 21.4×34, кегль центра 19px, подпись .5em — и чернила центра
 * задевали угловую подпись у 48 раскладок: 3241 пересечение по трём ширинам и двум слоям.
 * Перебор восьми конфигураций показал, какие рычаги работают, а какие только кажутся:
 *   • `top: 0` у подписи убирает пересечения, но выталкивает её ЗА кромку (25 → 66 выходов) — плохо;
 *   • одна высота (44px) или один сдвиг центра (+3px) снимают меньше трети;
 *   • работает СВЯЗКА: высота 44px + центр 17px + подпись .45em + сдвиг центра +3px = 0 пересечений
 *     и 5 выходов подписи вместо 25.
 * Остаток (обрезание широких центров и три подписи-знака письма) снимает подгонка по факту —
 * `KB.prototype._fitFull` в движке; CSS даёт ей базу, к которой она каждый раз возвращается.
 *
 * Ширины клавиш, ряды и раскладка НЕ трогаются: правило поднимает только высоту и типографику. */
.rkbd__kb .kb[data-mode="full"] .kb__key { min-height: 44px; }
.rkbd__kb .kb[data-mode="full"] { --kb-cap-nudge: 3px; }
.rkbd__kb .kb[data-mode="full"] .kb__cap { font-size: 17px; }
.rkbd__kb .kb[data-mode="full"] .kb__hint,
.rkbd__kb .kb[data-mode="full"] .kb__hint--corner { font-size: .45em; }

/* ─────────────────────── ОБЩАЯ ПАЛИТРА ЗНАКОВ (типографика и валюты) ───────────────────────
 * Клавиша палитры показывает СИМВОЛ и под ним КОРОТКУЮ ПОДПИСЬ. Подпись обязательна: без неё
 * половину пакета не различить глазом — `‐ ‑ ‒ – —` рисуются почти одинаково, как и `“ ” „`,
 * `‘ ’ ‚`, а `¥` от `￥` отличается только шириной. В поле подпись не попадает никогда
 * (печатается data-k), она чисто зрительная — и потому aria-hidden.
 */
.kb__key--noted {
    flex-direction: column;
    justify-content: center;
    gap: 0;
    line-height: 1.05;
    padding-inline: .2em;
}
.kb__key--noted .kb__cap { font-size: 1.15em; }
.kb__note {
    display: block;
    font-size: .58em;
    opacity: .72;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    pointer-events: none;
}
/* Вкладка категории: активная выделена, но БЕЗ bootstrap-обрамления (глобальное правило сайта). */
.kb [data-a="palette-tab"][data-active="on"],
.kb [data-a="palette-tab"][aria-pressed="true"] { font-weight: 700; }
