/* Домашний экран страницы поиска — минималистичный скин.
 *
 * URL: /nodejs/res/css/home.css (маунт search/ уже есть в dg-light.js, правок сервера не нужно).
 *
 * ВСЁ здесь живёт под классом-скином body.dg-skin-minimal и/или под состоянием
 * body.dg-state-home. Это сознательно: минималистичный стиль сейчас применяется ТОЛЬКО к
 * домашнему экрану, а выдача и ридер остаются в нынешнем оформлении — общий стиль вырабатывается
 * отдельно, по мере объединения поиска и ридера. Позже скин станет пунктом в /settings/, и тогда
 * его хватит расширить на остальные состояния, не переписывая эти правила.
 *
 * Никаких внешних шрифтов (в демке был Google Fonts — на проде внешний CDN не подключаем) и
 * никакой своей палитры: цвета те же, что уже у поиска и ридера, см. блок ниже.
 *
 * Тёмная тема здесь — body.dark, а НЕ html.dark как в демке: класс ставит themeswitch.js на
 * <body> (assets/js/themeswitch.js, bodyTag.classList.add("dark")).
 */

/* Палитра — НЕ своя. Это те же значения, которыми уже живут поиск и ридер: цвета ридера
   объявлены в reader/css/rus-multi.css (--off-white rgb(221,221,221), --light-off-white
   rgb(253,253,253), --off-black rgb(4,1,19), --dark-gray #5a5a5a, --light-gray #8f8f8f,
   --blue #3434be, в тёмной теме ссылки rgb(122,122,249)), а поверхности и границы — Bootstrap,
   как у кнопок .btn-light в ряду инструментов выдачи. Значения повторены буквально, а не через
   var(): rus-multi.css подключается лениво, только вместе с ридером, и до первого открытия
   текста её переменных на странице просто нет. Тот же приём уже применён к #language-button
   в <head> этой страницы.

   ОБНОВЛЕНО: светлая палитра переехала на землистые нейтрали и зелёный акцент (макет
   production-v4). Тёмная осталась на боевом --off-black, см. комментарий у body.dark ниже. */

/* Owner: "ширина страницы... получается неудобно, что под пальцем страница ездит" — decorative
   absolutely-positioned elements (e.g. reader/css/uiextra.css's .copyLink-start markers, which
   sit at left:-1em relative to a segment that can itself start near the viewport's left edge)
   push a few px past the viewport edge. They don't add real scrollable content, just enough
   negative overflow for mobile Safari/Chrome to treat the page as horizontally pannable — this
   guard clips exactly that kind of stray edge overflow without touching any element's OWN
   overflow-x:auto (home.css's own #dg-hero-band horizontal scrollers etc. are unaffected, they
   scroll inside their own box regardless of what the page root clips). Unscoped (not under
   body.dg-skin-minimal) — this single shell page (search/index.html) serves home/results/reader
   alike, and the bug isn't specific to the minimal skin.

   clip, not hidden: `overflow-x: hidden` on html/body makes the body a scroll container, which
   silently kills `position: sticky` for every descendant (Chrome: the sticky element has no
   scrollport left to stick within). That is what kept .toc-aside (Translator filter) from parking
   under the pinned header — it just scrolled away with the list and slid under the band. `clip`
   clips the same stray overflow without creating a scroll container, so sticky works (verified in
   the browser: aside top goes 81 -> 77 = stack height + gap on scroll). `hidden` stays first as
   the fallback for engines without `clip` (pre-16 Safari), which keep today's behaviour. */
html, body { overflow-x: hidden; overflow-x: clip; }
/* Owner: "сдвигаются на мм инпуты между ридером и результатами" — without this, the vertical
   scrollbar only appears once a page's content actually overflows, and since the centered
   .dg-hero-form's width is the same 520px in results/reader/toc/404 (see body.dg-skin-minimal
   rules below), a short results page (no scrollbar) vs a long reader page (scrollbar) differ by
   the scrollbar's width, shifting the centered field left/right by half of it. Reserving the
   gutter unconditionally keeps the field pixel-identical across states regardless of content
   height. Not scoped to dg-skin-minimal, same reasoning as overflow-x above. */
html { scrollbar-gutter: stable; }

/* Owner: "текст на мобильном слишком мелкий... во всех частях... в 1.2 раза крупнее" (было 1.5 —
   owner: "слишком крупно"). Unscoped (not under body.dg-skin-minimal) on purpose, same reasoning
   as the overflow-x rule above: this one shell page serves home/results/reader/toc alike, and the
   complaint wasn't specific to the minimal skin. One rem-scale line covers ALL of it because the
   whole codebase (this file, Bootstrap utilities, --dg-* components) sizes type in rem, not px —
   rem always resolves against THIS root value, so nothing per-component needs touching.

   The chrome-specific opt-outs from this bump (icon buttons, toolbar/tab links — owner: "текст...
   не должно влиять на расстояние между иконками и текстовыми ссылками") live at the very END of
   this file, not here: they target selectors (.dg-tile, #reader-toolbar, …) that this file ALSO
   sets font-size on later at their normal spot, same specificity — same-specificity CSS is decided
   by source order, so the override has to come after, not before (this exact trap bit an earlier
   round of this file too, see the #dg-mega comment further down). */
@media (max-width: 767.98px) {
    :root { --dg-mobile-scale: 1; }
    html { font-size: calc(100% * var(--dg-mobile-scale)); }
}

/* Lato — the reference's typeface, self-hosted (public/overrides/fonts/), not a CDN link — the
   "no external fonts" rule above still holds. Lato 2.015 (Debian fonts-lato, OFL): unlike the
   Google-hosted v1 it has Cyrillic and the Pāḷi diacritics (ā ī ū ṁ ṅ ñ ṭ ḍ ṇ ḷ), so headings,
   Russian UI and quotes all set in one face; a real Semibold for the 600 headings/labels. */
@font-face { font-family: "Lato"; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fonts/lato-400.woff2") format("woff2"); }
@font-face { font-family: "Lato"; font-style: italic; font-weight: 400; font-display: swap; src: url("/assets/fonts/lato-400-italic.woff2") format("woff2"); }
@font-face { font-family: "Lato"; font-style: normal; font-weight: 600; font-display: swap; src: url("/assets/fonts/lato-600.woff2") format("woff2"); }
@font-face { font-family: "Lato"; font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/fonts/lato-700.woff2") format("woff2"); }
/* Pali in scripts most devices ship no font for (?script=, public/overrides/js/pali-script.js):
   Noto Sans Brahmi / Chakma / Tai Tham / Myanmar (Mon letters) / Lao (Pali letters), OFL. Each face
   is limited to its own Unicode block, so Latin and Cyrillic keep their current fonts and a file is
   downloaded only when a page actually shows letters from that block. Used as a fallback family
   after sans-serif: table.css (* rule) and --bs-font-sans-serif (extrastyles.css/styles.css, which
   every Lato stack ends in). font-weight 100-900 so bold headings use the same file. Not added as
   extra "Lato" faces: faces with different weight descriptors are not merged into one family, so
   the Noto faces were skipped for Lato text. */
@font-face { font-family: "DG Pali"; font-weight: 100 900; font-display: swap; src: url("/assets/fonts/noto-brahmi.woff2") format("woff2"); unicode-range: U+11000-1107F; }
@font-face { font-family: "DG Pali"; font-weight: 100 900; font-display: swap; src: url("/assets/fonts/noto-chakma.woff2") format("woff2"); unicode-range: U+11100-1114F; }
@font-face { font-family: "DG Pali"; font-weight: 100 900; font-display: swap; src: url("/assets/fonts/noto-taitham.woff2") format("woff2"); unicode-range: U+1A20-1AAF; }
@font-face { font-family: "DG Pali"; font-weight: 100 900; font-display: swap; src: url("/assets/fonts/noto-myanmar.woff2") format("woff2"); unicode-range: U+1000-109F, U+A9E0-A9FF, U+AA60-AA7F; }
@font-face { font-family: "DG Pali"; font-weight: 100 900; font-display: swap; src: url("/assets/fonts/noto-lao.woff2") format("woff2"); unicode-range: U+0E80-0EFF; }
body.dg-skin-minimal {
    /* Фон страницы. Отдельным токеном, а не через --bs-body-bg: тот у Bootstrap белый ВСЕГДА —
       тёмную тему на этом сайте делает body.dark из langswitch.css, до бутстраповских переменных
       она не дотягивается. Пока правило ниже брало --bs-body-bg, тёмная главная выбеливалась. */
    --dg-page: #ffffff;
    --dg-surface: #ffffff;
    --dg-surface-hover: #f5f4f1;
    --dg-surface-active: #eae8e2;
    --dg-border: #e7e5de;
    --dg-border-strong: #d7d4c9;
    --dg-text: #1b1d19;
    --dg-text-2: #5c6058;
    /* apple-design audit: was #93968c on white ≈ 3:1, fails WCAG AA (4.5:1) for text.
       Darkened to ~5:1 while keeping the same olive-gray hue. */
    --dg-text-muted: #6e716a;
    --dg-navy: #243448;
    --dg-navy-2: #1b2836;
    --dg-accent: #149c7c;
    /* Акцент для ТЕКСТА. В светлой теме совпадает с основным, в тёмной берёт более светлый тон:
       прод-зелёный для значков в подписи не читается. */
    --dg-accent-ink: #0f7c63;
    --dg-accent-dark: #0f7c63;
    --dg-accent-bg: #dff3ec;
    /* Glyph on the accent-bg disc (tile icons, announcement close) — reference .disc color. */
    --dg-icon-ink: #0c6a55;
    --dg-radius: 10px;
    --dg-font: "Lato", var(--bs-body-font-family);
    --dg-ease: cubic-bezier(0.22, 0.68, 0, 1);
    /* One-time shine sweep on #home-motto (below) — dimmer than pure white here on purpose:
       --dg-page is solid #fff in this theme, and --dg-text is near-black, so a full-white
       highlight would wash the swept letters out against the page for an instant (owner: "чуть
       менее ярким белым, чтобы пятно света не сливало буквы с фоном"). */
    --dg-motto-shine: #cfcfcf;
    /* Боковое поле страницы: столько добавляет .container-fluid вокруг .table-wrapper. Нужно
       hero-полосе, чтобы вылезти из этого поля на всю ширину экрана (margin с минусом). На
       телефоне это поле сжато до 3px — см. медиазапрос в <head> index.html. */
    --dg-gutter: 12px;
}
@media (max-width: 767.98px) {
    body.dg-skin-minimal { --dg-gutter: 3px; }
}

/* Тёмная тема отталкивается от БОЕВОГО тёмного фона: страница в тёмной теме — rgb(17,17,17),
   его задаёт [data-theme="dark"] из assets/css/extrastyles.css (замерено на живой странице; в
   langswitch.css есть ещё body.dark с --off-black, но выигрывает первое). Поверхности здесь —
   нейтральные, на пол-тона светлее фона: возьми мы оливковую основу из макета, главная встала бы
   другим цветом, чем соседние страницы, и переход между ними читался бы как переход на другой
   сайт. От макета берём только зелёный акцент — в тёмной теме он и правда звонче синего. */
body.dg-skin-minimal.dark {
    --dg-page: #111111;
    --dg-surface: #191919;
    --dg-surface-hover: #202020;
    --dg-surface-active: #2a2a2a;
    --dg-border: #2c2c2c;
    --dg-border-strong: #3b3b3b;
    --dg-text: rgb(221, 221, 221);
    /* --dg-text here is already near-white on a near-black page — full white reads as a clean
       glint with no wash-out risk (owner: "на темной она уже почти белая, так что свет можно
       сделать чисто белым"). */
    --dg-motto-shine: #ffffff;
    --dg-text-2: #a8a8a8;
    --dg-text-muted: #7c7c7c;
    --dg-navy: #1b2836;
    --dg-navy-2: #131c26;
    /* Зелёный в тёмной теме — БОЕВОЙ, приглушённый, а не яркий из светлой: #136857 у прода стоит
       на .bg-primary и .menu-icon, #025242 на .btn-primary, #09967a на ссылках
       ([data-theme="dark"] в assets/css/extrastyles.css). Яркий #3fe3bc из макета на тёмном фоне
       бил в глаза и не совпадал ни с одной соседней страницей.
       Для значков берём ровно прод-цвет, для текста — прод-цвет ссылок: #136857 в подписи на
       тёмном фоне уже нечитаем (контраст ниже 3:1), а у прода для текста и заведён отдельный,
       более светлый тон. */
    --dg-accent: #136857;
    --dg-accent-ink: #09967a;
    --dg-accent-dark: #025242;
    --dg-accent-bg: #12241f;
    --dg-icon-ink: #16b394;
}

/* ============================================================================
   Показ/скрытие домашних блоков.
   Схлопывание через max-height + opacity, а не display:none — display не анимируется, а нам
   нужно, чтобы при уходе в выдачу шапка и плитки СЖИМАЛИСЬ, поднимая инпут вверх, а не исчезали
   рывком. max-height заведомо больше реальной высоты; overflow:hidden прячет остаток во время
   перехода. Шторки живут отдельно, в конце <body>, и под это схлопывание не попадают.
   ============================================================================ */
#home-hint,
#home-pane {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
    /* No transition anymore: the home screen's enter/exit (dg-drop-in / home-out keyframes
       further down) already animates the tiles; this collapse ran AFTER home-out and made the
       tiles vanish last, after everything else (owner). #home-hint keeps its own below. */
    margin: 0;
}
#home-hint { transition: max-height 0.34s var(--dg-ease), opacity 0.22s ease, transform 0.34s var(--dg-ease), margin 0.34s var(--dg-ease); }

body.dg-state-home #home-hint,
body.dg-state-home #home-pane {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

/* Отступ инпута от заголовка — раньше был большим (74px) специально, чтобы под собой
   зарезервировать место для #dg-announce (плашка лежала АБСОЛЮТНО над полем, см. её комментарий
   ниже). Теперь плашка в обычном потоке ПОСЛЕ поля (production-v4 redesign,
   docs/Home-standalone.html: поле → строка области поиска → плашка → плитки), резервировать
   тут больше нечего — просто небольшой зазор от подзаголовка. */
body.dg-state-home .hero-row { margin-top: 22px; }
body.dg-state-home #home-pane  { max-height: 2000px; margin: 22px 0 0; }
/* #home-hint — position:absolute (см. .hero-row/#home-hint в search/index.html), max-height/
   opacity/transform ниже всё ещё нужны для схлопывания при уходе с главной, margin — только
   небольшой зазор от нижнего края поля, не отступ в потоке (его больше нет в потоке). */
body.dg-state-home #home-hint { max-height: 60px; margin-top: 8px; }

/* Ширина поля по состояниям: на главной оно — центр экрана, в выдаче и чтении уступает место
   содержимому. Переход между значениями анимируется (transition на .dg-hero-form в index.html).
   width:100% обязателен: форма — flex-элемент в .hero-row, а flex-элемент по умолчанию сжимается
   до содержимого, и одного max-width мало (замерено: поле выходило 270px вместо 640px). */
/* display:block — ответ на `#form { display:flex; justify-content:center; align-items:baseline }`
   из /assets/css/langswitch.css (общий файл, его не трогаем): из-за него поле-оболочка была
   flex-элементом и сжималась до содержимого — 269px вместо 640px, и вдобавок выравнивалась по
   базовой линии. Здесь форма — простой блок, а вся раскладка внутри у .dg-input-shell. */
body.dg-skin-minimal #form.dg-hero-form { display: block; width: 100%; }
body.dg-skin-minimal.dg-state-home .dg-hero-form { max-width: 620px; }
body.dg-skin-minimal.dg-state-results .dg-hero-form,
body.dg-skin-minimal.dg-state-reader .dg-hero-form,
body.dg-skin-minimal.dg-state-toc .dg-hero-form { max-width: 520px; }

/* ============================================================================
   Фирменная hero-полоса главной.
   Тёмный сине-зелёный с переходом в зелёный — та же пара, что в шапке боевого сайта. Вывеска,
   девиз, поле и подсказка сидят НА ней: на главной это один цельный блок, а не четыре строки
   на белом. В выдаче и в чтении полоса схлопывается — фон снимается, отступы обнуляются, и
   разметка возвращается к обычной (их оформление делаем отдельно).
   ============================================================================ */
/* Переходов здесь намеренно НЕТ. Полоса появляется и исчезает вместе со сменой состояния, а
   состояние обязано примениться сразу: анимируемое свойство во вкладке, которая не рисует кадры
   (фоновая вкладка, свёрнутое окно), застревает на начальном значении — замерено, полоса
   оставалась с домашним фоном и отступом уже в выдаче. Плавность ухода даёт схлопывание
   #home-motto/#home-hint/#home-pane по max-height, этого достаточно. */
/* Полоса тянется во ВСЮ ширину окна, а не до края колонки. Отрицательного margin по полю
   контейнера не хватало: у .table-wrapper есть свой max-width 1600px, и на мониторе шире полоса
   обрывалась вертикальной границей — заливка кончалась, а страница шла дальше, и это читалось
   как недоделанный кусок. 50% — середина колонки, 50vw — половина окна; разница и есть тот
   вылет, который нужно добрать с каждой стороны. */
#dg-hero-band {
    /* /var(--dg-zoom): при масштабе интерфейса (issue #13, зум на html) vw остаются в реальных
       пикселях окна, а всё остальное уже масштабировано — без деления полоса выезжает за край. */
    width: calc(100vw / var(--dg-zoom, 1));
    margin-left: calc(50% - 50vw / var(--dg-zoom, 1));
    margin-right: calc(50% - 50vw / var(--dg-zoom, 1));
    padding: 0;
    background: none;
}
body.dg-state-home #dg-hero-band {
    /* Съедаем .mt-2 родителя: полоса должна начинаться от самого верха окна, иначе над ней
       остаётся белая щель в 8px и она перестаёт читаться как шапка. */
    margin-top: -0.5rem;
    padding-bottom: 24px;
    /* No background of its own anymore — the dark color lives on #dg-hero-navbar below, sized
       to just the navbar row, not the whole band (production-v4 redesign,
       docs/Home-standalone.html: a slim dark bar, headline/search on the plain page below it). */
}
/* Full-bleed dark navbar strip, home only — same 100vw/negative-margin trick as #dg-hero-band
   itself, just for the (much shorter) top row alone. */
#dg-hero-navbar { display: none; }
body.dg-state-home #dg-hero-navbar {
    display: block;
    width: calc(100vw / var(--dg-zoom, 1));
    margin-left: calc(50% - 50vw / var(--dg-zoom, 1));
    margin-right: calc(50% - 50vw / var(--dg-zoom, 1));
    background: var(--dg-navy);
}
.dg-hero-inner {
    max-width: 700px;
    margin: 0 auto;
    padding: 0 var(--dg-gutter, 12px);
}
/* --dg-gutter сжимается до 3px на телефоне ради ПЛОТНОЙ таблицы выдачи (#search-pane, см.
   index.html) — там это осознанный выбор, каждый пиксель ширины строки на счету. Поле ввода на
   главной — не таблица, и 3px от края экрана читались как «упирается в край» (жалоба владельца).
   Отвязываем именно этот контейнер от переменной, не трогая саму переменную (другие потребители
   3px могут появиться позже и по-прежнему хотят именно 3px). */
@media (max-width: 767.98px) {
    .dg-hero-inner { padding: 0 14px; }
    /* Тот же 3px-сквоз (index.html, ради плотной таблицы выдачи) достаётся и главной — вход и
       плитки лежат в ТОМ ЖЕ .container-fluid.mt-2, что и таблица. На главной строк с колонками
       нет, экономить пиксели ширины не для чего — только на этом состоянии возвращаем воздух.
       Селектор специфичнее, чем правило в index.html (доп. класс dg-state-home), поэтому
       порядок подключения файлов не важен. */
    body.dg-state-home > .container-fluid.mt-2 { padding-left: 14px; padding-right: 14px; }
}

/* На полосе весь текст светлый — независимо от темы: подложка тёмная в обеих. */
body.dg-state-home #dg-hero-band .dg-brand-name { color: #fff; }
body.dg-state-home #dg-hero-band .dg-icon-btn { color: #eaf4ef; }
body.dg-state-home #dg-hero-band .dg-icon-btn:hover,
body.dg-state-home #dg-hero-band .dg-icon-btn:focus-visible {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}
/* Абрис лого нужен только на светлом фоне; на полосе логотип и так контрастен. */
body.dg-state-home #dg-hero-band .dg-brand-logo { filter: none; }

/* ============================================================================
   Шапка главной: лого с названием слева, бургер в противовес справа.
   Только на главной. В выдаче и в чтении вывеска убирается совсем — там от знака остаётся
   ракушка внутри поля, а бургер стоит правее поля (.dg-menu-btn-hero).
   ============================================================================ */
/* Two children only (brand, menu button) since the headline moved into its own block below
   (#dg-hero-heading) — plain space-between, no grid/centering math needed for a middle child
   anymore. */
/* Geometry measured off the reference (docs/Home-standalone.html, header.bar): 60px tall strip,
   33px content row vertically centered, 920px inner width. Fixed height rather than padding so
   the bar reads the same regardless of what the logo/wordmark happen to measure. */
#dg-topbar {
    display: none;
    position: relative; z-index: 20; /* the Brahmi tag tooltip must paint over the content below the bar */
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    height: 60px;
    padding: 0;
    font-family: var(--dg-font);
}
body.dg-state-home #dg-topbar { display: flex; }
body.dg-state-home .dg-hero-inner { max-width: 920px; }

/* Compass/theme/burger cluster, right side of the navbar row. Reference: 33px square buttons,
   8px radius, 14px glyphs, light steel-blue ink (#cfdae5), 10px apart. */
.dg-topbar-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}
@media (min-width: 768px) { .dg-topbar-actions { gap: 0; } }
body.dg-state-home #dg-topbar .dg-icon-btn {
    width: 33px;
    height: 33px;
    border-radius: 8px;
    color: #cfdae5;
}
body.dg-state-home #dg-topbar .dg-menu-btn svg { width: 15px; height: 15px; }
/* compass.svg/circle-half-stroke.svg ship with a fixed mid-gray fill (#989898) for use on light
   backgrounds elsewhere on the site — brighten them for this dark strip the same way dark-theme
   icon adjustments already do elsewhere in this codebase (invert-based filters, see e.g.
   .autocomplete-history-icon further down this file), rather than fork separate white asset
   files just for this one row. opacity(0.85) lands them on the same #cfdae5-ish tone as the
   inline-SVG burger next to them. */
.dg-topbar-icon-img { width: 14px; height: 14px; display: block; filter: brightness(0) invert(1) opacity(0.85); }

/* Бургеров в разметке два — в шапке и рядом с полем: перенести один элемент между строками
   средствами CSS нельзя, а состояния требуют разных мест. Оба открывают одно и то же меню. */
/* Селектор с body — намеренно: .dg-icon-btn ниже в этом же файле задаёт display:inline-flex той
   же специфичностью и выигрывал бы по порядку (замерено: бургер оставался виден и на главной). */
body .dg-menu-btn-hero { display: none; }
body.dg-state-results .dg-menu-btn-hero,
body.dg-state-reader .dg-menu-btn-hero,
body.dg-state-toc .dg-menu-btn-hero { display: inline-flex; }

#dg-brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: var(--dg-text);
}
/* "Pāḷi Canon" next to the wordmark (reference header.bar: 11.5px, muted steel blue). */
@font-face { font-family: "DG Brahmi"; font-display: swap; src: url("/assets/fonts/brahmi-subset.woff2") format("woff2"); unicode-range: U+11000-1107F; }
.dg-brand-tag {
    font-size: 11.5px;
    font-weight: 400;
    color: #93a5b8;
    white-space: nowrap;
}
/* issue #14: phones — the tag is the first thing to give up so the header icons fit. */
@media (max-width: 575.98px) { .dg-brand-tag { display: none; } }
#dg-brand:hover { color: var(--dg-text); }

/* Лого в шапке. Картинка почти белая (см. /assets/img/dgsanhkalogo.png: раскрытая книга серая,
   а лепестки-страницы и раковина — почти #fff), и на светлом фоне верх логотипа пропадал.
   Кружок-подложка эту беду решал, но выглядел наклейкой; вместо него — тонкий абрис ПО КОНТУРУ
   самой картинки: четыре drop-shadow по сторонам света дают ровную обводку в 1px (у filter нет
   своего «обводящего» примитива, это обычный приём для png с прозрачностью).
   В тёмной теме логотип и так виден на тёмном фоне — обводка там только пачкала бы края. */
.dg-brand-logo {
    width: 34px;
    height: 34px;
    flex: none;
    object-fit: contain;
    display: block;
    filter:
        drop-shadow(1px 0 0 rgba(4, 1, 19, 0.45))
        drop-shadow(-1px 0 0 rgba(4, 1, 19, 0.45))
        drop-shadow(0 1px 0 rgba(4, 1, 19, 0.45))
        drop-shadow(0 -1px 0 rgba(4, 1, 19, 0.45));
}
body.dark .dg-brand-logo { filter: none; }

/* Главный логотип на главной странице — на 10% крупнее базового 34px (34*1.1≈37, владелец:
   "мелко"). #dg-brand — единственный полный лого+название лок-ап, показывается только на
   главной (в выдаче/чтении остаётся только ракушка внутри поля, другая картинка) — точечный
   override, не трогает базовый размер, которым пользуются другие места (боковое меню ниже). */
/* History: 34 → 37 → 48 → 72px square, and 100×58 + no wordmark on phones (owner rounds).
   Superseded by the production-v4 redesign (docs/Home-standalone.html): the slim 60px bar
   carries a 30px-tall logo at its natural ratio (≈52×30) with the wordmark beside it, on every
   width — the big-logo/mobile-only-logo rules are gone with the tall band they were sized for. */
#dg-brand .dg-brand-logo { width: auto; height: 30px; }

/* Маленькая копия лого в шапке бокового меню — там та же история со светлыми лепестками. */
.dg-drawer-head .dg-brand-logo { width: 26px; height: 26px; }

.dg-brand-name {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dg-text);
}
/* Owner: "Dhamma.Gift с больших букв". text-transform вместо переписывания текста: "." рвёт
   слово для capitalize так же, как пробел ("dhamma.gift" -> "Dhamma.Gift"), поэтому одно правило
   вместо второй захардкоженной строки.
   БЕЗ медиазапроса (было `min-width: 768px`, owner: "на планшетах тоже с большой, а то разнобой"):
   надпись в принципе показывается только там, где ей место (на главной ниже 768px её прячет
   правило выше, остаётся одно лого), так что ограничивать ЕЩЁ и регистр было незачем — ровно это
   и давало строчные буквы у той же надписи в шапке бокового меню, где она видна на любой ширине,
   включая узкие планшеты и телефоны. */
.dg-brand-name { text-transform: capitalize; }

/* Кнопка-иконка шапки (бургер, крестик в меню) — без рамки и заливки. */
.dg-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--dg-text-2);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.dg-icon-btn:hover,
.dg-icon-btn:focus-visible { background: var(--dg-surface-hover); color: var(--dg-text); }

/* Ряд с полем: само поле тянется, бургер стоит рядом и не сжимается. Ширину на главной держит
   .dg-hero-inner, поэтому своего max-width здесь больше нет. */
body.dg-skin-minimal .hero-row {
    max-width: 700px;
    margin-left: auto;
    margin-right: auto;
    flex-wrap: nowrap;
}
body.dg-state-home .hero-row { max-width: none; margin-bottom: 0 !important; }
body.dg-skin-minimal #form.dg-hero-form { flex: 1 1 auto; min-width: 0; }

/* ============================================================================
   Поле ввода: знак сайта + поле + очистить + быстрые настройки + лупа, всё в одной рамке
   ============================================================================ */
.dg-input-shell {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 8px 6px 10px;
    background: var(--dg-surface);
    border: 1px solid var(--dg-border);
    border-radius: 28px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}
.dg-input-shell:hover { border-color: var(--dg-border-strong); }
.dg-input-shell:focus-within {
    background: var(--dg-surface);
    border-color: var(--dg-border-strong);
    box-shadow: 0 0 0 3px var(--dg-accent-bg);
}
/* В выдаче/чтении --dg-surface (фон поля) и --dg-border (рамка) почти совпадают с фоном
   страницы (--dg-page) — поле и кнопки в нём читались как "почти невидимые" что в светлой,
   что в тёмной теме (владелец, со скриншотом). На главной то же поле — светлая карточка
   поверх ТЁМНОЙ полосы (правило выше, .dg-state-home), там контраст и так есть, не трогаем.
   Цвета — не новые: те же, что уже у #paliauto/#language-button/#scrollToTopBtn на проде и в
   reader-template.html (reader/css/index.css: --off-white/--dark-gray/--dark-blue) — владелец
   явно попросил взять оттуда. */
/* Заодно — владелец: поле "стало слишком большим" (50px высотой, замерено) рядом с рядом
   компактных 19px-иконок ниже (#results-toolbar/#reader-toolbar) — непропорционально. Паддинг
   потоньше, сами кнопки (32-34px) не трогаем — они те же, что и в остальной шапке. */
body.dg-state-results .dg-input-shell,
body.dg-state-reader .dg-input-shell,
body.dg-state-toc .dg-input-shell {
    padding: 4px 6px 4px 8px;
    background: rgb(221, 221, 221);
    border-color: #5a5a5a;
}
body.dg-state-results .dg-input-shell .dg-shell-btn,
body.dg-state-reader .dg-input-shell .dg-shell-btn,
body.dg-state-toc .dg-input-shell .dg-shell-btn,
body.dg-state-reader .dg-shell-toc {
    color: #5a5a5a;
}
body.dg-state-results #form #paliauto.searchinput,
body.dg-state-reader #form #paliauto.searchinput,
body.dg-state-toc #form #paliauto.searchinput {
    color: #2b2b2b;
}
body.dg-state-results #form #paliauto.searchinput::placeholder,
body.dg-state-reader #form #paliauto.searchinput::placeholder,
body.dg-state-toc #form #paliauto.searchinput::placeholder {
    color: #5a5a5a;
}
body.dark.dg-state-results .dg-input-shell,
body.dark.dg-state-reader .dg-input-shell,
body.dark.dg-state-toc .dg-input-shell {
    background: #42426a;
    border-color: #42426a;
}
body.dark.dg-state-results .dg-input-shell .dg-shell-btn,
body.dark.dg-state-reader .dg-input-shell .dg-shell-btn,
body.dark.dg-state-toc .dg-input-shell .dg-shell-btn,
body.dark.dg-state-reader .dg-shell-toc {
    color: rgb(221, 221, 221);
}
body.dark.dg-state-results #form #paliauto.searchinput,
body.dark.dg-state-reader #form #paliauto.searchinput,
body.dark.dg-state-toc #form #paliauto.searchinput {
    color: rgb(221, 221, 221);
}
/* apple-design audit: .dg-input-shell:focus-within's ring uses --dg-accent-bg (#12241f in
   dark) — nearly invisible against both the dark page and this pill's own #42426a fill
   (confirmed live: box-shadow computed but not perceptible). Brighter ring for these
   dark-theme states specifically. */
body.dark.dg-state-results .dg-input-shell:focus-within,
body.dark.dg-state-reader .dg-input-shell:focus-within,
body.dark.dg-state-toc .dg-input-shell:focus-within {
    box-shadow: 0 0 0 3px rgba(122, 122, 249, 0.6);
}

/* Поле на главной крупнее, чем в выдаче/чтении — оно тут центр экрана, а не строка в ряду.
   Раньше это была светлая карточка с тенью, лежащая поверх тёмной полосы (тень нужна была,
   чтобы отделиться от градиента); теперь поле стоит на обычном фоне страницы вместе с
   заголовком, так что ему хватает того же бордера, что у .dg-input-shell везде — своей тени
   и прозрачной рамки больше нет (production-v4 redesign, docs/Home-standalone.html). */
body.dg-state-home .dg-input-shell {
    /* Reference .search-shell: 12px corners (not the 28px pill of results/reader), the
       stronger border tone, white fill, 10/8/10/15 padding, 10px between children. */
    padding: 10px 8px 10px 15px;
    gap: 10px;
    border-radius: 12px;
    border-color: var(--dg-border-strong);
    background: var(--dg-surface);
}
/* Magnifying glass inside the field, left edge (reference: 14px, muted) — home only; results/
   reader keep the shell logo there instead (.dg-shell-logo above). */
.dg-shell-search-ic { display: none; }
body.dg-state-home .dg-shell-search-ic {
    display: inline-flex;
    flex: none;
    color: var(--dg-text-muted);
    line-height: 0;
}
/* Quick-settings sliders leave the field on the home screen — the reference moves that action
   to the "изменить" link under the field (#home-scope-summary). The button stays in the DOM
   (hidden): "изменить" clicks it, and openQuick() (home.js) anchors the sheet to the link when
   the button itself has no box. Results/reader keep the sliders in the field as before. */
body.dg-state-home #dg-quick-btn { display: none; }

/* Порядок справа: сперва быстрые настройки, потом лупа. Лупа — последняя кнопка строки, у самого
   края: это действие «искать», и оно завершает ввод. Разделитель между «очистить» и парой кнопок
   на главной не нужен — там и так просторно. */
body.dg-state-home .dg-shell-sep { display: none; }

/* Ракушка внутри поля — только в выдаче и оглавлении: на главной знак и название уже стоят
   в шапке. Она же кнопка «домой». В чтении на этом месте стоит .dg-shell-toc (ниже) — owner:
   логотип там теперь ведёт в оглавление, не на главную (тот же паттерн, что у логотипа в
   документационных сайтах — GitBook/Readthedocs, клик внутри статьи уводит в оглавление книги,
   а не на маркетинговый home); с /toc «домой» по-прежнему одно касание через бургер. */
body .dg-shell-logo { display: none; flex: none; line-height: 0; text-decoration: none; }
body.dg-state-results .dg-shell-logo,
body.dg-state-toc .dg-shell-logo { display: inline-flex; }
.dg-shell-logo img { width: 26px; height: 26px; object-fit: contain; display: block; }
/* Оглавление — та же позиция в поле, что у ракушки, но только в чтении (см. комментарий выше) и
   с другой иконкой (fa-table-list, не логотип), чтобы не читалось как «ракушка перестала быть
   домой» — owner: "иконка должна быть другая... чтобы пользователь понимал, что это не дом".
   Стили — 1:1 с .dg-shell-logo (та же ячейка строки, тот же паддинг/цвет вокруг). */
body .dg-shell-toc { display: none; flex: none; line-height: 0; text-decoration: none; color: var(--dg-text-muted); }
body.dg-state-reader .dg-shell-toc { display: inline-flex; align-items: center; justify-content: center; }
.dg-shell-toc svg { width: 20px; height: 20px; display: block; }
/* Разделитель перед блоком кнопок справа — как в строке поиска у поисковиков. */
.dg-shell-sep {
    width: 1px;
    height: 22px;
    flex: none;
    margin: 0 2px;
    background: var(--dg-border);
}

/* Спиннер ожидания живёт ВНУТРИ кнопки-лупы и подменяет саму иконку. Отдельным элементом в
   строке он раздвигал соседей, и на каждый запрос кнопки успевали дёрнуться туда и обратно
   (шестерёнка-лупа → спиннер-шестерёнка → шестерёнка-лупа). Теперь меняется только картинка
   внутри кнопки, геометрия строки неподвижна. */
.dg-shell-spinner {
    display: none;
    width: 17px;
    height: 17px;
    /* Owner: still invisible on the home page — border was a hardcoded teal (--dg-accent)
       sitting on the search button's own dark navy fill (body.dg-state-home .dg-shell-go,
       color:#fff), near-zero contrast between two dark/teal tones. Real Bootstrap
       .spinner-border uses `currentColor`, not a fixed color, precisely so it always matches
       whatever text/icon color its button already has — white on the home button, muted
       grey on results/reader, near-white in dark theme (all already set via .dg-shell-btn's
       own `color`, see above) — no per-state override needed here at all. */
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: dg-spin 0.7s linear infinite;
}
body.dg-busy .dg-shell-spinner { display: block; }
body.dg-busy #searchbtn .dg-search-icon { display: none; }
/* Home: the button is a text pill — the spinner replaces the label (owner: label + spinner
   side by side made the button jump in width). Same footprint: the label's line box is kept
   by a min-width on the pill, the spinner just sits centered inside it. */
body.dg-state-home.dg-busy .dg-shell-go-label { display: none; }
body.dg-state-home .dg-shell-go { min-width: 74px; justify-content: center; }
body.dg-state-home .dg-shell-spinner { width: 16px; height: 16px; margin: 2px 0; }
@keyframes dg-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .dg-shell-spinner { animation-duration: 2s; }
}

/* Тот же спиннер, но НЕ внутри поля — на случай, когда сама шапка (и вместе с ней
   .dg-shell-spinner) уехала за экран автоскрытием (autoHideHeader). Показывается только когда
   ОБА условия разом: идёт запрос И шапка спрятана — когда шапка видна, свой спиннер в поле уже
   всё показывает, дублировать незачем. z-index выше стека шапки (850/849), чтобы не потеряться
   под подложкой (#dg-header-backdrop), но ниже дровера. */
#dg-busy-indicator {
    display: none;
    position: fixed;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 900;
}
body.dg-busy.dg-header-hidden #dg-busy-indicator { display: block; }
#dg-busy-indicator .spinner-border {
    width: 22px;
    height: 22px;
    border-width: 3px;
    border-color: var(--dg-accent);
    border-right-color: transparent;
    border-radius: 50%;
    border-style: solid;
    animation: dg-spin 0.7s linear infinite;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
@media (prefers-reduced-motion: reduce) {
    #dg-busy-indicator .spinner-border { animation-duration: 2s; }
}

/* Инпут внутри оболочки — без своей рамки, фона и «пилюли»: рамка теперь у оболочки.
   Специфичность (0,2,1) намеренная: reader/css/uiextra.css задаёт `#form.ui-widget #paliauto,
   #paliauto { padding-left:10px !important }` (ДВА id), и она подключается лениво, ПОСЛЕ этого
   файла — обычным правилом её не перебить (см. docs/SPA_HANDOVER.md §4). */
body #form #paliauto.searchinput,
body #form #paliauto.form-control {
    flex: 1 1 auto;
    min-width: 0;
    height: auto;
    padding: 6px 4px !important;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--dg-text);
    font-family: var(--dg-font);
    font-size: 1rem;
    outline: none;
}
body.dg-state-home #form #paliauto.searchinput { font-size: 17px; font-family: var(--dg-font); }
/* Legacy sheets (index.css & co.) pin p/span/h5/a to their own family; on the home screen
   everything is Lato (reference), so claim the whole home column and the drawers/sheets at
   once instead of chasing each tag. */
body.dg-state-home #home-pane,
body.dg-state-home #home-pane *,
body.dg-state-home #dg-hero-band *,
body.dg-skin-minimal .dg-sheet,
body.dg-skin-minimal .dg-sheet *,
body.dg-skin-minimal .dg-drawer,
body.dg-skin-minimal .dg-drawer * { font-family: var(--dg-font); }

/* ============================================================================
   Phone layout of the home screen (owner's phone mock, 2026-09-06): no big headline, the field
   straight under the bar with the sliders back INSIDE it (no "изменить" line), announcement
   right below, compact tiles, compass off the bar.
   ============================================================================ */
@media (max-width: 767.98px) {
    /* html prefix: the desktop show-rules for these two live further down at the same
       specificity and would win on source order otherwise. */
    html body.dg-state-home #dg-hero-heading { display: none; }
    body.dg-state-home .hero-row { margin-top: 16px; }
    body.dg-state-home #dg-quick-btn { display: inline-flex; }
    html body.dg-state-home #home-scope-summary { display: none; }
    body.dg-state-home #dg-topbar .dg-compass-btn-home { display: none; }
    /* body.dg-state-home prefix: the base tile/announce rules sit further down this file at the
       same specificity, so plain selectors here would lose on source order. */
    /* Values below: the reference's own body[data-view="mobile"] rule set. */
    body.dg-state-home #dg-announce { margin-top: 14px; }
    body.dg-state-home .dg-announce-box { width: 100%; max-width: none; padding: 6px 6px 6px 10px; gap: 7px; font-size: 12px; border-radius: 10px; line-height: 1.4; }
    body.dg-state-home .dg-announce-tag { font-size: 9.5px; padding: 2px 6px; }
    body.dg-state-home #dg-hero-band { padding-bottom: 4px; }
    body.dg-state-home #home-pane { margin-top: 18px; }
    body.dg-state-home .dg-tiles { gap: 8px; padding: 0 0 4px; }
    body.dg-state-home .dg-tile { padding: 12px 9px; gap: 6px; font-size: 13px; }
    body.dg-state-home .dg-tile-ic { width: 36px; height: 36px; }
    body.dg-state-home .dg-tile svg { width: 16px; height: 16px; }
    body.dg-state-home .dg-tile-desc { font-size: 11px; line-height: 1.35; }
    body.dg-state-home #home-slides { margin-top: 16px; }
    body.dg-state-home .dg-slides-box { padding: 15px 4px 12px; }
    body.dg-state-home #dg-carousel .carousel-item { padding: 0 30px; }
    body.dg-state-home #dg-carousel .carousel-control-prev,
    body.dg-state-home #dg-carousel .carousel-control-next { width: 28px; height: 28px; }
    body.dg-state-home #dg-carousel .carousel-control-prev { left: 4px; }
    body.dg-state-home #dg-carousel .carousel-control-next { right: 4px; }
    body.dg-state-home #dg-carousel .dg-slides-arw { width: 8px; height: 13px; }
    body.dg-state-home #dg-carousel h5 { font-size: 15px; }
    body.dg-state-home #dg-carousel span { font-size: 12.5px; }
    body.dg-state-home #dg-footer { margin: 24px auto 0; padding: 16px 0 30px; }
}
body #form #paliauto.searchinput::placeholder { color: var(--dg-text-muted); }
/* Родной крестик type="search" (только webkit) — вместо него своя кнопка #dg-clear-btn: родной
   не поддаётся оформлению и вставал бы вплотную к нашим кнопкам. */
body #form #paliauto.searchinput::-webkit-search-cancel-button { display: none; }

/* Лупа-сабмит. Раньше лежала ПОВЕРХ поля (position:absolute + z-index:12 из-за
   .searchinput{z-index:9}) — теперь это обычный элемент flex-строки, накладок больше нет. */
.dg-input-shell .dg-shell-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: none;
    padding: 0;
    border: 0;
    /* Круглые, а не скруглённые квадраты. Заливки у них нет, пока на кнопку не навели, — но при
       наведении подсветка вылезала прямоугольником посреди круглого поля с круглыми соседями. */
    border-radius: 50%;
    background: transparent;
    color: var(--dg-text-muted);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.dg-input-shell .dg-shell-btn:hover,
.dg-input-shell .dg-shell-btn:focus-visible { background: var(--dg-surface-hover); color: var(--dg-text); }

/* Слайдеры (fa-sliders) — быстрые настройки. Раньше была шестерёнка с молнией-прорезью, но с
   гером (полные настройки) и словарной шестерёнкой в компасе получалось три шестерёнки подряд —
   путали, какая для чего (просьба владельца). Иконку сменили в home.js (quickButtonHtml), сам
   диск-молния (.dg-qs-bolt) был частью именно гексагонной композиции гера и с ней вместе убран.
   Кнопка круглая, а не скруглённый квадрат: в поле ввода круглое уже всё остальное — и само
   поле, и «очистить», и лупа, — и один квадрат посреди них выбивался. */
.dg-qs-btn {
    /* Прозрачно, пока не навели — как остальные кнопки поля (.dg-shell-btn), не отдельный кружок
       на виду всегда: слайдеры второстепенное действие, не должны тянуть взгляд. */
    --dg-qs-bg: transparent;
    --dg-qs-fg: var(--dg-text-2);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--dg-qs-bg);
    color: var(--dg-qs-fg);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.dg-qs-btn:hover,
.dg-qs-btn:focus-visible { --dg-qs-bg: var(--dg-border); --dg-qs-fg: var(--dg-text); }
/* Повёрнута на 90° и увеличена — владелец: горизонтальные слайдеры (fa-sliders) на маленьком
   размере читались почти как бургер (тоже три горизонтальные линии), путали. Вертикальные
   слайдеры — стандартная альтернативная ориентация той же иконки, однозначно другой силуэт.
   Центровка — сама .dg-qs-btn уже flex/center (см. выше), rotate() крутит вокруг центра иконки
   по умолчанию, так что положение не съезжает. */
/* 26px оказался БОЛЬШЕ бургера — перебор. Владелец задал точный ориентир: не крупнее лупы
   (#searchbtn .dg-search-icon, index.html — 17×17, тот же ряд той же формы поля). 17px, без
   попытки сравнять зрительный вес на глаз ещё раз — на этот раз просто взял чужой размер
   буквально. */
.dg-qs-btn .dg-qs-gear { width: 17px; height: 17px; display: block; transform: rotate(90deg); }

/* Тёмный кружок — на лупе (главное, кликабельное действие поля), не на шестерёнке (второстепенная
   настройка). Раньше было наоборот, и тёмное пятно тянуло взгляд/палец не туда — шестерёнку
   хотелось нажать, а не лупу (жалоба владельца). Шестерёнка теперь просто шестерёнка — тот же
   приглушённый стиль, что у остальных кнопок поля (.dg-shell-btn: прозрачно, подсветка только
   по наведению).
   transition:none по той же причине, что и у полосы: цвет здесь меняет СОСТОЯНИЕ страницы, а не
   наведение, и не должен зависеть от того, рисует ли вкладка кадры. */
/* Text label — added to the button markup (index.html) for every state, but only shown on the
   home screen: results/reader keep the compact icon-only button, there's no room for a label in
   that toolbar-sized field. */
.dg-shell-go-label { display: none; }
body.dg-state-home .dg-shell-go,
body:not(.dg-state-home) .dg-shell-go { transition: none; }
/* Reference button.go: text only, 13.5px/500, 8px/16px padding, 8px corners, accent fill
   (--dg-accent-dark: #0f7c63 light / #025242 dark — both measured off the reference). The
   magnifying glass stays in the markup for results/reader (icon-only button there) and for the
   busy spinner that swaps in for it; on home the label is the whole button. */
body.dg-state-home .dg-shell-go {
    background: var(--dg-accent-dark);
    color: #fff;
    width: auto;
    height: auto;
    padding: 8px 16px;
    border-radius: 8px;
    gap: 0;
}
body.dg-state-home .dg-shell-go:hover,
body.dg-state-home .dg-shell-go:focus-visible { background: var(--dg-accent); color: #fff; }
body.dg-state-home .dg-shell-go .dg-search-icon { display: none; }
body.dg-state-home .dg-shell-go-label {
    display: inline;
    font-family: var(--dg-font);
    font-size: 13.5px;
    font-weight: 500;
    line-height: 1.45;
    white-space: nowrap;
}
/* Owner: on mobile the "Искать" pill crowds the field (screenshot: label clipping the query
   text) — icon-only there, same as results/reader already are, instead of the text button.
   The glass keeps the site's mirrored orientation (lens right, handle down-left — the scaleX(-1)
   inline style on the <svg> in index.html), same as in results/reader (owner: turn it right). */
@media (max-width: 767.98px) {
    body.dg-state-home .dg-shell-go {
        width: 34px;
        height: 34px;
        min-width: 0;
        padding: 0;
        border-radius: 50%;
    }
    body.dg-state-home .dg-shell-go-label { display: none; }
    body.dg-state-home .dg-shell-go .dg-search-icon { display: block; }
    /* Owner: with the submit button now showing its own glass (right, above), the decorative
       one at the field's left edge (.dg-shell-search-ic, home-only) is a second, redundant
       glass on the same narrow row — hide it on mobile specifically, desktop home keeps it
       (there the submit button is still the text pill, no icon of its own to duplicate it). */
    body.dg-state-home .dg-shell-search-ic { display: none; }
}

/* Ожидание ответа поиска: пока крутится спиннер, выдачи (даже пустой) быть не должно — ради
   этого весь класс и заведён. Домашние блоки при этом НЕ прячем: смысл в том, чтобы человек
   остался на главной, а не смотрел в пустоту. */
body.dg-busy #results-toolbar,
body.dg-busy #results-divider,
body.dg-busy #search-pane,
body.dg-busy:not(.dg-state-reader) #reader-pane {
    display: none;
}
/* Reader while loading (cold load: dg-busy; in-app: .reader-pending): only #sutta is hidden, and
   the header keeps its place.

   The first version drew ONE 300px bar per row, and it fitted worse the narrower the screen got
   (owner, 2026-09-20). The width was never the real fault. Looking at the loaded header at 1900,
   820 and 390 shows what is actually there: at the two larger sizes the toolbar is a single centred
   row — six text links, six icons, the title pill — and at 390 it wraps into two rows, with the
   prev/next row under it either way.

   Most of that is NOT waiting for anything. The icons are the same for every sutta and are ready
   before the text is; a grey bar over them replaces finished content with a promise. Three things
   do wait, and each now gets a placeholder of its OWN shape in its OWN place:

     #smart-toc-btn (the title pill) → its own box, shimmering
     #navigation    (prev/next)      → two bars at the two ends

   And one that deliberately gets NOTHING: the per-sutta edition links (Voice/4nt/DPR/BJT/SC/TBW).
   megareader.js builds them at render time (generateThirdPartyLinks), so on a cold load there are
   no elements to shimmer — a placeholder for them would have to be invented out of guessed widths,
   which is exactly the fixed-pixel mistake this replaces. They stay hidden, as before; the rule
   that hides them matters for in-app navigation, where the PREVIOUS sutta's links are still in the
   DOM.

   Nothing here is a fixed pixel width that has to be retuned per screen: each placeholder inherits
   the box of the element it stands for, so wrapping at 390 and the single row at 1900 come out
   right for free, and there is not one media query in it. */
body.dg-state-reader.dg-busy #sutta, #reader-pane.reader-pending #sutta { visibility: hidden; }

/* Shared look. Applied to backgrounds rather than to a bar element, so a placeholder can BE the
   element it replaces instead of standing next to it — that is what went wrong before: the old
   ::before joined the toolbar's centred flex row as one more item and shoved the icons aside. */
body.dg-state-reader.dg-busy #smart-toc-btn, #reader-pane.reader-pending #smart-toc-btn,
body.dg-state-reader.dg-busy #navigation::before, #reader-pane.reader-pending #navigation::before,
body.dg-state-reader.dg-busy #navigation::after, #reader-pane.reader-pending #navigation::after {
    border-radius: 999px;
    background: linear-gradient(90deg, var(--dg-surface-hover) 25%, var(--dg-border) 50%, var(--dg-surface-hover) 75%);
    background-size: 200% 100%; animation: dg-tiles-skeleton 1.4s ease-in-out infinite;
}
/* The per-sutta edition links, wherever they currently are.

   Scoping this to #reader-toolbar was not enough (owner, 2026-09-20, landscape phone): until
   megareader.js has rendered, the links sit in their MOBILE home (#top-links-container, a row of
   their own) and only then does buildSutta move them up into the icon row — on desktop widths,
   decided by window.innerWidth at render time. So a wide screen showed the mobile two-row header
   for as long as the load took, and then the header rearranged itself under the reader's eyes.

   Hiding them by class rather than by container means they are simply not seen in the wrong place:
   they appear once, already where they belong. The header keeps its height either way — the icons
   hold the toolbar row and #navigation has its min-height. */
body.dg-state-reader.dg-busy .sc-ext-link, #reader-pane.reader-pending .sc-ext-link { display: none; }
body.dg-state-reader.dg-busy #top-links-container, #reader-pane.reader-pending #top-links-container { display: none; }
/* The title pill: its own box already knows how wide it may be at each size (160px, 280px, 96px on
   phones), so the placeholder inherits all of that. min-width is in em, so it follows the same
   responsive font-size the pill itself uses. */
body.dg-state-reader.dg-busy #smart-toc-btn, #reader-pane.reader-pending #smart-toc-btn {
    color: transparent; border-color: transparent; pointer-events: none; min-width: 7em;
}
body.dg-state-reader.dg-busy #smart-toc-btn *, #reader-pane.reader-pending #smart-toc-btn * {
    visibility: hidden;
}
/* prev/next: two bars at the two ends, exactly where the two links sit. The row is laid out here
   only while loading — the real links are display:none below, so this governs nothing but the
   placeholders and leaves the loaded layout (legacy reader CSS) alone. */
body.dg-state-reader.dg-busy #navigation, #reader-pane.reader-pending #navigation {
    display: flex; align-items: center; justify-content: space-between;
}
body.dg-state-reader.dg-busy #navigation::before, #reader-pane.reader-pending #navigation::before,
body.dg-state-reader.dg-busy #navigation::after, #reader-pane.reader-pending #navigation::after {
    content: ''; display: block; flex: none; height: 13px; width: min(150px, 38%);
}
body.dg-state-reader #navigation { min-height: 34px; }
body.dg-state-reader.dg-busy #navigation a, #reader-pane.reader-pending #navigation a { display: none; }
body.dg-busy #variants-hint { display: none !important; }

#dg-loading {
    display: flex;
    justify-content: center;
    padding: 2.5rem 0;
}
#dg-loading[hidden] { display: none; }
/* .spinner-border есть и в Bootstrap (подключён здесь), и в reader/css/rus-multi.css — размеры
   и цвет задаём сами, чтобы вид не зависел от того, догружен ли уже ридер. */
#dg-loading .spinner-border {
    width: 1.75rem;
    height: 1.75rem;
    border-width: 0.2em;
    color: var(--dg-text-muted);
}

/* Всё, что относится к выдаче, на главной не нужно: пустая таблица с шапкой колонок, ряд кнопок
   выдачи, подсказка о вариантах, плавающие кнопки языка и "наверх". Модалки (#settings,
   #SearchResultHelp) НЕ трогаем — у них свой display, которым управляет Bootstrap. */
body.dg-state-home #results-toolbar,
body.dg-state-home #results-divider,
body.dg-state-home #search-pane,
body.dg-state-home #reader-pane,
body.dg-state-home #language-button,
body.dg-state-home #scrollToTopBtn,
/* #dynamicHeader lives outside #results-toolbar on purpose (see its own comment in index.html —
   shouldn't hide/show on scroll like the rest of the toolbar) and is already hidden for
   dg-state-toc/dg-state-reader, but was missing here: going home after a search left the old
   "N texts and M matches..." title floating below the page (owner screenshot). */
body.dg-state-home #dynamicHeader {
    display: none;
}
/* ============================================================================
   Совместимость с таблицами стилей ридера
   Они подключаются в рантайме (при первом открытии текста), то есть ПОСЛЕ всех остальных, и
   выигрывают по порядку. Здесь — точечные ответы на конкретные конфликты.
   ============================================================================ */

/* Ответ на `#form.ui-widget #paliauto, #paliauto { padding-left:10px !important }` из
   reader/css/uiextra.css — выше, вместе с остальными правилами инпута (.dg-input-shell). */

/* И index.css, и rus-multi.css задают глобальное `body { margin:1rem 3rem; background-color;
   font-family:"Robto Serif" }`. Пока ридер был отдельной страницей, это никого не задевало;
   теперь, один раз открыв текст, выдача до конца сессии съезжала на 3rem и меняла шрифт.
   Возвращаем ей своё оформление везде, КРОМЕ состояния ридера — там правила ридера как раз
   нужны. Специфичность (0,1,1) против (0,0,1) у голого `body`, поэтому побеждаем и без
   !important. */
body:not(.dg-state-reader):not(.dg-state-toc) {
    margin: 0;
    font-family: var(--bs-body-font-family);
    background-color: var(--dg-page);
}

/* Панель ридера видна только в своём состоянии. В разметке у неё раньше стоял bootstrap-овский
   d-none (display:none !important) — его перебить состоянием было нельзя, поэтому класс снят, а
   видимость целиком здесь. */
#reader-pane { display: none; }
/* Reader screen transition (owner spec). Enter: 380ms, scale(.94)->1, translateY(10px)->0,
   fade in, origin 50%/40% of the viewport (40vh, not 40% of the pane — the pane is as tall as
   the whole sutta). Plays automatically on display:none -> block (dgSetState('reader')) and is
   restarted by hand in megareader.js between neighbouring suttas. Exit: 240ms, scale 1->.9,
   translateY 0->-6px, fade — class .reader-out added by routeFromUrl() (search/index.html) /
   navigateSutta() (megareader.js); the screen switches only after it finishes. */
@keyframes dg-reader-in {
    from { opacity: 0; transform: scale(.94) translateY(10px); }
    to { opacity: 1; transform: none; }
}
@keyframes dg-reader-out {
    to { opacity: 0; transform: scale(.9) translateY(-6px); }
}
/* No fill-mode on the enter: a filled transform (even the identity one) makes #reader-pane the
   containing block of its position:fixed header stack (#reader-toolbar etc.), shifting it. */
body.dg-state-reader #reader-pane { display: block; }
/* The animation runs on #sutta (the text), not the pane: the fixed toolbar/nav rows inside the
   pane stay put (owner: "шапка монолитна"). .reader-pending (text still loading, see the
   skeleton rules above) keeps the stale text hidden so the enter plays once, on the NEW text;
   .reader-in is added by buildSutta() (megareader.js) when the text is in the DOM. */
body.dg-state-reader #sutta { transform-origin: 50% 40vh; }
body.dg-state-reader #reader-pane.reader-in #sutta { animation: dg-reader-in 380ms var(--dg-ease); }
body.dg-state-reader #reader-pane.reader-out #sutta { animation: dg-reader-out 240ms var(--dg-ease) both; }
@media (prefers-reduced-motion: reduce) {
    body.dg-state-reader #reader-pane.reader-in #sutta, body.dg-state-reader #reader-pane.reader-out #sutta { animation: none; }
}

/* Панель TOC/навигатора — тот же приём, что #reader-pane выше. Первая, минимальная версия
   разметки: подробная стилизация (тема шапки/тулбара и т.п.) при желании донастраивается позже,
   как и весь остальной визуал ридера когда-то дорабатывался постепенно. */
#toc-pane { display: none; }
body.dg-state-toc #toc-pane { display: block; }
body.dg-state-toc #search-pane,
body.dg-state-toc #results-toolbar,
body.dg-state-toc #results-divider,
body.dg-state-toc #dynamicHeader,
body.dg-state-toc #language-button {
    display: none;
}

/* Layout: tree on the left (this is a Dhamma site, not a translation-comparison site — owner),
   translator filter as a right-hand aside when there's room; on narrow screens the aside moves
   ABOVE the tree instead (order:-1) and stays compact via the per-language <details> "ещё". */
/* Palette: not new — reuses the site's own production-v4 tokens (--dg-surface/--dg-border/
   --dg-text/--dg-accent etc.), already defined on body.dg-skin-minimal above and already
   theme-aware (body.dark redefines them) since they drive the home screen and reader toolbar.
   The old version of this block used bare Bootstrap vars (--bs-border-color etc.), which this
   site's dark theme never touches — that's why it looked like an unstyled draft in dark mode. */
#toc-pane { max-width: 1100px; margin: 0 auto; color: var(--dg-text); }
/* Safety net: every link in this pane is the same accent green, full stop (owner: "цвета ссылок
   должны быть тогда уже все зелёные, а не только зелёные какие-то фиолетовые" — repeated after
   the :visited-only fix, because the REAL cause wasn't :visited at all). Once the reader has been
   opened anywhere in this SPA session, reader/css/index.css + rus-multi.css stay loaded and carry
   a bare ".dark a{color:rgb(122,122,249)}" — class+type beats this file's plain ".toc-mark"/
   ".toc-leaf-link" classes (both are single-class selectors), so links quietly turned lilac the
   moment reader CSS entered the page, :visited or not. #toc-pane is an ID selector — it outranks
   any class-based rule regardless of load order, so this one line pins every link in the pane. */
#toc-pane a,
#toc-pane a:visited { color: var(--dg-accent-ink, var(--dg-accent)); }
.toc-layout { display: flex; gap: 2rem; align-items: flex-start; }
.toc-main { flex: 1 1 auto; min-width: 0; }
/* Pinned just under the header stack, not at a fixed 1rem: the stack is position:fixed, so a
   hardcoded top slid this column underneath the band (the filter's own title was the first thing
   to disappear — same "закрывает" complaint). --dg-stack-height is written by applyPadding()
   (search/index.html); the fallback covers the instant before it first runs. */
.toc-aside {
    flex: 0 0 260px;
    position: sticky; top: calc(var(--dg-stack-height, 65px) + 12px);
    border: 1px solid var(--dg-border); border-radius: var(--dg-radius, 10px);
    padding: .75rem .9rem;
    background: var(--dg-surface);
}
/* Scroll targets of /spa/toc.js's scrollTo() (revealTarget): scrollIntoView({block:'start'}) puts
   the element's top edge at the viewport top, i.e. exactly under the fixed band. scroll-margin-top
   shifts that edge below the stack instead, so arriving at /toc/dn lands on "Dīgha Nikāya (34)"
   rather than behind the search field. */
#toc-pane [id^="toc-category-"],
#toc-pane .toc-book, #toc-pane [data-toc-node], #toc-pane .toc-group {
    scroll-margin-top: calc(var(--dg-stack-height, 65px) + 8px);
}
/* TOC screen transition (owner spec). Enter: 340ms, list (left) from -22px, translator filter
   (right) from +22px with a 60ms delay, both fade in; plays on display:none -> block and on the
   rebuilt nodes of renderTopLevel(). Exit: 240ms, columns fly outward (-26px / +26px) and fade —
   class .toc-out on #toc-pane, added by routeFromUrl() (search/index.html); the screen switches
   only after it finishes. */
@keyframes dg-toc-in-left { from { opacity: 0; transform: translateX(-22px); } to { opacity: 1; transform: none; } }
@keyframes dg-toc-in-right { from { opacity: 0; transform: translateX(22px); } to { opacity: 1; transform: none; } }
@keyframes dg-toc-out-left { to { opacity: 0; transform: translateX(-26px); } }
@keyframes dg-toc-out-right { to { opacity: 0; transform: translateX(26px); } }
body.dg-state-toc .toc-main { animation: dg-toc-in-left 340ms var(--dg-ease); }
body.dg-state-toc .toc-aside { animation: dg-toc-in-right 340ms var(--dg-ease) 60ms backwards; }
body.dg-state-toc #toc-pane.toc-out .toc-main { animation: dg-toc-out-left 240ms var(--dg-ease) both; }
body.dg-state-toc #toc-pane.toc-out .toc-aside { animation: dg-toc-out-right 240ms var(--dg-ease) both; }
@media (prefers-reduced-motion: reduce) {
    body.dg-state-toc .toc-main, body.dg-state-toc .toc-aside,
    body.dg-state-toc #toc-pane.toc-out .toc-main, body.dg-state-toc #toc-pane.toc-out .toc-aside { animation: none; }
}
.toc-aside-title { font-size: .95rem; margin: 0 0 .5rem; color: var(--dg-text-2); }
/* Same button-reset + "+/-" affordance as the category expand-all toggle — collapsible on
   phones so arriving at /toc lands on the Pali contents, not this panel (owner: "на мобильном
   когда пришёл в оглавление, он пришёл в оглавление пали, а не в список переводчиков"). */
.toc-aside-toggle {
    display: flex; align-items: center; gap: .4rem;
    width: 100%; background: none; border: none; padding: 0; cursor: pointer;
    text-align: left; font: inherit;
}
.toc-aside-toggle .toc-toggle { flex: none; }
.toc-filter-reset { font-size: .8rem; margin-bottom: .6rem; }
.toc-filter-reset a,
.toc-filter-reset a:visited { color: var(--dg-accent-ink, var(--dg-accent)); }
/* Stack to one column only on phones — tablets have plenty of room for the two-column layout
   too (owner: "на планшетах же много места... в одну колонку только на мобильных"). 640px keeps
   portrait tablets (iPad-class, ≥768px) two-column; only narrower phone widths collapse. */
@media (max-width: 640px) {
    .toc-layout { flex-direction: column; }
    .toc-aside { order: -1; flex-basis: auto; width: 100%; position: static; }
}

.toc-category { margin-bottom: 1.75rem; }
.toc-category-header { display: flex; align-items: center; gap: .75rem; margin-bottom: .35rem; }
.toc-category-header h3 { margin: 0; font-size: 1.15rem; color: var(--dg-text); }
/* Chunky square toggle — prod's own look for its one top-level collapse-all control
   (read.php #collapseAll: filled accent square, bold "+"). */
.toc-expand-all-btn {
    width: 1.9rem; height: 1.9rem; flex: none;
    border: none; border-radius: 6px; background: var(--dg-accent); color: #fff;
    font-size: 1.2rem; font-weight: 700; line-height: 1; cursor: pointer;
}
.toc-expand-all-btn:hover { background: var(--dg-accent-dark, var(--dg-accent-ink, var(--dg-accent))); }
.toc-books { display: flex; flex-direction: column; }
.toc-book { border-top: 1px solid var(--dg-border); padding: .5rem 0; }
.toc-book:first-child { border-top: none; }
.toc-book-header,
.toc-book-header:visited {
    display: block; width: 100%; text-align: left;
    background: none; border: none; padding: .3rem .1rem; cursor: pointer;
    color: var(--dg-accent-ink, var(--dg-accent)); font-size: 1.3rem; font-weight: 700;
    text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
}
.toc-book-header:hover { text-decoration-color: currentColor; }
/* The "(N)" count (and, for Khuddaka, the "*" partial-collection mark) is its own muted span, not
   part of the bold name — it's metadata about the row, not the title itself (owner: "отдели
   счётчик от названия чтобы он был серым... это к имени не относится"). */
.toc-count {
    color: var(--dg-text-muted); font-weight: 400; font-size: 1rem;
    text-decoration: none;
}
.toc-count-star { cursor: help; }
.toc-book-body { padding: .25rem 0 .5rem .7rem; }
.toc-empty { padding: .35rem 0; color: var(--dg-text-muted); font-size: .9rem; }

/* Explicit hierarchy: "Переводчики" (aside title, h4) → language name (level 2 — bigger, bold,
   its own underline) → each translator (level 3 — small checkbox row). Owner: "у тебя всё
   одинакового размера... это же для того, чтобы было удобно понимать, это первый уровень, это
   там опция, это второй уровень" — same size everywhere read as one flat blob. */
.toc-filter-search {
    width: 100%; box-sizing: border-box; margin-bottom: .85rem;
    padding: .4rem .55rem; font-size: .85rem;
    background: var(--dg-page); color: var(--dg-text);
    border: 1px solid var(--dg-border-strong); border-radius: 6px;
}
.toc-filter-group { margin-bottom: 1.1rem; padding-top: .6rem; border-top: 1px solid var(--dg-border); }
.toc-filter-group:first-child { padding-top: 0; border-top: none; }
.toc-filter-patimokkha { margin-top: .4rem; padding-top: .6rem; border-top: 1px solid var(--dg-border); }
/* Named ...-hdr/-title, deliberately NOT ...-lang-row/...-lang: reader/css/uiextra.css has its own
   "[class*='-lang']{display:block}" (targets .pli-lang/.eng-lang/etc.) — any class of ours that
   happens to contain that substring gets silently forced to display:block too (same specificity,
   uiextra.css loads later so it wins), which is exactly what broke the checkbox+language-name row
   here (owner: screenshot showed the checkbox stacked above "English" — that CSS rule, not the
   active-word JS bug from before, which was a separate collision on the same "-lang" substring). */
.toc-filter-hdr { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.toc-filter-title { font-weight: 700; font-size: 1rem; color: var(--dg-text); }
.toc-filter-item { display: flex; align-items: baseline; gap: .5rem; font-size: .85rem; padding: .2rem 0; color: var(--dg-text-2); }
/* Real, visible checkboxes — not text-sized-to-invisibility (owner: "это же не просто какие-то
   ссылки, это должны быть чекбоксы... непонятно как это работает"). They were rendering
   display:none: extrastyles.css has a global "label input[type=checkbox]{display:none}" (its own
   custom-checkbox hack elsewhere on the site) that swallows every checkbox nested in a <label> —
   same issue already solved once for .dg-scope/.dg-check below; same fix here, a selector with
   enough classes to outrank it. accent-color tints the checked state green in both themes. */
.toc-filter-item input.toc-filter-checkbox {
    display: inline-block;
    width: 16px; height: 16px; flex: none; margin: 0; cursor: pointer;
    accent-color: var(--dg-accent);
    border: 1px solid var(--dg-border-strong); border-radius: 3px;
}
/* The language master checkbox lives in a plain div, not a <label> — extrastyles.css's
   display:none hack only targets checkboxes inside a <label>, so this one just needs sizing. */
.toc-filter-master {
    width: 16px; height: 16px; flex: none; margin: 0; cursor: pointer;
    accent-color: var(--dg-accent);
    border: 1px solid var(--dg-border-strong); border-radius: 3px;
}
.toc-filter-more { margin-top: .3rem; }
.toc-filter-more summary { font-size: .8rem; cursor: pointer; color: var(--dg-accent-ink, var(--dg-accent)); list-style: none; }
.toc-filter-more summary::-webkit-details-marker { display: none; }

/* Small per-level step, not 1.4rem — SN nests up to 5 deep (group>samyutta>paññāsaka>vagga>leaf
   list), and since this stacks cumulatively at every level, 1.4rem there pushed the leaf/
   translator list ~7rem off the left edge, squeezing it into the middle of the page (owner:
   "слишком большие отступы... список сутт оказывается в центре экрана"). */
.toc-tree, .toc-children { list-style: none; margin: 0; padding-left: .35rem; }
/* Second nesting level and deeper step in at HALF the first level's indent, not another full
   step each time — cumulative width still adds up on a narrow phone once you're 4-5 levels deep
   (owner: repeated "отступы всё ещё гигантские" even after the first halving — halved again). */
.toc-children .toc-children,
.toc-children .toc-children .toc-children,
.toc-children .toc-children .toc-children .toc-children { padding-left: .18rem; }
/* Only the OUTERMOST list (straight under .toc-book-body, never anyone's "children" container)
   starts flush — every nested level below it (buildTreeChildren always stamps .toc-tree on the
   node it returns, then renderBranch ALSO adds .toc-children onto that SAME element for anything
   nested) needs to keep its indent. A bare ".toc-tree{padding-left:0}" matched every level alike
   and cancelled the indent everywhere, not just at the root (owner: "они должны отличаться
   отступами тоже" — depth should read in the indent, not only font size/weight). */
.toc-book-body > .toc-tree { padding-left: 0; }
/* Vagga/chapter heading — prod shows this as a plain bold static subheading, not another
   collapsible row; kept collapsible here (large books like SN/AN genuinely need it lazy), but
   styled like a heading, not a list item, to match. */
.toc-branch-header { display: flex; align-items: baseline; gap: .4rem; cursor: pointer; padding: .5rem 0 .3rem; }
.toc-branch-title { color: var(--dg-text-2); font-weight: 700; font-size: 1.05rem; }
/* Depth reads two ways at once: size/weight taper (unchanged) plus a black/green color
   alternation, one step smaller AND a swapped color per level, so hierarchy is visible at a
   glance instead of every branch looking the same (owner: "уровни у тебя не отличаются", then
   "саньютты зелёный поменять... вагги чёрным оставить" — vagga black, samyutta green, and the
   same alternation continues for any book with more levels, not just SN). */
.toc-children .toc-branch-title { color: var(--dg-accent-ink, var(--dg-accent)); font-weight: 600; font-size: .95rem; }
.toc-children .toc-children .toc-branch-title { color: var(--dg-text-2); font-weight: 500; font-size: .88rem; }
.toc-children .toc-children .toc-children .toc-branch-title { color: var(--dg-accent-ink, var(--dg-accent)); font-weight: 400; font-size: .84rem; }
.toc-toggle {
    background: none; border: none; cursor: pointer; padding: 0;
    width: 1.3em; height: 1.3em; line-height: 1.3em; text-align: center;
    font-weight: 700; color: var(--dg-text-muted); flex: none;
}
/* padding-left was a flat 1.75rem (28px) on EVERY leaf row regardless of depth — on top of the
   UL nesting indent above, that alone was nearly half the total indent a leaf sat at, and it
   didn't scale down the way the rest of the tree just got tuned to (owner: "отступы всё ещё
   гигантские"). The UL nesting already carries the depth signal; the leaf only needs a small
   step of its own. */
.toc-leaf { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; padding: .6rem 0 .6rem .5rem; border-bottom: 1px solid var(--dg-border); }
.toc-leaf:last-child { border-bottom: none; }
.toc-leaf-link,
.toc-leaf-link:visited { text-decoration: underline; color: var(--dg-accent-ink, var(--dg-accent)); font-weight: 600; }
/* One language's tag + its own translator marks wrap together as a single unit — without this,
   wrapping split the tag from its marks, landing "EN" wherever the wrap fell, disconnected from
   its own translator list (owner: "переводы... переносится на разные строчки"). */
.toc-src-group { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: .45rem; }
.toc-src-tag { font-size: .68rem; text-transform: uppercase; color: var(--dg-text-muted); }
/* Phones: a wrapping flex row of id + title + N language groups reads as a jumble at this width —
   stack it instead, one clear line per thing (owner: "посмотри как ужасно выглядят переводы...
   на мобильном"). Tablet/desktop keep the denser inline row, there's room for it. */
@media (max-width: 640px) {
    .toc-leaf { flex-direction: column; align-items: flex-start; gap: .3rem; }
}
/* Translator marks — plain small text, like prod's muted "TB"/"BS" initials, not chip/badge
   boxes: a box reads as tooling chrome, plain text reads as part of the same page. All the same
   accent green as every other link here (owner: "почему одни зеленые одни сиреневые, делай все
   зелёными") — the lilac was the browser's default :visited color leaking through; explicit
   :visited rules on every link class in this pane pin the color regardless of visited state. */
.toc-mark,
.toc-mark:visited {
    font-size: .78rem; color: var(--dg-accent-ink, var(--dg-accent)); text-decoration: none;
}
.toc-mark:hover { text-decoration: underline; }
.toc-mark-primary,
.toc-mark-primary:visited { color: var(--dg-accent-ink, var(--dg-accent)); font-weight: 600; }
.toc-more { display: inline-block; }
.toc-more summary { font-size: .78rem; cursor: pointer; color: var(--dg-text-muted); list-style: none; }
.toc-more summary::-webkit-details-marker { display: none; }
.toc-more .toc-mark { margin-right: .5rem; }
.toc-loading, .toc-error { padding: .5rem 0; color: var(--dg-text-muted); }
.toc-book-link { text-decoration: underline; }

/* Bhikkhu/Bhikkhuni Pātimokkha fragment (reader/{bu,bi}-pm-fragment.html, injected by toc.js's
   renderBookRow) carries legacy styles.css-scale headings/text — that stylesheet isn't loaded
   here (this page uses its own toc-* typography), so left unscoped the fragment renders with
   browser-default h3 sizing (much bigger than everything else in the panel) and, depending on
   ancestor flex context, can end up centered instead of left-aligned like the rest of the toc.
   Scale it down to the same rhythm as a tree branch (.toc-branch-title) and force left/block. */
.toc-patimokkha-body .level1,
.toc-patimokkha-body .level2,
.toc-patimokkha-body .level3,
.toc-patimokkha-body .level4,
.toc-patimokkha-body .level5 { text-align: left; }
/* h3 = section (Pārājikuddeso...), h4 = nested vagga sub-group inside Nissaggiya/Pācittiya/
   Sekhiya (Pādukavaggo...) — one step deeper than a section, so one step smaller, same as
   .toc-children .toc-branch-title vs .toc-branch-title for a normal tree branch. */
.toc-patimokkha-body h3,
.toc-patimokkha-body h4 {
    margin: 0; font-weight: 700; color: var(--dg-text); text-align: left;
}
.toc-patimokkha-body h3 { font-size: 1.05rem; }
.toc-patimokkha-body h4 { font-size: .95rem; }
/* Each section/vagga toggle row (.level2/.level3.d-flex) has no vertical margin of its own in
   extrastyles.css — one after another they sit flush, the "+" squares touching like a caterpillar
   (owner: "они как гусеница слиплись"). Gap between the button and its own heading stays as-is
   (align-items-center row), only space BETWEEN rows is added. */
.toc-patimokkha-body .level2.d-flex,
.toc-patimokkha-body .level3.d-flex { margin-bottom: .5rem; }
.toc-patimokkha-body .pli-lang { font-size: .92rem; line-height: 1.5; }
.toc-patimokkha-body a.setReader { font-size: .85rem; font-weight: 600; }
/* extrastyles.css (legacy) overrides .btn-primary's background-color directly (green, matching
   this site's palette) but never touches Bootstrap's own :hover/:focus/:active states — those
   still come from Bootstrap's --bs-btn-hover-bg variable, precomputed from ITS default blue
   --bs-primary, not from the overridden background-color. Result: the "+"/"−" toggle squares
   here read green at rest and flash bootstrap-blue on hover (owner: "делай тёмно зелёными как в
   стилях"). Fixed with an explicit hover/focus/active shade of the same green instead of editing
   the shared legacy file (see CLAUDE.md symlink policy) — darker in light mode (standard hover
   treatment), lighter in dark mode (dark surfaces read hover as "lighter", not "darker"). */
.toc-patimokkha-body .btn-primary:hover,
.toc-patimokkha-body .btn-primary:focus,
.toc-patimokkha-body .btn-primary:active {
    background-color: #128a72 !important;
    border-color: #159c81 !important;
}
[data-theme="dark"] .toc-patimokkha-body .btn-primary:hover,
[data-theme="dark"] .toc-patimokkha-body .btn-primary:focus,
[data-theme="dark"] .toc-patimokkha-body .btn-primary:active {
    background-color: #036b57 !important;
    border-color: #6b7d79 !important;
}

/* В ридере выдача остаётся в DOM (возврат по "назад" мгновенный), но не показывается. Раньше
   здесь прятались только ОТДЕЛЬНЫЕ кнопки внутри #results-toolbar (разворачивание строк,
   отметки "прочитано", переключатель "Тексты/Слова", заголовок результатов), а сам
   #results-toolbar оставался в потоке — по мысли того времени, часть его кнопок (тема, словарь,
   компас, настройки, помощь) должна была использоваться и при чтении. С тех пор в ридере
   появился свой ПОЛНЫЙ #reader-toolbar с тем же набором функций — оставшийся #results-toolbar не
   удалялся из потока (display не задан ни в одном правиле), стоял пустой полосой ~41px высотой
   ПЕРЕД самим reader-pane и просто отодвигал текст сутты вниз без всякой видимой причины
   (владелец, скриншот: "огромный чёрный отступ"). Заодно теперь и #toggle-mode-results (кнопка
   режима колонок ИМЕННО для выдачи, соседствует в этом же ряду) не дублируется в ридере поверх
   его собственной #toggle-mode. #language-button сюда НЕ входит — он физически вынесен из
   #results-toolbar в разметке (search/index.html) именно потому, что ему нужна ОБРАТНАЯ
   видимость (скрыт в выдаче — там нечего переключать, показан в чтении — см. правило ниже), а
   display:none на родителе полностью скрыл бы потомка независимо от любых его собственных
   правил — быть внутри этого списком он не мог бы в принципе. */
body.dg-state-reader #search-pane,
body.dg-state-reader #results-toolbar,
body.dg-state-reader #results-divider,
body.dg-state-reader #dynamicHeader,
body.dg-state-reader #btn-show-all-children,
body.dg-state-reader #btn-read-marks,
body.dg-state-reader .forshellscript {
    display: none;
}
/* Pāḷi/translation toggle used to be hidden on the results LISTING (comment here used to claim
   it was a "fake button that doesn't work" there) — that was true at the time, but is stale now:
   search-render.js/langswitch.css later wired up .dg-title-lang + .quote so hide-pali/hide-english
   on #sutta DOES affect titles and quotes in the results table too. Owner asked for the button
   back on results, same as in the reader — #dg-state-home still hides it above (no results table
   there at all, nothing to toggle). */
body.dg-state-reader #variants-hint,
body.dg-state-toc #variants-hint { display: none !important; }

/* ── ИИ-поиск (docs/AI_SEARCH_BRIEF.md, docs/AI_MODE_DESIGN.md) ──────────────────────────────
   Фолбэк, когда точный поиск дал 0 результатов: #ai-pane пуст по умолчанию, наполняется JS
   (public/overrides/js/ai-search.js) тем же приёмом, что #toc-pane/spa/toc.js — тег остаётся в
   разметке всегда, содержимое приходит только когда реально нужно. */
#ai-pane { display: none; }
body.dg-state-ai #ai-pane { display: block; }
body.dg-state-ai #search-pane,
body.dg-state-ai #results-toolbar,
body.dg-state-ai #results-divider,
body.dg-state-ai #dynamicHeader,
body.dg-state-ai .forshellscript {
    display: none;
}
.ai { max-width: 840px; margin: 0 auto; padding: 22px 0 0; }
.aihead { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.aihead h2 { font-size: 21px; margin: 0; font-weight: 600; letter-spacing: -.01em; flex: 1 1 auto; min-width: min(100%, 26ch); text-wrap: pretty; }
.aihead .n { font-size: 13px; color: var(--dg-text-muted); }
/* Loading skeleton in the same order as the answer: note line, Pali word chips, results table rows
   (owner: the old one showed a side column of words that the answer never had). */
.aiskel { display: flex; flex-direction: column; gap: 16px; margin: 22px 0 0; }
.aisk-row { display: flex; align-items: center; gap: 16px; }
.aisk-row .skl + .skl { margin-top: 0; }
.aisk-row .aisk-end { margin-left: auto; }
/* .aicards stays — tableSkeleton() (ai-search.js) still uses it for the LOADING placeholder rows.
   The real thing (.aicard, .aicollapse, .aicards.collapsed, .qg — an actual rendered card with a
   sutta id/title/quote and its own collapse-all) never got built: real results reuse the site's
   own DataTable instead (#pali, docs/AI_SEARCH_BRIEF.md "по-настоящему DataTable"), triangles and
   collapse-all included for free. Deleted rather than left as dead weight (owner: "1 удали"). */
.aicards { display: flex; flex-direction: column; gap: 0; border-top: 1px solid var(--dg-border); }
.aiwords { display: flex; flex-wrap: wrap; gap: 7px; }
/* Owner: "клики по слову подставляют слово в инпут, а доп ссылочка — открыть в словаре" —
   the pill is a container for two separate clickable pieces now, not one link: the word itself
   (button, overwrites #paliauto) and a small ↗ (real link to dict.dhamma.gift, new tab). */
.aiword { display: inline-flex; align-items: baseline; gap: 2px; border: 1px solid var(--dg-border); background: none; border-radius: 999px; font-size: 13.5px; color: var(--dg-text); padding: 2px 4px 2px 13px; transition: border-color .15s var(--dg-ease), background .15s var(--dg-ease), color .15s var(--dg-ease); }
.aiword:hover { border-color: var(--dg-accent); background: var(--dg-accent-bg); color: var(--dg-text); }
.aiword-term { display: inline-flex; align-items: baseline; gap: 7px; border: 0; background: none; font: inherit; font-size: inherit; color: inherit; padding: 4px 0; cursor: pointer; text-align: left; }
.aiword em { font-style: normal; font-size: 12px; color: var(--dg-text-muted); }
/* Gloss slot while the bundled DPD is still loading (ai-search.js enrichWithLocalDpd) — same
   shimmer as the .skp/.skl skeletons above, sized to sit inline next to the word. */
.aiword em.is-loading { display: inline-block; width: 58px; height: 9px; border-radius: 999px; background: var(--dg-surface-active); background-image: linear-gradient(90deg, transparent 0, var(--dg-surface) 50%, transparent 100%); background-size: 280% 100%; animation: ai-sk 1.4s ease-in-out infinite; }
.aiword-dict { display: inline-flex; align-items: center; justify-content: center; align-self: center; border: 0; background: none; color: var(--dg-text-muted); padding: 6px; border-radius: 999px; cursor: pointer; }
.aiword-dict:hover { color: var(--dg-accent); background: var(--dg-surface); }
.aifoot { display: flex; align-items: center; gap: 3px; flex-wrap: wrap; margin: 24px 0 0; padding: 12px 0 50px; border-top: 1px solid var(--dg-border); }
.aifoot .dis { font-size: 12px; color: var(--dg-text-muted); padding-left: 8px; }
.aifoot a, .aifoot button { border: 0; background: none; font: inherit; font-size: 13px; color: var(--dg-tblue); cursor: pointer; padding: 4px 8px; border-radius: 6px; display: flex; align-items: center; gap: 5px; text-decoration: none; }
.aifoot a:hover, .aifoot button:hover { background: var(--dg-accent-bg); color: var(--dg-tblue); text-decoration: underline; }
/* Owner: "внизу маленькую кнопку raw data... кнопки копировать на каждой строке" — click-to-reveal
   debug panel (ai-search.js showDebug/copyRow), replacing an earlier hover-only tooltip that
   never worked on touch. Muted throughout on purpose — a debug aid, not a real feature.
   Owner: "сделай МАЛЕНЬКУЮ кнопку... не растягивай тултип на весь экран... копировать может
   оказаться за кнопкой языка" — the toggle now renders as a plain small link (no Bootstrap .btn
   padding, see ai-search.js), the panel is capped to a real "small note" width instead of
   stretching across its (often very wide) container, and .ai-debug-value no longer pushes the
   copy icon out to the row's far edge — it sits right after the text, nowhere near the
   fixed-position Pāli/translation pill in the bottom-right corner regardless of panel width. */
/* Owner: "твоя задача добавить в футер кнопки на 4 страницах... где-то вообще нет" — only the
   real sutta-table outcome had an actual footer to plug into (.dt-buttons, Main/History/Export/…);
   the other three (words-only, empty, error) just got the debug link dropped wherever a container
   happened to exist, with no shared visual treatment. This border-top makes every placement read
   as the same "footer strip" element regardless of what it's sitting inside; reset to nothing
   inside .dt-buttons, which is already a real footer row and needs no second one nested in it. */
.ai-debug-wrap { margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--dg-border); }
/* Owner: "К точному поиску на одной строке, raw data на другой... они же вместе должны быть" —
   #ai-error/#ai-empty already have their own "back to exact search" button inside a flex row
   (.aifoot / .acts); raw data is appended INSIDE that same row now (ai-search.js), not as a
   block sibling after it — so it needs to behave like one more flex item on that row (same
   treatment .dt-buttons already gets there), not the default stacked-below footer look. */
.dt-buttons .ai-debug-wrap, .aifoot .ai-debug-wrap, .acts .ai-debug-wrap { margin-top: 0; padding-top: 0; border-top: 0; display: inline-block; }
/* Collapsed, .ai-debug-wrap is short — sits inline right next to "К точному поиску" on the same
   flex row. Expanded, the panel makes it tall — flex's default align-items:center would then
   vertically float the short neighbour button in the middle of that height, reading as broken
   (found live). flex-basis:100% forces it onto its own full-width line once open, same as any
   ordinary expand/disclosure widget — only the SHORT collapsed state needs to share the row. */
.aifoot .ai-debug-wrap:has(.ai-debug-panel:not(.d-none)),
.acts .ai-debug-wrap:has(.ai-debug-panel:not(.d-none)) { flex-basis: 100%; }
.ai-debug-link { border: 0; background: none; padding: 0; font-size: 12px; color: var(--dg-text-muted); text-decoration: underline; cursor: pointer; opacity: 0.7; }
.ai-debug-link:hover { opacity: 1; }
.ai-debug-panel { margin-top: 6px; max-width: min(360px, 100%); padding: 8px 10px; border: 1px solid var(--dg-border); border-radius: 8px; background: var(--dg-surface); font-size: 12px; }
.ai-debug-row { display: flex; align-items: baseline; gap: 6px; padding: 3px 0; flex-wrap: wrap; }
.ai-debug-label { color: var(--dg-text-muted); flex-shrink: 0; }
.ai-debug-value { color: var(--dg-text); word-break: break-word; }
.ai-debug-copy { border: 1px solid var(--dg-border); background: none; color: var(--dg-text-muted); font-size: 11px; padding: 1px 7px; border-radius: 999px; cursor: pointer; flex-shrink: 0; }
.ai-debug-copy:hover { color: var(--dg-accent); border-color: var(--dg-accent); }
#ai-ready, #ai-load, #ai-empty, #ai-error { display: none; }
[data-ai=ready] #ai-ready, [data-ai=load] #ai-load, [data-ai=empty] #ai-empty, [data-ai=error] #ai-error { display: block; }
#ai-load .st { display: flex; align-items: center; gap: 9px; margin: 10px 0 0; font-size: 13.5px; color: var(--dg-text-2); }
#ai-load .st .gi { font-size: 14px; color: var(--dg-accent-ink); animation: ai-spin 1.1s linear infinite; }
#ai-load .st .sub { font-size: 12px; color: var(--dg-text-muted); }
.aisk { padding: 13px 10px 14px; border-bottom: 1px solid var(--dg-border); }
.skp { display: block; height: 30px; border-radius: 999px; background: var(--dg-surface-active); background-image: linear-gradient(90deg, transparent 0, var(--dg-surface) 50%, transparent 100%); background-size: 280% 100%; animation: ai-sk 1.4s ease-in-out infinite; }
.skl { height: 11px; border-radius: 6px; background: var(--dg-surface-active); background-image: linear-gradient(90deg, transparent 0, var(--dg-surface) 50%, transparent 100%); background-size: 280% 100%; animation: ai-sk 1.4s ease-in-out infinite; }
.skl + .skl { margin-top: 9px; }
@keyframes ai-sk { from { background-position: 160% 0; } to { background-position: -60% 0; } }
@keyframes ai-spin { to { transform: rotate(360deg); } }
/* Блик по фразе запроса, пока идёт подбор — ТОЛЬКО по буквам, не полосой через всю шапку
   (owner: было "пучком по всей длине"). Тот же приём, что #home-motto выше в этом файле:
   background-clip:text держит свет строго внутри контуров букв. */
.aihead h2.sheening {
    background-color: var(--dg-text);
    background-image: radial-gradient(circle 20px at center, var(--dg-motto-shine) 0%, transparent 100%);
    background-repeat: no-repeat;
    background-size: 40px 100%;
    background-position: -40px 0;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: ai-sheen 8s linear infinite;
}
@keyframes ai-sheen { from { background-position: -40px 0; } to { background-position: calc(100% + 40px) 0; } }
.aistate { margin: 22px 0 0; padding: 26px 22px; background: var(--dg-surface-hover); border: 1px solid var(--dg-border); border-radius: var(--dg-radius); max-width: 64ch; }
.aistate .ttl { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -.01em; display: flex; align-items: baseline; gap: 9px; }
.aistate p { margin: 9px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--dg-text-2); text-wrap: pretty; }
.aistate .acts { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 18px 0 0; }
.aistate .primary { border: 0; border-radius: 999px; background: var(--dg-accent-dark); color: #fff; font: inherit; font-size: 13.5px; font-weight: 500; padding: 9px 20px; cursor: pointer; transition: background .15s var(--dg-ease); }
.aistate .primary:hover { background: var(--dg-accent); }
.aistate .ghost { border: 0; background: none; font: inherit; font-size: 13.5px; color: var(--dg-tblue); cursor: pointer; padding: 9px 2px; text-decoration: underline; text-underline-offset: 3px; }
.aierr { margin: 14px 0 0; max-width: 70ch; font-size: 12.5px; line-height: 1.6; color: var(--dg-text-muted); text-wrap: pretty; }
.aierr button { border: 0; background: none; font: inherit; font-size: 12.5px; color: var(--dg-tblue); cursor: pointer; padding: 0; text-decoration: underline; text-underline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
    .skl, .skp, .aiword em.is-loading, #ai-load .st .gi { animation: none; }
    .aihead h2.sheening { animation: none; background: none; color: var(--dg-text); }
}
@media (max-width: 700px) {
    .aihead h2 { font-size: 19px; }
}

/* #variants-hint — отдельно и с !important: скрипт выдачи показывает его ИНЛАЙНОВЫМ
   style="display:block" (см. renderResultHeader в index.html), а инлайн бьёт любой селектор
   таблицы стилей. Без этого подсказка "у слова есть варианты" оставалась висеть на главной
   после возврата из выдачи по кнопке "назад". */
body.dg-state-home #variants-hint { display: none !important; }

@media (prefers-reduced-motion: reduce) {
    #home-motto, #home-hint, #home-pane,
    .hero-row, .dg-hero-form {
        transition: none;
    }
}

/* Первый кадр загрузки: состояние уже проставлено инлайновым скриптом в начале <body>, и без
   этого главная каждый раз "въезжала" бы анимацией. Снимается через два requestAnimationFrame. */
body.dg-no-anim,
body.dg-no-anim * {
    transition: none !important;
    animation: none !important;
}

/* ============================================================================
   Заголовок главной (production-v4 redesign, docs/Home-standalone.html)
   Крупный H1 + подзаголовок, центрированные, собственным блоком между шапкой и полем поиска —
   не строка рядом с вывеской, как раньше (см. #dg-hero-heading в index.html).
   ============================================================================ */
/* Sizes measured off the reference: 38px above the H1, 30px/600 H1 with 6px below, 14px
   subtitle with 22px below it (that 22px lives on .hero-row's margin-top, see above). */
#dg-hero-heading {
    display: none;
    text-align: center;
    /* Horizontal inset already comes from the parent .dg-hero-inner — just top spacing here. */
    padding: 38px 0 0;
}
body.dg-state-home #dg-hero-heading { display: block; }
#home-motto {
    margin: 0 0 6px;
    font-family: var(--dg-font);
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.2;
    /* On the plain page background now (not the dark band) — dark text in light theme, light
       text in dark theme, same tokens the rest of the page's headings use. */
    color: var(--dg-text);
}
/* One-time shine sweep across "Найдите Истину" on first paint (owner: "чтобы при открытии один
   раз по надписи прошёл такой свет по всей надписи") — delight tier, plays once per real page
   load, never repeats (a plain CSS animation with no trigger to re-fire, not tied to any
   frequently-toggled state). @supports-gated: browsers without background-clip:text just keep
   the plain solid --dg-text color set above, never see transparent text. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    #home-motto {
        /* Owner: "какой формы луч я представлял круглый" — a round spot of light, not a
           diagonal bar. background-color is the letters' normal resting color, always painted
           (a plain color can't be a comma-separated background-image layer — that was tried
           first and silently resolved to `none`, caught live via computed-style before
           shipping). background-image is a single small radial circle (the travelling
           spotlight, fading to transparent at its own edge) painted on top of that fill; only
           its position animates, sliding left to right, so most of the word stays its normal
           color and only the ~48px pool under the circle brightens as it passes — instead of
           the whole word dimming/brightening together like the earlier diagonal-band version. */
        background-color: var(--dg-text);
        background-image: radial-gradient(circle 24px at center, var(--dg-motto-shine) 0%, transparent 100%);
        background-repeat: no-repeat;
        background-size: 48px 100%;
        background-position: -48px 0;
        -webkit-background-clip: text;
        background-clip: text;
        -webkit-text-fill-color: transparent;
        color: transparent;
        /* linear, not var(--dg-ease): that token is a strong ease-out for entering/exiting UI
           (see the file's other uses) — this is constant, marquee-like motion crossing the
           screen, which wants linear (AUDIT.md §2, improve-animations skill). */
        /* Owner: "нужно сделать чтобы ещё была медленно... хотя бы за 3 сек" — was 1.4s. */
        animation: dg-motto-shine 8s linear 0.3s 1 both;
    }
}
@keyframes dg-motto-shine {
    from { background-position: -48px 0; }
    to { background-position: calc(100% + 48px) 0; }
}
@media (prefers-reduced-motion: reduce) {
    /* Delight-only motion, no comprehension purpose — reduced motion drops it entirely rather
       than offering a gentler variant, per owner's usual pattern on purely decorative sweeps. */
    #home-motto { animation: none; background: none; color: var(--dg-text); }
}
#home-subtitle {
    margin: 0;
    font-family: var(--dg-font);
    font-size: 14px;
    line-height: 1.5;
    color: var(--dg-text-2);
}
@media (max-width: 767.98px) {
    #home-motto { font-size: 26px; }
}

/* Подсказка под полем: "искать «…»" / "похоже на ссылку на текст". На полосе — светлая плашка
   поверх тёмного фона; акцентная заливка там нечитаема.
   Owner (round 3): справа, под полем — не в потоке (иначе снова толкала бы плитки вниз), а
   position:absolute от .dg-hero-form (position:relative там же, search/index.html — раньше был
   от .hero-row, но та растянута на всю строку и шире самого поля, из-за чего подсказка уезжала
   вправо от кнопки поиска; теперь #home-hint — последний child формы, а не .hero-row, и правым
   краем совпадает ровно с полем/кнопкой), вровень с полем. Автодополнение (.ui-autocomplete,
   uiextra.css) висит у ЛЕВОГО края поля и не шире 274px — справа под широким полем места
   достаточно, не пересекаются. Скрыта на мобильных (see media query below) — owner. */
#home-hint {
    text-align: right;
    position: absolute;
    top: 100%;
    right: 0;
}
@media (max-width: 767.98px) { #home-hint { display: none; } }
#home-hint .dg-hint {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.72rem;
    font-weight: 600;
    /* Was a translucent-white chip for sitting on the dark band; the hint now sits on the plain
       page background alongside the search field, so it takes the same neutral surface/border
       tokens as everything else there. */
    color: var(--dg-text-2);
    background: var(--dg-surface-hover);
    padding: 5px 10px;
    border-radius: 7px;
}

/* ============================================================================
   Строка области поиска — "N Никаи · M КН · изменить" (production-v4 redesign,
   docs/Home-standalone.html). Текст считает renderScopeSummary() (home.js) из тех же
   SCOPE_GROUPS/readScope(), что и обычная шторка быстрых настроек.
   ============================================================================ */
/* Reference .scope-line: 11px under the field, 12.5px muted text, 7px gap, the link in accent
   with a 13px sliders glyph 5px before the word. */
#home-scope-summary {
    display: none;
    justify-content: center;
    align-items: center;
    gap: 7px;
    margin-top: 11px;
    font-family: var(--dg-font);
    font-size: 12.5px;
    color: var(--dg-text-muted);
}
body.dg-state-home #home-scope-summary { display: flex; }
.dg-scope-change {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    color: var(--dg-accent-ink);
    font-family: var(--dg-font);
    font-size: inherit;
}
/* Same sliders SVG as the quick-settings button (quickButtonHtml(), home.js) — unrotated here,
   like the reference's fa-sliders; .dg-qs-btn's 90° turn is scoped to that button only. */
.dg-scope-change .dg-qs-gear { width: 13px; height: 13px; display: block; }
.dg-scope-change:hover, .dg-scope-change:focus-visible { text-decoration: underline; }

/* ============================================================================
   Объявление под полем поиска (#dg-announce, см. .dg-hero-inner в search/index.html)
   ============================================================================ */
/* Было position:absolute НАД полем (owner: "без сдвига интерфейса") — .hero-row держал
   зарезервированный пустой отступ специально под неё. В production-v4 redesign
   (docs/Home-standalone.html) плашка стоит ПОСЛЕ поля, в обычном потоке — резервировать место
   больше незачем, а появление/закрытие просто раздвигает/сдвигает то, что ниже (плитки), один
   раз при показе, а не постоянно занимает воздух над полем. */
/* Takes no space until an announcement is actually shown (display:none, not just opacity):
   the one shift when it appears a couple of seconds after load is accepted (owner, 2026-09-06 —
   a first-paint reservation was tried and rejected: it can't help the very first visit anyway). */
#dg-announce {
    display: none;
    justify-content: center;
    margin-top: 18px;
    /* Плавное появление (плашку показывает home.js через несколько секунд после загрузки). */
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity 0.35s ease, transform 0.35s ease;
}
#dg-announce.dg-announce-in { display: flex; opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    #dg-announce { transition: none; transform: none; }
}
body:not(.dg-state-home) #dg-announce { display: none; }
/* Reference .announce: 13px text, 7/8/7/13 padding, 12px corners, 9px gaps, ≤640px; a small
   uppercase "BETA" badge in front (item.tag, announcements.json); accent-colored link and close. */
.dg-announce-box {
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: 640px;
    padding: 7px 8px 7px 13px;
    border-radius: 12px;
    /* Was a translucent-white chip for the dark band; now on the plain page, so it can use the
       real accent-tinted pill everywhere else on the page uses (production-v4 redesign,
       docs/Home-standalone.html) instead of a fake-transparent stand-in. */
    background: var(--dg-accent-bg);
    color: var(--dg-text-2);
    font-family: var(--dg-font);
    font-size: 13px;
    line-height: 1.45;
}
.dg-announce-box a { color: var(--dg-accent-ink); text-decoration: underline; }
.dg-announce-tag {
    flex: none;
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--dg-accent-dark);
    color: #fff;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    line-height: 1.45;
}
.dg-announce-close {
    flex: none;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--dg-accent-ink);
    opacity: 0.6;
    cursor: pointer;
}
.dg-announce-close:hover, .dg-announce-close:focus-visible { opacity: 1; background: rgba(0, 0, 0, 0.08); }
/* На узком экране отступ над полем тот же, но текст переносится в две строки — прижимаем плашку
   к низу отступа, чтобы она не наезжала на шапку. */
@media (max-width: 767.98px) {
    .dg-announce-box { font-size: 0.78rem; padding: 6px 6px 6px 10px; }
}

/* ============================================================================
   Плитки
   ============================================================================ */
/* Reference nav: the full 880px content column, 4 × 1fr, 10px gaps, 24px above / 10px below. */
.dg-tiles {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    max-width: 880px;
    margin: 0 auto;
    padding: 2px 0 10px;
    /* Reserve space for the tiles home.js fills in after its menu-links.json fetch resolves —
       without this the empty grid collapses to 0 height and everything below (footer etc.)
       jumps down once tiles pop in. Sized for the default 8 tiles at 2 cols (4 rows); narrower
       at >=576px below since it switches to 4 cols (2 rows). Approximate on purpose — tile count
       is user-customizable (hidden/custom tiles), an exact height isn't possible anyway. */
    min-height: 460px;
}
.dg-tiles:empty {
    background: linear-gradient(90deg, var(--dg-surface) 25%, var(--dg-surface-hover) 50%, var(--dg-surface) 75%);
    background-size: 200% 100%;
    border-radius: 12px;
    animation: dg-tiles-skeleton 1.4s ease-in-out infinite;
}
@keyframes dg-tiles-skeleton {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
/* 4 columns from tablet width up; phones keep 2 (reference: 2 columns below 760px). */
@media (min-width: 768px) {
    .dg-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); max-width: 880px; min-height: 336px; }
}

/* Reference .tile: 18/14 padding, 10px corners, 9px between disc/label/desc, 14px/600 label,
   12px description. */
.dg-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 18px 14px;
    background: var(--dg-surface);
    border: 1px solid var(--dg-border);
    border-radius: 10px;
    font-family: var(--dg-font);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.5;
    color: var(--dg-text);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.dg-tile:hover,
.dg-tile:focus-visible {
    background: var(--dg-surface-hover);
    border-color: var(--dg-border-strong);
    color: var(--dg-text);
}
.dg-tile:active { transform: scale(0.985); }

/* Иконка — в кружке из акцентного фона, сама иконка акцентного цвета. Кружок и есть то, что
   делает плитку значком, а не строкой списка в рамке. */
.dg-tile-ic {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    flex: none;
    border-radius: 50%;
    background: var(--dg-accent-bg);
}
.dg-tile svg {
    width: 21px;
    height: 21px;
    display: block;
    color: var(--dg-icon-ink);
}
/* Мини-описание под названием плитки (menu-links.json desc; включается в шторке «Настройки»).
   Мельче и бледнее подписи, не жирное, до двух строк — плитка остаётся значком с подписью, а
   строка лишь отвечает «что там внутри». Отрицательный margin съедает часть gap'а плитки, чтобы
   описание читалось как продолжение подписи, а не как третий равноправный элемент. */
.dg-tile-desc {
    display: block;
    margin-top: -4px;
    font-size: 12px;
    font-weight: 400;
    line-height: 1.4;
    color: var(--dg-text-2);
    max-width: 100%;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

/* ============================================================================
   Нижняя шторка со ссылками
   position:fixed — она вне схлопывающегося #home-pane и живёт в конце <body>, иначе
   overflow:hidden родителя обрезал бы её.
   ============================================================================ */
#dg-sheet-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(20, 18, 10, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
    z-index: 1080;
}
#dg-sheet-backdrop.show { opacity: 1; pointer-events: auto; }
/* Под выпадашкой быстрых настроек подложка невидима, но клики по странице всё так же ловит:
   затемнять весь экран ради маленького меню — перебор, а закрывать по клику мимо нужно. */
#dg-sheet-backdrop.dg-transparent { background: transparent; }

.dg-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* Above the offline download card (1082, public/offline/offline-status.js): tiles < card <
       sheet — owner: the tiles sit behind the card, the mega menu may go over it. */
    z-index: 1083;
    display: flex;
    flex-direction: column;
    max-height: 82vh;
    background: var(--dg-surface);
    color: var(--dg-text);
    font-family: var(--dg-font);
    border-top: 1px solid var(--dg-border-strong);
    border-radius: 16px 16px 0 0;
    transform: translateY(100%);
    transition: transform 0.3s var(--dg-ease);
}
.dg-sheet.show { transform: translateY(0); }
@media (min-width: 768px) {
    .dg-sheet {
        left: 50%;
        right: auto;
        bottom: 20px;
        width: 560px;
        max-height: 74vh;
        border: 1px solid var(--dg-border-strong);
        border-radius: 16px;
        transform: translate(-50%, calc(100% + 20px));
    }
    .dg-sheet.show { transform: translate(-50%, 0); }
    /* «О проекте» — шире 560px списка плиток: поле поиска на главной 720px (.dg-hero-form ниже)
       плюс по 100px с каждой стороны (owner), там длинная цитата и ряд кнопок приложений. */
    .dg-sheet.dg-wide { width: min(920px, calc(100vw / var(--dg-zoom, 1) - 32px)); }
    /* Owner: "если место позволяет нужно чтобы футер был внизу" — .dg-sheet has no explicit
       height (max-height only, sized to fit its own content), so the .dg-about #contacts
       margin-top:auto trick above has nothing to push against on a tall viewport with short
       content. Same value as max-height above: the sheet locks to a real 74vh box whenever
       content fits inside it (giving margin-top:auto real room to push the footer down to the
       bottom of THAT box), and content taller than 74vh simply overflows/scrolls exactly like
       today — min-height can't force it shorter than its own content. */
    .dg-sheet.dg-wide { min-height: 74vh; }
    .dg-sheet.dg-wide .dg-sheet-body { padding: 8px 44px 40px; }
}

/* Быстрые настройки — выпадашка ПОД шестерёнкой, на любой ширине. Нижняя шторка выглядела как
   отдельный раздел страницы и уводила взгляд от поля, к которому эти настройки относятся.
   Правило вне медиазапроса намеренно: на узком экране home.js сам сужает выпадашку до ширины
   экрана за вычетом полей (см. placeAnchored). Координаты приходят инлайном. */
.dg-sheet.dg-anchored {
    left: auto;
    right: auto;
    bottom: auto;
    max-height: 70vh;
    border: 1px solid var(--dg-border-strong);
    border-radius: 14px;
    box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.35);
    transform: translateY(-8px);
    opacity: 0;
    transition: transform 0.16s var(--dg-ease), opacity 0.16s ease;
}
.dg-sheet.dg-anchored.show { transform: translateY(0); opacity: 1; }
/* Opened from the quick window's gear (quickModal.js): the window is at z-index 10000
   (quick-modal.css), every sheet here at 1080/1081 — the dropdown would open behind it. */
.dg-sheet.dg-above-quick-modal { z-index: 10050; }
#dg-sheet-backdrop.dg-above-quick-modal { z-index: 10040; }
/* У выпадашки ручки-«потяни вниз» быть не должно: тянуть её некуда. */
.dg-sheet.dg-anchored .dg-sheet-handle { display: none; }

/* Мега-меню (External/AI & Dicts/Materials/Tools/Русские) — тот же анкоренный попап, что у
   быстрых настроек, но .dg-sheet-body раскладывается в колонки вместо вкладок+списка.
   Ширину/позицию считает placeMegaAnchored() (home.js) инлайном.
   position: absolute (не fixed, как у .dg-sheet/.dg-anchored) — координаты, которые считает
   placeMegaAnchored(), уже document-relative (учитывают scrollX/scrollY), так что попап скроллится
   ВМЕСТЕ со страницей, а не остаётся приклеенным к вьюпорту. max-height/overflow — none/visible:
   owner явно просил убрать СВОЙ скролл попапа ("не должно быть скролла... за счёт общего сдвига
   экрана его нужно прокручивать, а не за счёт какого-то своего отдельного скроллбара") — если
   колонки не помещаются в высоту вьюпорта, страница просто скроллится ниже, как у обычного
   мега-меню; scrollForMega() (home.js) заранее подтягивает страницу так, чтобы поле поиска
   оказалось у верха экрана (плюс сжимает зазоры над плитками, body.dg-mega-compact ниже), чтобы
   места обычно хватало без скролла вовсе.
   Открытие — не translateY, как у .dg-anchored выше, а scale от transform-origin, который
   выставляет placeMegaAnchored() инлайном (X — под серединой открывшей кнопки): owner: "анимацию
   как будто мегаменю расширяется/растягивается из соответствующей кнопки". */
.dg-sheet.dg-anchored.dg-mega {
    position: absolute;
    max-height: none;
    transform: scale(0.35);
    transition: transform 0.22s var(--dg-ease), opacity 0.16s ease;
}
.dg-sheet.dg-anchored.dg-mega.show { transform: scale(1); }
.dg-mega .dg-sheet-body {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 0 28px;
    align-items: start;
}
/* #dg-mega (id), not .dg-mega (class): .dg-sheet .dg-sheet-body (overflow-y:auto, further down
   this file) has the SAME class-only specificity and comes AFTER this rule in source order, so a
   same-specificity .dg-mega override here would silently lose (same trap as the comment on
   #dg-mega .dg-sheet-row above) — bumped to an id selector to win for real. */
#dg-mega .dg-sheet-body {
    overflow-y: visible;
    max-height: none;
}
/* A later un-headed cluster inside a "blocks" group (owner: "не выделяй suttacentral в
   отдельный" — SC/Vinaya/Voice/Legacy etc. share the Collections header, split from the block
   above them by a quiet rule only, never a made-up sub-title). */
.dg-mega-block-divider { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--dg-border); }
.dg-mega-col { min-width: 0; }
/* Owner: "скролл не нужен был по максимуму" — Patimokkha+Prātimokṣa (10 пунктов с описаниями,
   владелец явно просил их держать в одной колонке) остаются самой высокой колонкой независимо
   от числа колонок в сетке; единственный оставшийся рычаг — плотность самой строки. Сужаем
   только внутри мега-меню (.dg-sheet-row/.dg-group-title — общие классы с нижней шторкой, её
   не трогаем). :first-child здесь переопределяет общее .dg-group-title:first-child (метит
   первый заголовок ВСЕЙ шторки) — в колонках первый заголовок должен быть без верхнего отступа
   у КАЖДОЙ колонки, а не только у первой. */
/* #dg-mega (id), not .dg-mega (class): the generic .dg-sheet-row/.dg-row-desc/.dg-group-title
   rules a bit further down this file have the SAME class-only specificity and come AFTER these
   in source order, so a same-specificity .dg-mega override here was silently losing the
   cascade (measured live: padding stayed 11px, not 7px) — the id bumps specificity past that,
   no reordering needed. */
#dg-mega .dg-sheet-row { padding: 7px 0; }
/* Owner: "описание идёт отдельной строчкой снизу... всё удлиняется чуть ли не в два раза" —
   desc back to inline (its default as a <small>, before the generic .dg-sheet rule below forces
   it to its own line) with a quiet separator, same row, no line break — label stays bright
   (inherits the row's normal text color), desc stays dim (--dg-text-2 further down). Cuts most
   rows back to one line, which also does more for "скролл не нужен был по максимуму" than the
   padding trim above ever could. */
#dg-mega .dg-row-desc {
    display: inline;
    margin-top: 0;
}
#dg-mega .dg-row-desc::before { content: " \00b7 "; color: var(--dg-text-muted); }
#dg-mega .dg-group-title { margin: 1.4em 0 0.6em; }
.dg-mega-col .dg-group-title:first-child { margin-top: 0; }

@media (prefers-reduced-motion: reduce) {
    .dg-sheet, #dg-sheet-backdrop { transition: none; }
}

.dg-sheet .dg-sheet-handle {
    width: 34px;
    height: 3.5px;
    border-radius: 3px;
    background: var(--dg-border-strong);
    margin: 9px auto 2px;
    flex: none;
}
@media (min-width: 768px) { .dg-sheet .dg-sheet-handle { display: none; } }

.dg-sheet .dg-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 8px 18px 4px;
    flex: none;
}
.dg-sheet .dg-sheet-head h2 {
    font-size: 0.95rem;
    font-weight: 700;
    margin: 0;
    color: var(--dg-text);
}
.dg-sheet .dg-sheet-close {
    border: none;
    background: transparent;
    color: var(--dg-text-2);
    font-size: 1.3rem;
    line-height: 1;
    padding: 0.2rem 0.4rem;
    cursor: pointer;
}

.dg-sheet .dg-sheet-tabs {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding: 6px 18px 10px;
    border-bottom: 1px solid var(--dg-border);
    flex: none;
}
.dg-sheet .dg-sheet-tabs button {
    flex: none;
    font-size: 0.74rem;
    font-weight: 600;
    padding: 6px 11px;
    border-radius: 7px;
    border: 1px solid var(--dg-border);
    color: var(--dg-text-2);
    background: var(--dg-surface);
    cursor: pointer;
}
.dg-sheet .dg-sheet-tabs button.on {
    background: var(--dg-accent-bg);
    border-color: var(--dg-accent);
    color: var(--dg-accent);
}

.dg-sheet .dg-sheet-body {
    overflow-y: auto;
    padding: 4px 18px 22px;
    flex: 1 1 auto;
}
/* Owner: "если место позволяет нужно чтобы футер... был внизу" — the About sheet's own contacts
   block (openAbout(), search/js/home.js) is a flex column so short content (a small viewport's
   worth or less) pins "Контакты"+icons+"Powered by"+copyright to the bottom of the sheet instead
   of floating right under "Приложения и расширения"; long content still just scrolls normally,
   margin-top:auto only pushes down as far as there's actual leftover space. */
.dg-sheet-body.dg-about {
    display: flex;
    flex-direction: column;
}
.dg-sheet-body.dg-about #contacts {
    margin-top: auto;
}
/* Settings page embedded as a slide-in sheet (owner: "настройки должны выезжать как меню
   тайлов в мобильном, а не как отдельная страница" → "и на десктопе тоже, так красивее и
   функциональнее") — reuses the same .dg-sheet chrome as the multitool tile sheet, but hosts
   the real /settings/ page in an iframe instead of a rendered link list, so there's exactly one
   settings implementation. dg-wide (home.js): same 920px floating-card width as the About
   sheet on desktop — owner explicitly wants it to still READ as a sheet there, not a full page
   ("а-то меню не отличить от полной страницы"); iframe/body sizing below is shared, only the
   position/size override just under it is mobile-only ("на мобильных пусть занимает всю
   страницу"). */
/* height:100% on the iframe (a percentage against a flex-item ancestor whose own height comes
   from flex-grow, not an explicit value) doesn't reliably resolve in Chromium — confirmed live:
   at some window sizes the iframe silently fell back to the UA default 150px, leaving most of
   the sheet blank (owner screenshot, incognito/no-cache — not a caching artifact). Absolute-fill
   instead: position:relative on the body makes it the containing block, inset:0 on the iframe
   sizes it directly from that box's padding edges, without depending on percentage-height
   resolution at all. */
.dg-sheet.dg-settings-embed .dg-sheet-body { padding: 0; overflow: hidden; min-height: 0; position: relative; }
.dg-sheet.dg-settings-embed .dg-sheet-body iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
/* Settings = full-height side panel on the right at EVERY width (owner: "на всех открывать так,
   просто на каких-то ничего не будет видно от старой страницы"). Wide screens keep the live page
   visible and scrollable beside it (backdrop is transparent, see openSettingsSheet()); below
   460px the panel is simply the whole screen. Selectors out-rank the generic .dg-sheet
   breakpoint rules (left:50% + translate(-50%)). */
.dg-sheet.dg-settings-embed,
.dg-sheet.dg-settings-embed.show {
    top: 0;
    right: 0;
    bottom: 0;
    left: auto;
    width: min(460px, 100%);
    height: 100%;
    max-height: none;
    min-height: 0;
    border: 0;
    border-left: 1px solid var(--dg-border-strong);
    border-radius: 0;
    box-shadow: -12px 0 32px rgba(0, 0, 0, 0.18);
}
.dg-sheet.dg-settings-embed { transform: translateX(100%); }
.dg-sheet.dg-settings-embed.show { transform: translateX(0); }
.dg-sheet.dg-settings-embed .dg-sheet-handle { display: none; }
/* Below 768px there is no useful room for the page beside the panel (only a strip of it stuck out,
   owner; at 820px the side panel is still fine) — the panel is centered over a dimmed page instead
   (backdrop: openSettingsSheet()). Same 768px as home.js and settings/index.html (sample folded
   only when the page is visible) and the site's other sheet breakpoint above. */
@media (max-width: 767px) {
    .dg-sheet.dg-settings-embed,
    .dg-sheet.dg-settings-embed.show {
        left: 0;
        right: 0;
        margin: 0 auto;
        border-right: 1px solid var(--dg-border-strong);
        box-shadow: 0 0 32px rgba(0, 0, 0, 0.25);
    }
    .dg-sheet.dg-settings-embed { transform: translateY(100%); }
    .dg-sheet.dg-settings-embed.show { transform: translateY(0); }
}
/* Full-width panel: nothing beside it to separate from. */
@media (max-width: 480px) {
    .dg-sheet.dg-settings-embed,
    .dg-sheet.dg-settings-embed.show { border-left: 0; box-shadow: none; }
}
/* Заголовок набора отбит пустой строкой сверху и снизу — до правки он прилипал к предыдущему
   пункту и читался как его продолжение, а не как начало нового набора. */
.dg-sheet .dg-group-title {
    /* Owner: main menu items must read bigger than their sub-items, not smaller — was 0.72rem
       against .dg-sheet-row's 0.95rem (below), backwards from the intended hierarchy. Also
       covers #dg-mega (desktop mega-menu), which only overrides margin, not font-size. */
    font-size: 1.05rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--dg-text-muted);
    margin: 2em 0 1em;
}
.dg-sheet .dg-group-title:first-child { margin-top: 0.8em; }
.dg-sheet .dg-sheet-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 0;
    font-size: 0.95rem;
    color: var(--dg-text);
    text-decoration: none;
    border-bottom: 1px solid var(--dg-border);
    cursor: pointer;
}
.dg-sheet .dg-sheet-row:last-child { border-bottom: none; }
.dg-sheet .dg-sheet-row:hover { color: var(--dg-accent-ink); }
.dg-sheet .dg-sheet-row .dg-row-icon {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--dg-text-muted);
}
.dg-sheet .dg-sheet-row .dg-row-label { flex: 1; min-width: 0; }
.dg-sheet .dg-sheet-empty {
    font-size: 0.82rem;
    color: var(--dg-text-muted);
    padding: 14px 0;
}

/* Пояснение под названием ссылки — «что это вообще такое». Проставлено пока не всем пунктам, а
   первым в каждом наборе (поле desc в menu-links.json): по ним и видно, чем набор занимается. */
.dg-sheet .dg-sheet-row { align-items: flex-start; }
.dg-sheet .dg-sheet-row .dg-row-icon { margin-top: 2px; }
/* Пояснение — второй по важности текст строки, а не сноска: мелким его просто не читали.
   Цвет тоже подняли до --dg-text-2: muted на светлом фоне давал слишком блёклую строку. */
.dg-sheet .dg-row-desc {
    display: block;
    margin-top: 3px;
    font-size: 0.84rem;
    line-height: 1.45;
    color: var(--dg-text-2);
}

/* Вкладка-ссылка в шапке шторки: те плитки, у которых нет своего списка (Читать Pāḷi, История).
   Это НЕ переключение набора, а прямое действие — помечаем стрелкой и не даём состояние "on". */
.dg-sheet .dg-sheet-tabs button.dg-tab-link::after {
    content: " ↗";
    font-size: 0.68rem;
    opacity: 0.7;
}

/* ============================================================================
   Быстрые настройки (шестерёнка-молния). Отдельная шторка: наполнение зависит от состояния
   страницы, поэтому она перерисовывается при каждом открытии.
   ============================================================================ */
.dg-sheet .dg-qs-note {
    margin: 6px 0 0;
    font-size: 0.72rem;
    line-height: 1.4;
    color: var(--dg-text-muted);
}
.dg-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 9px 0;
    border: 0;
    border-bottom: 1px solid var(--dg-border);
    background: transparent;
    color: var(--dg-text);
    font-family: var(--dg-font);
    font-size: 0.85rem;
    text-align: left;
    cursor: pointer;
}
.dg-toggle-row:last-child { border-bottom: none; }
.dg-toggle-row .dg-toggle-label { flex: 1; min-width: 0; }
.dg-toggle-row .dg-toggle-label small {
    display: block;
    font-size: 0.72rem;
    color: var(--dg-text-muted);
}
/* Owner: "нужно чтобы это было видимо пользователю что есть горячие клавиши" — inline next to
   the label, not its own line (unlike .dg-toggle-label small above, that's a sub-description). */
.dg-toggle-hotkey {
    font-size: 0.7rem;
    font-weight: 400;
    color: var(--dg-text-muted);
}
/* Переключатель — свой, а не .form-switch Bootstrap: тот тянет за собой свою палитру и
   размеры, которые в шторке смотрятся крупнее всего остального. */
.dg-tgl {
    position: relative;
    width: 34px;
    height: 20px;
    flex: none;
    border-radius: 10px;
    background: var(--dg-surface-hover);
    border: 1px solid var(--dg-border-strong);
    transition: background-color 0.18s ease, border-color 0.18s ease;
}
.dg-tgl::after {
    content: "";
    position: absolute;
    top: 1px;
    left: 1px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--dg-surface);
    border: 1px solid var(--dg-border-strong);
    transition: transform 0.18s var(--dg-ease);
}
.dg-toggle-row[aria-pressed="true"] .dg-tgl {
    background: var(--dg-accent);
    border-color: var(--dg-accent);
}
.dg-toggle-row[aria-pressed="true"] .dg-tgl::after {
    transform: translateX(14px);
    border-color: transparent;
}

/* Переключатель «одно из нескольких». Размеры по макету: кнопки крупнее прежних — в них
   попадают пальцем, а не курсором. Выбранное — нейтральной заливкой, не акцентной: акцент в
   этом экране закреплён за действиями, а выбранный пункт действием не является. */
/* Same gotcha as the other [hidden] patches in this file (#dg-loading, .dg-scope-list, ...):
   `display:flex` below beats the browser's own `[hidden]{display:none}` on a specificity tie
   (author origin wins over user-agent) — dictModePicker()'s language seg staying .hidden did
   nothing visible without this. */
.dg-segmented[hidden] { display: none; }
.dg-segmented {
    display: flex;
    margin: 8px 0 2px;
    border: 1px solid var(--dg-border);
    border-radius: var(--dg-radius);
    overflow: hidden;
}
.dg-segmented button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
    padding: 10px 6px;
    border: 0;
    background: var(--dg-surface);
    color: var(--dg-text-2);
    font-family: var(--dg-font);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}
/* Подпись рядом со значком на узком экране может не помещаться — сжимается она, а значок
   остаётся целым: по нему вариант и узнают. */
.dg-segmented button > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dg-seg-ic { width: 14px; height: 14px; flex: none; }
.dg-segmented button[aria-pressed="true"] .dg-seg-ic { color: var(--dg-accent-ink); }
/* На узком экране трети переключателя не хватало на «Light» рядом со значком — подпись
   обрезалась многоточием (замерено на 375px). Ужимаем отступы и кегль, а не значок. */
@media (max-width: 420px) {
    .dg-segmented button { gap: 5px; padding: 10px 3px; font-size: 0.76rem; }
}
.dg-segmented button:hover { background: var(--dg-surface-hover); }
.dg-segmented button[aria-pressed="true"] {
    background: var(--dg-surface-active);
    color: var(--dg-text);
}

/* issue #5: font-size stepper in the drawer, right under the theme switch — owner ask: same
   style as the En/Ru and theme .dg-segmented switches. #dg-fontsize-ctrl carries
   class="dg-segmented" itself (search/index.html) for the shared border/radius/flex container.
   Owner: three EQUAL thirds ("−" / "100%" / "+"), same as .dg-segmented button's own flex:1 —
   no cell-level width override needed for that part, .dg-fontsize-val only needs its own
   look (no hover/pointer, muted color) since it isn't a button. */
#dg-fontsize-ctrl .dg-fontsize-btn { font-size: 1.2rem; font-weight: 700; }
#dg-fontsize-ctrl .dg-fontsize-btn:disabled { opacity: 0.4; cursor: not-allowed; }
#dg-fontsize-ctrl .dg-fontsize-btn:disabled:hover { background: var(--dg-surface); color: var(--dg-text-2); }
#dg-fontsize-ctrl .dg-fontsize-val {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--dg-font);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--dg-text-2);
    border-left: 1px solid var(--dg-border);
    border-right: 1px solid var(--dg-border);
}

/* ============================================================================
   Область поиска — раскрывающийся список с галочками
   Восемь переключателей подряд занимали пол-экрана и открывались на каждый запрос. Переключатель
   вообще про «включить режим»; здесь же выбирают из набора, где обычно отмечено почти всё, —
   а это галочки. Свёрнутая строка показывает выбранное («DN, MN, SN, AN, KN»), и чаще всего
   разворачивать не приходится вовсе.
   ============================================================================ */
.dg-scope {
    margin: 8px 0 2px;
    border: 1px solid var(--dg-border);
    border-radius: var(--dg-radius);
    background: var(--dg-surface);
    overflow: hidden;
}
.dg-scope-group + .dg-scope-group { border-top: 1px solid var(--dg-border); }

/* Строка группы: галка, название, счётчик «сколько из скольких», кнопка раскрытия. Счётчик тут
   вместо перечисления — он и сообщает, выбрана группа целиком, частично или вовсе нет. */
.dg-scope-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 12px;
    font-family: var(--dg-font);
    font-size: 0.92rem;
    color: var(--dg-text);
}
/* font-size: inherit — assets/css/extrastyles.css (legacy, shared) sets a global `label {
   font-size: 20px }` that otherwise wins over inheriting .dg-scope-head's 0.92rem, since an
   explicit rule on the element itself beats inheritance regardless of specificity. Same trap as
   .dg-check-row below, which already has its own font-size for the same reason. */
.dg-scope-label { flex: 1; min-width: 0; cursor: pointer; font-size: inherit; }
.dg-scope-count {
    flex: none;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    color: var(--dg-text-muted);
}
.dg-scope-group.dg-some .dg-scope-count { color: var(--dg-accent-ink); }
.dg-scope-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--dg-text-muted);
    cursor: pointer;
}
.dg-scope-toggle:hover { background: var(--dg-surface-hover); color: var(--dg-text); }
.dg-scope-chev { transition: transform 0.18s var(--dg-ease); }
.dg-scope-group.dg-open .dg-scope-chev { transform: rotate(180deg); }

/* Под-пункты с отступом — видно, что они принадлежат группе, а не идут с ней вровень. */
.dg-scope-list { padding: 0 12px 8px 34px; }
.dg-scope-list[hidden] { display: none; }

.dg-check-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 0;
    font-size: 0.92rem;
    color: var(--dg-text);
    cursor: pointer;
}
/* Галочка — родная, только перекрашенная в акцент: свои квадратики пришлось бы отдельно учить
   доступности (фокус, клавиатура, screen reader), а accent-color даёт всё это даром.
   Селектор с двумя классами и элементом — ответ на `label input[type="checkbox"] {display:none}`
   из assets/css/extrastyles.css (общий файл, его не трогаем). Из-за него галки под-пунктов, а они
   лежат ВНУТРИ <label>, не рисовались вовсе: была видна одна родительская, и список читался как
   набор простых строк. */
.dg-scope input.dg-check {
    display: inline-block;
    width: 18px;
    height: 18px;
    flex: none;
    margin: 0;
    accent-color: var(--dg-accent);
    cursor: pointer;
}

/* Диакритика: набрать ā/ṁ/ñ без своей раскладки. Символ уходит в позицию курсора, поле фокус
   не теряет — набор продолжается с того же места. */
.dg-diac {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 6px;
    margin-top: 8px;
}
.dg-diac button {
    padding: 8px 0;
    border: 1px solid var(--dg-border);
    border-radius: var(--dg-radius);
    background: var(--dg-surface);
    color: var(--dg-text);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
}
.dg-diac button:hover { background: var(--dg-surface-hover); border-color: var(--dg-border-strong); }

/* ============================================================================
   Боковое меню — выезжает СПРАВА, с той стороны, где стоит бургер: выезд слева от кнопки
   справа читался как чужое движение.
   ============================================================================ */
#dg-drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1084;
    background: rgba(20, 18, 10, 0.4);
    /* Bleeds the dimming color far past the actual viewport edges via box-shadow (paints extra
       area without touching layout/scroll at all) — a defensive backstop for mobile rubber-band
       overscroll, on top of the real fix below (body scroll lock + overscroll-behavior on the
       drawer itself): owner, live device, dragging the open drawer: "граница белая всё ещё
       торчит" (a white edge still pokes through). */
    box-shadow: 0 0 0 100vmax rgba(20, 18, 10, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
}
#dg-drawer-backdrop.show { opacity: 1; pointer-events: auto; }
#dg-drawer-backdrop[hidden] { display: none; }

#dg-drawer {
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 1085;
    display: flex;
    flex-direction: column;
    width: 82%;
    max-width: 320px;
    background: var(--dg-surface);
    color: var(--dg-text);
    font-family: var(--dg-font);
    border-left: 1px solid var(--dg-border-strong);
    box-shadow: -8px 0 30px rgba(0, 0, 0, 0.14);
    transform: translateX(100%);
    transition: transform 0.3s var(--dg-ease);
    overflow-y: auto;
    /* Real fix for the mobile "white edge" bug (see #dg-drawer-backdrop above): scrolling the
       drawer's own list to its end used to chain into scrolling the page BODY behind it (body
       scroll wasn't locked either — see body.dg-drawer-open below), and that body-level
       rubber-band bounce is what briefly shifted the fixed backdrop/drawer and revealed page
       background at an edge. contain stops the drawer's scroll from ever handing off to body. */
    overscroll-behavior: contain;
}
/* Locked while the drawer is open (openDrawer()/closeDrawer(), home.js) — the other half of the
   white-edge fix: with body itself unable to scroll/bounce, there's nothing left for the fixed
   backdrop/drawer to visually lag behind during a drag. */
body.dg-drawer-open {
    overflow: hidden;
}
/* apple-design audit: menu drawer was a flat opaque fill — no depth/material feel over the
   dimmed content behind it. Falls back to the solid fill above where backdrop-filter is
   unsupported. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    #dg-drawer {
        background: color-mix(in srgb, var(--dg-surface) 88%, transparent);
        -webkit-backdrop-filter: blur(20px) saturate(180%);
        backdrop-filter: blur(20px) saturate(180%);
    }
}
#dg-drawer.show { transform: translateX(0); }
#dg-drawer[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
    #dg-drawer, #dg-drawer-backdrop { transition: none; }
}

.dg-drawer-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 14px 12px 10px 16px;
    border-bottom: 1px solid var(--dg-border);
}
/* issue #5: owner ask — share/close must hug the drawer's right edge. .dg-brand-name's own
   flex:1 only grows within .dg-brand-link's OWN flex row (logo + name); .dg-brand-link itself
   was never a growing child of .dg-drawer-head, so it (and everything after it) just sat at its
   natural content width, leaving share/close stranded mid-row with empty space after them. */
.dg-drawer-head .dg-brand-link { flex: 1; min-width: 0; }
.dg-drawer-head .dg-brand-name { flex: 1; min-width: 0; }
.dg-drawer-body { padding: 8px 18px 24px; }
.dg-drawer-body .dg-group-title {
    /* Owner: main menu items must read bigger than their sub-items, not smaller — was 0.66rem
       against .dg-drawer-row's 0.95rem (below), backwards from the intended hierarchy. */
    font-size: 1.05rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--dg-text-muted);
    margin: 18px 0 2px;
}
.dg-drawer-body .dg-group-title:first-child { margin-top: 2px; }
/* issue #5: Язык/Тема/Размер шрифта — подпункты "Настроек" (dg-group-title выше в разметке),
   не отдельные секции того же уровня — были на .dg-group-title, читались равнозначно с
   MULTITOOL/SETTINGS (owner: "равнозначные, слишком большие"). Меньше и без uppercase/жирности. */
.dg-drawer-body .dg-drawer-subtitle {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--dg-text-2);
    margin: 14px 0 4px;
}
/* Without this the injected FontAwesome <svg> (paintDrawerIcons, "Language" row) renders at its
   raw intrinsic size — .dg-group-title's own .dg-row-ic rule doesn't match .dg-drawer-subtitle. */
.dg-drawer-body .dg-drawer-subtitle .dg-row-ic { width: 13px; height: 13px; flex: none; color: var(--dg-text-muted); }
/* Пункты меню — со значками: без них список ссылок читается сплошной серой простынёй, и глазом
   не за что зацепиться. Значки те же, что у плиток (Font Awesome, см. paintDrawerIcons). */
.dg-drawer-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 0;
    font-size: 0.95rem;
    color: var(--dg-text);
    text-decoration: none;
    border-bottom: 1px solid var(--dg-border);
}
.dg-drawer-row:last-child { border-bottom: none; }
.dg-drawer-row:hover { color: var(--dg-accent-ink); }
.dg-drawer-row .dg-row-ic {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--dg-text-muted);
}
.dg-drawer-row:hover .dg-row-ic { color: var(--dg-accent-ink); }
/* Горячая клавиша строки бургера — тот же вид, что у .dg-mode-row-hotkey выше и у строк меню
   словаря (ddg-ui): тихой моноширинной подписью справа. Ставится только там, где клавиша
   действительно что-то делает (owner: "хоткеи видно в бургере"). */
.dg-drawer-row .dg-drawer-hotkey {
    margin-left: auto;
    flex: none;
    padding-left: 10px;
    font-size: 0.7rem;
    color: var(--dg-text-muted);
    font-variant-numeric: tabular-nums;
}
/* Значок-картинка (ракушка у «Главной»). object-fit — иначе картинка растянется в квадрат и
   потеряет пропорции. Коробка РОВНО как у соседних svg (17px), иначе подпись «Главная» съезжает
   вправо относительно остальных строк (замерено: при коробке 22px — 1013px против 1008px у
   соседей, owner: "выбивается"). Крупнее соседей ракушка становится через transform, который
   на раскладку не влияет: её рисунок узкий и с большими полями по бокам (замерено по пикселям
   картинки: 117×188 краски в холсте 206×206), поэтому в общей коробке 17px она выходит заметно
   мельче круглых значков рядом. */
.dg-drawer-row .dg-row-ic-img { width: 17px; height: 17px; object-fit: contain; transform: scale(1.6); }
/* Значок у заголовка раздела — того же роста, что и сама подпись раздела. */
.dg-drawer-body .dg-group-title {
    display: flex;
    align-items: center;
    gap: 8px;
}
.dg-drawer-body .dg-group-title .dg-row-ic { width: 13px; height: 13px; flex: none; }

/* Сворачиваемый раздел меню (<details>, см. "Навигация" в search/index.html) — summary
   переиспользует .dg-group-title один в один, только добавляет кликабельность и свой
   индикатор вместо браузерного треугольника (тот не темизируется единообразно между
   движками). */
.dg-drawer-group summary.dg-group-title {
    cursor: pointer;
    list-style: none;
}
.dg-drawer-group summary.dg-group-title::-webkit-details-marker { display: none; }
.dg-drawer-group summary.dg-group-title::after {
    content: '';
    width: 8px;
    height: 8px;
    margin-left: auto;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}
.dg-drawer-group:not([open]) summary.dg-group-title::after { transform: rotate(-45deg); }
/* Folded: keep the same breathing room under the title as the section body would leave. */
.dg-drawer-group:not([open]) summary.dg-group-title { margin-bottom: 8px; }

/* Список режимов чтения в бургере — тот же паттерн, что у .dg-drawer-row, плюс вторая строка
   описания под подписью. Owner: "не нужны радио кнопки" — was a radio-style filled/empty
   circle per row; dropped, active row is just bold + accent color, same convention as an
   active nav item elsewhere in this file. */
.dg-mode-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 0;
    border-bottom: 1px solid var(--dg-border);
    cursor: pointer;
    background: none;
    border-left: none; border-right: none; border-top: none;
    width: 100%;
    text-align: left;
    color: var(--dg-text);
}
.dg-mode-row:last-child { border-bottom: none; }
.dg-mode-row:hover { color: var(--dg-accent-ink); }
.dg-mode-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: 0.95rem; }
.dg-mode-row-desc { font-size: 0.78rem; color: var(--dg-text-muted); }
/* Owner: "нужно чтобы это было видимо пользователю что есть горячие клавиши" — Alt+N next to
   the row it actually triggers (window.MODE_HOTKEY_DIGITS, settings.js). */
.dg-mode-row-hotkey {
    flex: none;
    font-size: 0.7rem;
    font-weight: 400;
    color: var(--dg-text-muted);
    font-variant-numeric: tabular-nums;
}
.dg-mode-row.active .dg-mode-row-top { color: var(--dg-accent-ink); font-weight: 600; }

/* ============================================================================
   Перетаскивание плиток
   Порядок хранится в localStorage.dgTileOrder и переживает перезагрузку. Реализация — на
   pointer-событиях, а не на HTML5 drag-and-drop: тот на мобильных браузерах не работает вовсе,
   а плитки нужны в первую очередь именно там.
   ============================================================================ */
/* Deliberately NOT touch-action:none, even though that is the usual drag-and-drop recipe: tiles
   cover most of the mobile home screen, and "none" would kill page scrolling from all of it. The
   finger drag is unblocked in JS instead, only once the drag actually starts — see the
   passive:false touchmove handler in wireTileDrag() (search/js/home.js). */
.dg-tile { touch-action: manipulation; }
/* Пока идёт перетаскивание — гасим переходы у соседей, иначе они «догоняют» палец, и целиться
   в позицию становится невозможно. */
body.dg-tiles-dragging .dg-tile { transition: none; }
body.dg-tiles-dragging { user-select: none; -webkit-user-select: none; }
.dg-tile.dg-dragging {
    position: fixed;
    z-index: 1090;
    margin: 0;
    pointer-events: none;
    opacity: 0.95;
    box-shadow: 0 10px 26px -8px rgba(0, 0, 0, 0.45);
    transform: scale(1.03);
}
/* Место, куда плитка встанет. Тот же размер, что у неё самой — сетка не перестраивается. */
.dg-tile-placeholder {
    border: 1px dashed var(--dg-border-strong);
    border-radius: 12px;
    background: var(--dg-surface-hover);
    opacity: 0.6;
}

/* z-index выше #dg-sheet-backdrop (1080, home.css) намеренно — owner: "кликая по иконкам
   мультитула, они бы переключались сразу... сейчас нужно два тапа, если открыто мегаменю: один
   уходит на закрытие активного, второй — на открытие другого". Причина — общая подложка шторок/
   мега-меню на z-index:1080 закрывает весь экран (pointer-events:auto, пока показана), в том
   числе плитки, которые сами по себе ниже неё; первый клик всегда попадал в подложку, а не в
   плитку под ней. Приподнимаем ТОЛЬКО саму кнопку (не весь #home-tiles) — клик по зазору между
   плитками по-прежнему бьёт в подложку и корректно закрывает открытое, а клик по самой плитке
   идёт напрямую в её обработчик (renderTiles() → runTile()), который сам переключает/закрывает
   через openMega()/openSheet() — тем же кликом, без второго тапа. */
.dg-tile { position: relative; z-index: 1081; }
/* That lift also keeps tiles out of the backdrop's shade: on the light theme they stayed bright
   white while the rest of the page darkened under an open sheet (owner). Same tint as
   #dg-sheet-backdrop, laid over each tile only while a shading backdrop shows — clicks still go
   to the tile (pointer-events: none), so the one-tap switching above keeps working. */
.dg-tile::after {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    background: rgba(20, 18, 10, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
}
body:has(#dg-sheet-backdrop.show:not(.dg-transparent)) .dg-tile::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .dg-tile::after { transition: none; } }
/* Полный стек z-index этой страницы (снизу вверх): 900 #dg-busy-indicator, 1080 #dg-sheet-
   backdrop, 1081 .dg-tile, 1082 #dgDlCard (офлайн-карточка загрузки, public/offline/
   offline-status.js — плитки ЗА ней, issue #25), 1083 .dg-sheet (мега-меню/настройки — поверх
   карточки), 1084 #dg-drawer-backdrop, 1085 #dg-drawer, 1086 autocomplete,
   1090 плитка во время drag. Bootstrap-модалка (#SearchResultHelp — "Помощь", вызывается через
   runTile()) была НИЖЕ всего этого — bootstrap 5 по умолчанию кладёт .modal-backdrop/.modal в
   районе 1050-1060, скроен под страницы БЕЗ своего конкурирующего оверлей-стека. Раньше не
   всплывало: до фикса .dg-tile выше двумя пунктами модалка открывалась только вторым кликом,
   когда мега/шторка/дровер уже гарантированно закрыты первым. Теперь модалку можно открыть, пока
   что-то из стека ещё видимо (та же причина, что и починенный runTile() ниже) — owner
   (скриншот): "плитки поверх Помощи, z-index". Модалка — единственная НАСТОЯЩАЯ модальная
   штора (блокирует весь остальной интерфейс), поэтому кладём её однозначно выше ЛЮБОГО пункта
   этого стека, а не подбираем число под текущий максимум (1090) — если стек когда-то вырастет
   ещё, модалка не должна снова оказываться потерянной под новым слоем. */
.modal-backdrop { z-index: 1095 !important; }
.modal { z-index: 1096 !important; }
/* Owner: "странное поведение — при хувере появляется крестик закрыть, случайно можно удалить
   мегаменю... давай уберём" — .dg-tile-remove (inline ✕, appeared on hover AND on drag-start,
   both easy to trigger by accident) removed entirely, both the CSS here and its creation in
   renderTiles() (search/js/home.js). Show/hide now lives ONLY in "Изменить кнопки"
   (openEditList(), same file) as an explicit checkbox per row — a deliberate action in a
   dedicated list, not a stray button that shows up mid-interaction. */

/* ============================================================================
   Плитки на широком экране — компактнее, но В ДВА РЯДА
   Все восемь в одну строку вытягивались через весь экран «колбасой»: подписи расходились так
   далеко друг от друга, что набор переставал читаться как набор. Четыре в ряд — привычная сетка
   значков, и восьмая плитка просто уходит во второй ряд.
   ============================================================================ */
/* ============================================================================
   Воздух на широком экране.
   Отступы, подобранные под телефон, на десктопе сбивают всё в кучу: вывеска, девиз, поле и
   плитки стоят одной плотной пачкой, хотя места вокруг полно. Растягиваем по вертикали именно
   здесь, а не в общих правилах: на телефоне эта же прибавка увела бы плитки за нижний край.
   ============================================================================ */
@media (min-width: 992px) {
    /* Reference keeps one geometry for the header/heading/field at every width (60px bar,
       38px above the H1, 620px field) — the old desktop-only enlargements of the band, the
       topbar padding, the field and its type are gone; only the gap before the tiles stays. */
    .dg-hero-inner { max-width: 760px; }
    #home-slides { margin-top: 46px; }
    #dg-footer { margin-top: 56px; }
}

/* (Desktop used to shrink the tiles to a 680px, 38px-disc grid here; the reference keeps one
   size for the tile grid at every width, so nothing to override anymore.) */

/* Owner: "инпут оказывался у верха страницы, расстояние... сужалось... мега меню открывалось
   максимально без скролла" — toggled by scrollForMega() (home.js) right before a mega tile opens
   (desktop-only, mega tiles only). Shrinks the two gaps ABOVE the tile row (hero-band's own
   bottom padding, then #home-pane's margin before the tiles) so the row sits higher, leaving
   more viewport height below it for the mega panel (placeMegaAnchored sizes it off that gap).
   Two classes outrank the plain "body.dg-state-home ..." rules above without !important. */
body.dg-mega-compact.dg-state-home #dg-hero-band { padding-bottom: 20px; }
body.dg-mega-compact.dg-state-home #home-pane { margin-top: 14px; }

/* ============================================================================
   Строки списка: звёздочка и «чипсы»
   ============================================================================ */
/* Звезда у важных пунктов ($iconimportant в легаси-меню + личные отметки поверх, см. isStarred()
   в home.js). Раньше рисовался знак ✦ — но ромбик на этом сайте уже занят: им помечены скрытые
   ссылки-якоря на цитаты (.quoteLink-start), и два разных смысла одним значком путали. Здесь
   настоящая звезда (контур fa-star).
   Стоит СЛЕВА, на месте обычного значка строки — и ТОГО ЖЕ размера, что .dg-row-icon (17px):
   раньше была мельче (12px) соседних значков строки, из-за чего звёздный пункт визуально терял
   вес, а не подчёркивал важность (просьба владельца — «как иконка ссылки»). Золотая, а не
   акцентным цветом темы — так же, как остальное «избранное» на сайте. */
.dg-sheet .dg-sheet-row .dg-row-star {
    width: 17px;
    height: 17px;
    flex: none;
    margin-top: 2px;
    color: #f39c12;
}

/* Группы, где подписи короткие и говорят сами за себя (ИИ, переводчики, коды изданий), рисуются
   не столбцом строк, а вплотную — «чипсами» в одну-две строки: четыре имени вроде Gemini или
   DeepSeek не заслуживают четырёх полноразмерных строк (просьба владельца). Задаётся в
   menu-links.json полем группы "layout": "chips". */
.dg-sheet .dg-chip-group {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 0 10px;
}
.dg-sheet .dg-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    border: 1px solid var(--dg-border);
    border-radius: 999px;
    background: var(--dg-surface);
    color: var(--dg-text);
    font-size: 0.8rem;
    text-decoration: none;
}
.dg-sheet .dg-chip:hover {
    border-color: var(--dg-accent);
    color: var(--dg-accent);
    background: var(--dg-accent-bg);
}
.dg-sheet .dg-chip .dg-row-star { margin-top: 0; width: 11px; height: 11px; }

/* ============================================================================
   «Интересные запросы» — перенос слайд-шоу с боевой главной

   Разметка повторяет index.php один-в-один (#carouselWithCaptions в <div class="max-w-450
   container-lg my-5">), и на проде у этой карусели НЕТ ни одного своего правила в CSS — всё
   оформление бутстраповское. Поэтому здесь только то, чего у Bootstrap нет: ширина колонки,
   поля под боковые стрелки и цвет значков этих стрелок. Ни рамки, ни подложки, ни своих кнопок
   в шапке — от них наш вариант и выглядел хуже оригинала.
   ============================================================================ */
/* Production-v4 redesign (docs/Home-standalone.html) restyles the block: an eyebrow row
   ("ПОДБОРКИ" left, "Показать все" right) over a bordered 880px card with the arrows inside it
   and pill dots under it. The Bootstrap carousel itself and the slide markup (h5/span/br/a) are
   untouched — only wrapped and restyled; owner: "не трогай ничего по слайд шоу". */
#home-slides { margin-top: 16px; } /* + the grid's own 10px bottom padding = reference 26px */
#home-slides[hidden] { display: none; }

.dg-slides {
    max-width: 880px;
    margin: 0 auto;
    font-family: var(--dg-font);
    text-align: center;
}

/* Small uppercase section label — shared by "Подборки" and "Как искать?" (reference h2). */
.dg-eyebrow {
    margin: 0;
    font-family: var(--dg-font);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--dg-text-muted);
}
.dg-slides-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 12px;
}

/* The card. position:relative so the arrows (absolute) center on the card, not on the whole
   carousel element that also holds the dots below the card. */
.dg-slides-box {
    position: relative;
    padding: 20px 12px 16px;
    border: 1px solid var(--dg-border);
    border-radius: 10px;
    background: var(--dg-surface);
}
/* Поля под боковые стрелки, чтобы длинный заголовок не заезжал под них. */
#dg-carousel .carousel-item { padding: 0 48px; }
#dg-carousel h5 {
    margin: 0 0 6px;
    font-size: 17px;
    font-weight: 600;
    line-height: 1.5;
    color: var(--dg-text);
}
/* Direct child only: the blurb text itself carries nested <span title="…"> hints (slides.json,
   e.g. "10", "11", "12" with sutta refs on hover) that must stay inline. */
#dg-carousel .carousel-item > span {
    display: block;
    margin: 0 auto;
    max-width: 46ch;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--dg-text-2);
    text-wrap: pretty;
}
#dg-carousel h5 { letter-spacing: -0.01em; }
/* Reference .track: one quick 0.32s slide on the site's own ease curve instead of Bootstrap's
   0.6s ease-in-out — Bootstrap just waits for transitionend, so overriding the transition on
   the items is enough. */
#dg-carousel .carousel-item { transition: transform 0.32s var(--dg-ease); }
/* The legacy slide markup has a <br> between the blurb and "Читать"; with the blurb now a block
   it only adds an empty line above the link. */
#dg-carousel .carousel-item br { display: none; }
#dg-carousel a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 12px;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--dg-accent-ink);
    text-decoration: none;
}
#dg-carousel a:hover { text-decoration: underline; }
#dg-carousel a .dg-slides-chev { display: block; }

/* Arrows: 34px round buttons pinned to the card's left/right edge, vertically centered
   (reference .arw). Bootstrap's own control is a full-height 15% strip with a white glyph
   meant for photos — resized here, glyph darkened via invert on the light theme. */
#dg-carousel .carousel-control-prev,
#dg-carousel .carousel-control-next {
    top: 50%;
    bottom: auto;
    width: 34px;
    height: 34px;
    transform: translateY(-50%);
    border-radius: 50%;
    opacity: 1;
}
#dg-carousel .carousel-control-prev { left: 12px; }
#dg-carousel .carousel-control-next { right: 12px; }
#dg-carousel .carousel-control-prev:hover,
#dg-carousel .carousel-control-next:hover { background: var(--dg-surface-hover); }
/* Thin angle glyph (FA angle-left/right, 14px, muted) inline in renderSlides() instead of
   Bootstrap's bold white chevron background image. */
#dg-carousel .carousel-control-prev,
#dg-carousel .carousel-control-next { color: var(--dg-text-muted); opacity: 1; }
#dg-carousel .dg-slides-arw { width: 9px; height: 14px; display: block; }

/* Dots under the card (reference: 6px circles, active one an 18×6 accent pill). Bootstrap's
   .carousel-indicators is absolute at the carousel's bottom edge — made static here so it sits
   below the card in flow; the buttons keep their data-bs-slide-to wiring. */
#dg-carousel .carousel-indicators {
    position: static;
    margin: 0;
    padding: 14px 0 0;
    justify-content: center;
    align-items: center;
    gap: 6px;
}
/* Dots taper off with distance from the active one (reference .pick .dots: data-d = distance,
   1 → 6px, 2 → 5px/0.8, 3 → 4px/0.6, 4+ → 3px/0.42) so a long list reads as a soft trail, not
   a row of eighteen equal dots. data-d is set by paintSlideDots() (home.js) on every slide. */
#dg-carousel .carousel-indicators [data-bs-target] {
    box-sizing: border-box;
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--dg-border-strong);
    opacity: 1;
    text-indent: 0;
    transition: width 0.22s var(--dg-ease), height 0.22s var(--dg-ease),
        background-color 0.22s var(--dg-ease), opacity 0.22s var(--dg-ease);
}
#dg-carousel .carousel-indicators [data-bs-target]:hover { background: var(--dg-accent-ink); }
#dg-carousel .carousel-indicators [data-d="2"] { width: 5px; height: 5px; opacity: 0.8; }
#dg-carousel .carousel-indicators [data-d="3"] { width: 4px; height: 4px; opacity: 0.6; }
#dg-carousel .carousel-indicators [data-d="4"] { width: 3px; height: 3px; opacity: 0.42; }
#dg-carousel .carousel-indicators .active {
    width: 18px;
    height: 6px;
    border-radius: 999px;
    background: var(--dg-accent);
    opacity: 1;
}

/* «Показать все» — внизу справа, приглушённой мелочью: как .text-end.mt-2 с .text-muted.small
   на проде.
   Отрицательный margin-top — owner: "показать все стоит слишком далеко от слайд-шоу, подними
   ссылку вверх". Причина отрыва: lockCarouselHeight() (home.js) фиксирует min-height карусели по
   САМОМУ ВЫСОКОМУ слайду, чтобы переключение не дёргало страницу — под коротким слайдом остаётся
   пустая полоса (замерено по всем 18 слайдам: от 2px под самым длинным до 88px под самым
   коротким), и ссылка висела под ней. Саму карусель НЕ трогаем (owner: "не трогай ничего по
   слайд шоу" — попытки двигать .carousel-item ломали анимацию Bootstrap и съезжала «Читать»),
   поднимаем только сам футер — он вне карусели. Наезда нет даже на самом длинном слайде:
   «Показать все» прижата вправо, а «Читать»/текст слайда отцентрованы — по горизонтали не
   пересекаются (проверено по всем слайдам). */
/* «Показать все» — now in the head row, right of the eyebrow (reference); the old footer under
   the carousel (and its mobile negative-margin lift) is gone with it. */
.dg-slides-all {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--dg-text-muted);
    font-family: var(--dg-font);
    font-size: 12.5px;
    cursor: pointer;
}
.dg-slides-all:hover { color: var(--dg-text-2); text-decoration: underline; }

/* Пункты в списке «показать все» (шторка). Стрелка справа — знак того, что строку можно открыть:
   без неё список читался справочником с описаниями, а не набором ссылок. */
.dg-sheet .dg-slide-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 0;
}
.dg-sheet .dg-slide-row-body { flex: 1; min-width: 0; }
.dg-sheet .dg-slide-go-ic { flex: none; color: var(--dg-text-muted); }
.dg-sheet .dg-slide-row:hover .dg-slide-go-ic { color: var(--dg-accent-ink); }
.dg-sheet .dg-slide-row .dg-slide-title {
    display: block;
    margin: 0 0 2px;
    font-size: 0.95rem;
    color: var(--dg-text);
    text-decoration: none;
}
.dg-sheet .dg-slide-row .dg-slide-title:hover { color: var(--dg-accent-ink); }
.dg-sheet .dg-slide-row .dg-slide-desc {
    margin: 0;
    font-size: 0.84rem;
    line-height: 1.45;
    color: var(--dg-text-2);
}
/* Подсказка "Чего-то не хватает?" внизу полного списка — перенос с multiTool.html. */
.dg-slides-contacts-note {
    margin: 14px 0 2px;
    padding-top: 12px;
    border-top: 1px solid var(--dg-border);
    font-size: 0.82rem;
    color: var(--dg-text-muted);
}
.dg-slides-contacts-note a { color: var(--dg-accent-ink); }

/* ============================================================================
   Форма «своя кнопка» (в шторке, вызывается из бокового меню)
   ============================================================================ */
.dg-add-form { padding: 6px 0 4px; }
.dg-field { display: block; margin-bottom: 14px; }
.dg-field-label {
    display: block;
    margin-bottom: 5px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--dg-text-2);
}
.dg-field-input {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--dg-border-strong);
    border-radius: var(--dg-radius);
    background: var(--dg-surface);
    color: var(--dg-text);
    font-family: var(--dg-font);
    font-size: 0.95rem;
}
.dg-field-input:focus {
    outline: none;
    border-color: var(--dg-accent);
    box-shadow: 0 0 0 3px var(--dg-accent-bg);
}
.dg-field-textarea { resize: vertical; min-height: 44px; font-family: var(--dg-font); }
.dg-field-hint {
    margin: -8px 0 14px;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--dg-text-muted);
}
.dg-field-error {
    margin: 10px 0 0;
    font-size: 0.82rem;
    color: #b3261e;
}
body.dark .dg-field-error { color: #ff8a80; }

/* Выбор значка — из готового набора. Свои картинки не грузим: пришлось бы думать про их
   хранение, размер и то, как они переживут смену темы. */
.dg-icon-pick {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 6px 0 4px;
}
.dg-icon-opt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--dg-border);
    border-radius: 50%;
    background: var(--dg-surface);
    color: var(--dg-text-2);
    cursor: pointer;
}
.dg-icon-opt svg { width: 18px; height: 18px; }
.dg-icon-opt:hover { border-color: var(--dg-border-strong); }
.dg-icon-opt.on {
    border-color: var(--dg-accent);
    background: var(--dg-accent-bg);
    color: var(--dg-accent);
}
.dg-add-submit {
    width: 100%;
    margin-top: 16px;
    padding: 12px;
    border: 0;
    border-radius: var(--dg-radius);
    background: var(--dg-accent);
    color: #fff;
    font-family: var(--dg-font);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
}
.dg-add-submit:hover { background: var(--dg-accent-dark); }
.dg-add-reset {
    width: 100%;
    margin-top: 10px;
    padding: 11px;
    border: 1px solid var(--dg-border-strong);
    border-radius: var(--dg-radius);
    background: transparent;
    color: var(--dg-text-2);
    font-family: var(--dg-font);
    font-size: 0.9rem;
    cursor: pointer;
}
.dg-add-reset:hover { color: var(--dg-text); border-color: var(--dg-text-muted); }

/* Свой значок — эмодзи. Красим ОДНИМ цветом с остальными значками: цветная картинка среди
   одноцветных контуров выбивается из ряда, а плитки должны читаться как один набор.
   Приём стандартный: обесцвечиваем эмодзи и закрашиваем текущим цветом через фон с обрезкой по
   тексту. Если браузер не умеет background-clip:text, останется обычное цветное эмодзи —
   значок при этом виден, просто не одноцветный. */
.dg-emoji-ic {
    display: inline-block;
    font-size: 20px;
    line-height: 1;
    font-style: normal;
    color: transparent;
    background-color: currentColor;
    background-image: none;
    -webkit-background-clip: text;
    background-clip: text;
    filter: grayscale(1) contrast(0);
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
    .dg-emoji-ic { color: inherit; background: none; filter: none; }
}
.dg-tile-ic .dg-emoji-ic { font-size: 22px; color: transparent; background-color: var(--dg-accent); }
.dg-edit-ic .dg-emoji-ic { font-size: 15px; background-color: var(--dg-text-muted); }

.dg-emoji-input { margin-top: 4px; }

/* Строка списка «изменить кнопки» — .dg-edit-row теперь просто <div> (общий .dg-sheet-row даёт
   flex/gap/padding/border-bottom), внутри — чекбокс показа (owner: "добавь чекбоксы, по
   умолчанию включенные, чтобы можно было скрыть" — заменяет крестик, всплывавший на самой
   плитке) и .dg-edit-row-main — настоящая кнопка, открывающая форму правки по клику где угодно
   в строке, кроме самого чекбокса (там его click — свой stopPropagation, home.js). */
.dg-sheet .dg-edit-visible-cb {
    flex: none;
    width: 17px;
    height: 17px;
    margin: 0;
    accent-color: var(--dg-accent);
    cursor: pointer;
}
.dg-sheet .dg-edit-row-main {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    font-family: var(--dg-font);
    color: inherit;
    text-align: left;
    cursor: pointer;
}
.dg-sheet .dg-edit-row-main .dg-edit-ic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ============================================================================
   Подсказки автодополнения (jQuery UI, autopali.js)
   Виджет приходит со своим оформлением jQuery UI — светлые уголки, свой шрифт, синяя подсветка.
   Рядом с новым полем это выглядело деталью с другого сайта. Приводим к виду самого поля: та же
   рамка, то же скругление, те же цвета и та же тень.
   ============================================================================ */
body.dg-skin-minimal .ui-autocomplete {
    /* Легаси-стили (extrastyles.css) зажимали список в 220px — ровно пять строк, сколько бы
       экрана под полем ни оставалось. Точную высоту ставит autopali.js в open: по реальному
       месту под полем; здесь — вменяемый потолок на случай, если тот ещё не отработал. */
    max-height: min(64vh, 560px);
    padding: 6px;
    border: 1px solid var(--dg-border-strong);
    border-radius: var(--dg-radius);
    background: var(--dg-surface);
    box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.35);
    font-family: var(--dg-font);
    font-size: 0.95rem;
    z-index: 1086;
}
/* Строку подсказки autopali.js рисует своим шаблоном: <li><div class="autopali-dropdown-item">
   (см. _renderItem в /assets/js/autopali.js), а jQuery UI вешает подсветку через .ui-state-active
   на обёртку. Красим оба варианта — какой именно окажется в разметке, зависит от версии виджета. */
body.dg-skin-minimal .ui-autocomplete .autopali-dropdown-item,
body.dg-skin-minimal .ui-autocomplete .ui-menu-item-wrapper {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--dg-text);
}
/* Owner: long compound Pali words (autopali.js's <span>item.label</span>, e.g. a long jātaka
   title) ran off the edge of the dropdown instead of wrapping — flex items default to
   min-width:auto, which keeps them at their content's natural (unwrapped) width no matter how
   narrow the flex container actually is. min-width:0 lets the span actually shrink to the row's
   width; overflow-wrap breaks the long word itself once it does, since it has no spaces to wrap
   on normally. */
body.dg-skin-minimal .ui-autocomplete .autopali-dropdown-item span,
body.dg-skin-minimal .ui-autocomplete .ui-menu-item-wrapper span {
    min-width: 0;
    overflow-wrap: anywhere;
}
body.dg-skin-minimal .ui-autocomplete .ui-state-active,
body.dg-skin-minimal .ui-autocomplete .ui-state-active .autopali-dropdown-item,
body.dg-skin-minimal .ui-autocomplete .autopali-dropdown-item:hover,
body.dg-skin-minimal .ui-autocomplete .ui-menu-item-wrapper.ui-state-active {
    margin: 0;
    border: 0;
    background: var(--dg-accent-bg);
    color: var(--dg-accent-ink);
}
/* Часы у строк из истории — приглушаем: это пометка, а не содержание подсказки. */
/* Значок часов у строк из истории — это <img> с тёмным SVG (autopali.js подставляет
   /assets/svg/clock-rotate-left.svg), а не иконочный шрифт: currentColor на него не действует, и
   в тёмной теме он сливался с фоном. Инвертируем картинку — другого способа перекрасить внешний
   SVG, вставленный через <img>, у CSS нет. */
body.dg-skin-minimal .ui-autocomplete .autocomplete-history-icon {
    width: 13px;
    height: 13px;
    flex: none;
    opacity: 0.55;
}
body.dark .ui-autocomplete .autocomplete-history-icon { filter: invert(1); opacity: 0.7; }

/* ============================================================================
   Подвал — виден всегда (мобильный браузер, десктоп, установленное PWA-приложение).
   Слева: ссылки на шторку «О проекте», копирайт, «Powered by»; справа — иконки контактов.
   ============================================================================ */
#dg-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    align-items: center;
    gap: 14px 24px;
    margin: 34px 0 6px;
    padding-top: 18px;
    border-top: 1px solid var(--dg-border);
    font-family: var(--dg-font);
    font-size: 0.78rem;
    color: var(--dg-text-muted);
    text-align: left;
}
#dg-footer p { margin: 0; }
/* На главной подвал держит ту же колонку, что цитата над ним (#home-howto), а не всю ширину окна. */
body.dg-state-home #dg-footer { max-width: 880px; margin: 34px auto 10px; padding-top: 20px; }
/* Две строки слева (ссылки; копирайт) — в 720px-колонку одна строка вместе с иконками контактов
   справа не влезает. */
.dg-footer-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.dg-footer-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.98rem;
    color: var(--dg-accent-ink);
}
.dg-footer-nav .dg-footer-nav-ic { flex: none; color: var(--dg-accent); }
/* body.dg-skin-minimal в селекторах — не для красоты: langswitch.css несёт голое
   `.dark a { color: rgb(122,122,249) }` (класс+тег), которое в тёмной теме перебивало эти правила
   и красило ссылки подвала/цитаты/шторки и иконки контактов в сине-фиолетовый (живой скрин). */
body.dg-skin-minimal .dg-footer-nav a, body.dg-skin-minimal .dg-footer-nav a:visited { color: var(--dg-accent-ink); text-decoration: none; }
body.dg-skin-minimal .dg-footer-nav a:hover { text-decoration: underline; }
body.dg-skin-minimal .dg-footer-link, body.dg-skin-minimal .dg-footer-link:visited { color: var(--dg-text-2); text-decoration: none; }
body.dg-skin-minimal .dg-footer-link:hover { color: var(--dg-accent-ink); text-decoration: underline; }
.dg-footer-contacts { flex: none; }
.dg-footer-contacts .dg-contact-btn { width: 36px; height: 36px; }
.dg-footer-contacts .dg-contact-btn svg { width: 15px; height: 15px; }
@media (max-width: 600px) {
    #dg-footer { flex-direction: column; }
    body.dg-state-results #dg-footer { padding-bottom: 96px; }
}
.dg-terms-text {
    margin: 8px 0 4px;
    font-size: 0.92rem;
    line-height: 1.6;
    color: var(--dg-text);
}
.dg-terms-text a { color: var(--dg-accent-ink); }

/* ============================================================================
   Короткая цитата (DN 16) + памятка о переводах в одну строку — низ главной.
   На широком экране всегда видно; на узком свёрнуто (главная и так длинная), раскрывается
   .dg-anchor-revealed из revealAnchorSection(), как и раньше.
   ============================================================================ */
/* Reference: 38px above the divider, 26px under it, the same 880px column as the tiles. */
#home-howto {
    max-width: 880px;
    margin: 38px auto 0;
    padding-top: 26px;
    border-top: 1px solid var(--dg-border);
    font-family: var(--dg-font);
}
#home-howto .dg-eyebrow { margin-bottom: 14px; }
body.dg-state-home #home-howto:not([hidden]) { display: block; }
@media (max-width: 991.98px) {
    body.dg-state-home #home-howto:not(.dg-anchor-revealed) { display: none; }
}
/* Reference .pali / body / ref: 17px italic, 14px body up to ~585px, 12px reference line. */
.dg-intro-pali {
    margin: 0 0 12px;
    font-style: italic;
    font-size: 17px;
    line-height: 1.55;
    color: var(--dg-text);
}
.dg-intro-body {
    margin: 0;
    max-width: 64ch;
    font-size: 14px;
    line-height: 1.6;
    color: var(--dg-text-2);
}
.dg-intro-ref { margin: 12px 0 22px; font-size: 12px; color: var(--dg-text-muted); }
body.dg-skin-minimal .dg-intro-ref a, body.dg-skin-minimal .dg-intro-ref a:visited { color: var(--dg-accent-ink); text-decoration: none; }
body.dg-skin-minimal .dg-intro-ref a:hover { text-decoration: underline; }
/* Памятка о переводах — зелёный блок со значком «i», как было на проде (только значок был
   треугольником). Общий для главной (#home-howto) и шторки «О проекте». */
.dg-howto-warn {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin: 0;
    padding: 16px 20px;
    border-radius: 12px;
    background: var(--dg-accent-bg);
    color: var(--dg-text);
    font-family: var(--dg-font);
}
.dg-howto-warn svg { flex: none; margin-top: 2px; color: var(--dg-accent-ink); }
.dg-howto-warn strong { display: block; font-size: 0.95rem; margin-bottom: 6px; }
.dg-howto-warn p {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--dg-text-2);
    white-space: pre-line;
}
/* Reference .warn on the home page: neutral surface + hairline (not the accent tint the About
   sheet's copy keeps), 15/17 padding, 13.5px/600 title with a 13px glyph, 13px body. */
#home-howto .dg-howto-warn {
    padding: 15px 17px;
    max-width: calc(64ch + 48px);
    gap: 8px;
    border: 1px solid var(--dg-border);
    border-radius: 10px;
    background: var(--dg-surface-hover);
}
#home-howto .dg-howto-warn svg { width: 13px; height: 13px; margin-top: 4px; }
#home-howto .dg-howto-warn strong { font-size: 13.5px; margin-bottom: 8px; }
#home-howto .dg-howto-warn p { font-size: 13px; line-height: 1.65; }

/* Шторка «О проекте» (home.js openAbout): форматирование макета — заголовки-подписи как у
   списков плиток (.dg-group-title), всё по левому краю, серая карточка памятки, круглые
   кнопки контактов; содержимое — полное, как на проде. */
.dg-about .dg-group-title { margin: 56px 0 18px; letter-spacing: 0.1em; }
.dg-about .dg-group-title:first-child { margin-top: 14px; }
.dg-about-pali {
    margin: 0 0 18px;
    font-style: italic;
    font-size: 1.25rem;
    line-height: 1.55;
    color: var(--dg-text);
}
.dg-about-body { margin: 0 0 14px; font-size: 1rem; line-height: 1.7; color: var(--dg-text-2); }
.dg-about-refs { margin: 0 0 28px; font-size: 0.9rem; color: var(--dg-text-muted); }
body.dg-skin-minimal .dg-about-refs a, body.dg-skin-minimal .dg-about-refs a:visited { color: var(--dg-accent-ink); text-decoration: none; }
body.dg-skin-minimal .dg-about-refs a:hover { text-decoration: underline; }
.dg-about-note { margin: 0 0 22px; font-size: 1rem; line-height: 1.7; color: var(--dg-text-2); }
.dg-about-powered {
    margin: 28px 0 0;
    font-family: var(--dg-font);
    font-size: 1rem;
    color: var(--dg-text-2);
}
.dg-about-foot {
    margin-top: 48px;
    padding-top: 20px;
    border-top: 1px solid var(--dg-border);
    font-size: 0.8rem;
    color: var(--dg-text-muted);
}

/* Кнопки приложений и контакты — общие для шторки. */
.dg-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    max-width: 820px;
}
.dg-cta-btn { display: inline-flex; line-height: 0; border-radius: 8px; }
.dg-cta-btn img { height: 44px; width: auto; display: block; border-radius: 8px; }
.dg-cta-btn:hover img { opacity: 0.85; }
.dg-contacts {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}
body.dg-skin-minimal .dg-contact-btn,
body.dg-skin-minimal .dg-contact-btn:visited {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--dg-border-strong);
    border-radius: 50%;
    color: var(--dg-text-2);
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.dg-contact-btn svg { width: 18px; height: 18px; }
body.dg-skin-minimal .dg-contact-btn:hover {
    background: var(--dg-accent-bg);
    border-color: var(--dg-accent);
    color: var(--dg-accent-ink);
}

/* apple-design audit — #pali/#pali-words carry DataTables' "responsive" class but the
   Responsive extension itself is never loaded, so it does nothing: columns keep their
   auto-calculated desktop widths and long words in the Title column get torn mid-word
   on narrow screens. Give Title room and let it wrap on spaces instead. Also reserve a
   bottom safe zone so the fixed Pāli/Eng toggle (bottom:30px, ~38-48px tall) never
   permanently covers the last table row. */
@media (max-width: 480px) {
    #pali td:nth-child(2),
    #pali-words td:nth-child(2) {
        word-break: normal;
        overflow-wrap: anywhere;
        min-width: calc(45vw / var(--dg-zoom, 1));
    }
    /* #search-pane specifically, not the bare .table-wrapper class — that class is ALSO reused
       (search/index.html:913, deliberately, for matching max-width/centering) by the page-wide
       header wrapper present in every state (home/results/reader/toc), so the un-scoped
       selector was adding this same 90px trailing gap after the search heading, after the
       reader's prev/next row, and after the TOC input — everywhere, not just after the results
       table it was meant for (owner: "бессмысленный отступ" in all three places). */
    #search-pane.table-wrapper {
        padding-bottom: 90px;
    }
}

/* Owner: "верхние ссылки и кнопки слишком широко... увеличение шрифта не должно влиять на
   расстояние между иконками и текстовыми ссылками в ридере и в других частях сайта" — the mobile
   html{font-size} bump above (--dg-mobile-scale) is meant for PROSE (headings, paragraphs, table
   cells, TOC entries); growing icon-button/toolbar-link CHROME too was collateral damage — bigger
   link/tab labels wrapped onto extra lines (.dg-reader-toolbar's DPR/BJT/Voice/… row, "TBW" bumped
   to its own line) and read as "spaced too far apart", even though the row's own gap/min-width
   were already fixed px and never moved. Each selector below divides its OWN normal rem size back
   by --dg-mobile-scale — not a flat 1rem/scale for all of them, that would make .dg-icon-btn (0.8rem)
   and .dg-tile (0.92rem) suddenly render at the SAME size as everything else instead of their
   usual distinct ones. Must be the LAST block in the file: same specificity as each selector's own
   rule earlier up top, and same-specificity CSS is decided by source order. */
@media (max-width: 767.98px) {
    .dg-icon-btn,
    #smart-toc-btn { font-size: calc(0.8rem / var(--dg-mobile-scale)); }
    .dg-tile,
    .dg-tile-label { font-size: calc(0.92rem / var(--dg-mobile-scale)); }
    p.sc-link a { font-size: calc(1.1rem / var(--dg-mobile-scale)); }
    .dg-reader-toolbar,
    .dg-reader-toolbar a,
    #results-toolbar,
    #reader-toolbar { font-size: calc(1rem / var(--dg-mobile-scale)); }
}

/* ============================================================================
   Мультитул в бургере (#dg-drawer-tiles, home.js renderDrawerTiles) — список плиток; значок
   плитки в той же 17px-коробке, что у остальных строк меню.
   ============================================================================ */
.dg-brand-link { display: flex; align-items: center; gap: inherit; color: inherit; text-decoration: none; min-width: 0; }
.dg-drawer-tile-ic { display: inline-flex; align-items: center; justify-content: center; }
.dg-drawer-tile-ic svg { width: 17px; height: 17px; color: var(--dg-text-muted); }
.dg-drawer-row:hover .dg-drawer-tile-ic svg { color: var(--dg-accent-ink); }

/* Значок «внешняя ссылка» у пунктов мультитула — owner: слишком громоздкий и навязчивый.
   Меньше подписи и приглушён, читается как пометка, а не как второй значок строки. */
.dg-sheet .dg-sheet-row .dg-row-icon,
#dg-mega .dg-sheet-row .dg-row-icon { width: 12px; height: 12px; margin-top: 5px; opacity: 0.45; }
.dg-sheet .dg-sheet-row:hover .dg-row-icon,
#dg-mega .dg-sheet-row:hover .dg-row-icon { opacity: 0.8; }
/* Bootstrap-тултипы (звёздочка «Powered by NI», состав области поиска) должны быть выше
   шторок/мегаменю/бургера (1081–1084) — иначе тултип внутри шторки рисовался под ней. */
.tooltip { z-index: 1200 !important; }

/* ============================================================================
   «О проекте» как нижняя шторка (production-v4 redesign, docs/Home-standalone.html .sheet):
   во всю ширину от нижнего края, ручка сверху, без заголовка-полосы (только ×), контент в
   колонке 660px. Замеры — с макета. Класс вешает openAbout() (home.js); остальные шторки
   (#dg-sheet для плиток, условия) остаются плавающей карточкой.
   ============================================================================ */
.dg-sheet.dg-about-sheet {
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    min-height: 0;
    max-height: 84vh;
    border: 0;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -10px 44px rgba(27, 29, 25, 0.16);
    transform: translateY(100%);
}
.dg-sheet.dg-about-sheet.show { transform: translateY(0); }
/* Wide screens: as wide as the page content (the hero column, 920px — same as .dg-wide), not the
   whole window (owner). The dimmed page stays visible at the sides, so a tap there closes the sheet
   like any other one. Phones keep the full-width bottom sheet. */
@media (min-width: 768px) {
    .dg-sheet.dg-about-sheet {
        left: 50%;
        right: auto;
        width: min(920px, calc(100vw / var(--dg-zoom, 1) - 32px));
        transform: translate(-50%, 100%);
    }
    .dg-sheet.dg-about-sheet.show { transform: translate(-50%, 0); }
}
.dg-sheet.dg-about-sheet .dg-sheet-handle {
    display: block;
    width: 38px;
    height: 4px;
    border-radius: 999px;
    margin: 6px auto 4px;
}
.dg-sheet.dg-about-sheet .dg-sheet-head {
    position: relative;
    max-width: 660px;
    width: 100%;
    margin: 0 auto;
    padding: 0;
    height: 0;
}
.dg-sheet.dg-about-sheet .dg-sheet-head h2 { display: none; }
.dg-sheet.dg-about-sheet .dg-sheet-close {
    position: absolute;
    top: 8px;
    right: -4px;
    z-index: 1;
    font-size: 15px;
    color: var(--dg-text-muted);
}
.dg-sheet.dg-about-sheet .dg-sheet-body.dg-about {
    max-width: 660px;
    width: 100%;
    margin: 0 auto;
    padding: 0 0 30px;
}
@media (max-width: 767.98px) {
    .dg-sheet.dg-about-sheet .dg-sheet-head,
    .dg-sheet.dg-about-sheet .dg-sheet-body.dg-about { padding-left: 18px; padding-right: 18px; }
    .dg-sheet.dg-about-sheet .dg-sheet-close { right: 14px; }
}
.dg-about-sheet .dg-about .dg-group-title { margin: 40px 0 13px; font-size: 10.5px; letter-spacing: 0.1em; }
.dg-about-sheet .dg-about .dg-group-title:first-child { margin-top: 14px; }
.dg-about-sheet .dg-about-pali { margin: 0; font-size: 15px; line-height: 1.55; font-style: italic; color: var(--dg-text); }
.dg-about-sheet .dg-about-body { margin: 9px 0 0; font-size: 13px; line-height: 1.6; color: var(--dg-text-2); }
.dg-about-sheet .dg-about-refs { margin: 11px 0 0; font-size: 11.5px; color: var(--dg-text-muted); }
.dg-about-sheet .dg-howto-warn {
    margin-top: 16px;
    padding: 15px 17px;
    gap: 8px;
    border: 1px solid var(--dg-border);
    border-radius: 10px;
    background: var(--dg-surface-hover);
}
.dg-about-sheet .dg-howto-warn svg { width: 13px; height: 13px; margin-top: 4px; }
.dg-about-sheet .dg-howto-warn strong { font-size: 13.5px; margin-bottom: 8px; }
.dg-about-sheet .dg-howto-warn p { font-size: 13px; line-height: 1.65; }
.dg-about-sheet .dg-cta { gap: 9px; }
.dg-about-sheet .dg-cta-btn img { height: 40px; }
.dg-about-sheet .dg-about-note { margin: 0 0 14px; font-size: 13.5px; line-height: 1.6; }
.dg-about-sheet .dg-about-powered { font-size: 13px; }
.dg-about-sheet .dg-about-foot { font-size: 12px; color: var(--dg-text-muted); }
/* The floating-card variant pins #contacts to the bottom with margin-top:auto (id rule above);
   in the bottom sheet the sections just flow with the same 40px gap as the other titles. */
.dg-sheet-body.dg-about #contacts { margin-top: 40px; }
.dg-about-sheet .dg-about .dg-cta { margin-bottom: 0; }

/* ============================================================================
   Phone field in results/reader/toc/404 (owner, 2026-09-06: "на мобильных инпут выглядит
   коряво"): everything inside the pill was competing for ~330px — 26px conch, separator,
   34px sliders, 32px glass. Tighter pill, smaller conch, no separator, 30px buttons, so the
   text keeps the room and nothing crowds the edges.
   ============================================================================ */
@media (max-width: 767.98px) {
    body.dg-state-results .dg-input-shell,
    body.dg-state-reader .dg-input-shell,
    body.dg-state-toc .dg-input-shell { padding: 4px 5px 4px 9px; gap: 2px; }
    body.dg-state-results .dg-shell-logo img,
    body.dg-state-toc .dg-shell-logo img { width: 22px; height: 22px; }
    body.dg-state-reader .dg-shell-toc svg { width: 18px; height: 18px; }
    body.dg-state-results .dg-shell-sep,
    body.dg-state-reader .dg-shell-sep,
    body.dg-state-toc .dg-shell-sep { display: none; }
    body.dg-state-results .dg-input-shell .dg-shell-btn,
    body.dg-state-reader .dg-input-shell .dg-shell-btn,
    body.dg-state-toc .dg-input-shell .dg-shell-btn,
    body.dg-state-results .dg-qs-btn,
    body.dg-state-reader .dg-qs-btn,
    body.dg-state-toc .dg-qs-btn { width: 30px; height: 30px; }
    body.dg-state-results #form #paliauto.searchinput,
    body.dg-state-reader #form #paliauto.searchinput,
    body.dg-state-toc #form #paliauto.searchinput { font-size: 16px; padding-left: 6px; }
    .hero-row { gap: 4px; }
}

/* ============================================================================
   Выдача (production-v4 redesign, docs/Fresults-standalone.html): тот же DataTable, только
   опрятнее — чипсы-настройки, заголовок 21px, одна строка управления, таблица без зебры с
   волосяными разделителями и капительной шапкой, синие ссылки/оранжевые совпадения (прод-цвета),
   раскрытая цитата на мягкой подложке. Только стили, разметка/скрипты выдачи не тронуты.
   ============================================================================ */
body.dg-skin-minimal {
    /* Link blue / match orange of the results & reader — the site's own production values
       (reader --blue, table.css --highligh-td-b), just named. */
    --dg-tblue: #3434be;
    --dg-match: #a8341c;
}
body.dg-skin-minimal.dark { --dg-tblue: #8f8fe8; --dg-match: #ff6b45; }
/* table.css pins * { font-family: sans-serif } — the results column is Lato like the rest. */
body.dg-state-results #results-toolbar, body.dg-state-results #results-toolbar *,
body.dg-state-results #dynamicHeader, body.dg-state-results #dynamicHeader *,
body.dg-state-results #search-pane, body.dg-state-results #search-pane * { font-family: var(--dg-font); }

/* ряд быстрых настроек — чипсы (reference .qs) */
body.dg-state-results #dg-toolbar-buttons { gap: 5px; padding: 9px 0 10px; border-bottom: 0; max-width: 880px; }
body.dg-state-results #results-toolbar .btn {
    border: 1px solid transparent;
    background: var(--dg-surface-hover);
    color: var(--dg-text-2);
    font-size: 12px;
    padding: 4px 11px;
    margin: 0 !important;
    line-height: 1.4;
}
body.dg-state-results #results-toolbar .btn:hover { border-color: var(--dg-border-strong); color: var(--dg-text); background: var(--dg-surface-hover); }
body.dg-state-results #results-toolbar .btn.active,
body.dg-state-results #results-toolbar .btn[aria-pressed="true"] { background: var(--dg-accent-bg); border-color: var(--dg-accent); color: var(--dg-icon-ink); }
/* кнопки-значки: круглые, без заливки (reference .qs .ic) */
body.dg-state-results #results-toolbar .toggle-dict-btn,
body.dg-state-results #results-toolbar .toggle-multiselect-btn,
body.dg-state-results #results-toolbar .toggle-mode-btn,
body.dg-state-results #results-toolbar #btn-read-marks,
body.dg-state-results #results-toolbar #helpMessage {
    width: 27px; height: 27px; padding: 0; border-radius: 50%; background: none;
    display: inline-flex; align-items: center; justify-content: center; color: var(--dg-text-muted);
}
body.dg-state-results #results-toolbar .toggle-dict-btn:hover,
body.dg-state-results #results-toolbar .toggle-multiselect-btn:hover,
body.dg-state-results #results-toolbar .toggle-mode-btn:hover,
body.dg-state-results #results-toolbar #btn-read-marks:hover,
body.dg-state-results #results-toolbar #helpMessage:hover { background: var(--dg-surface-hover); border-color: transparent; color: var(--dg-text); }
body.dg-state-results #results-toolbar .btn img, body.dg-state-results #results-toolbar .btn svg { width: 14px; height: 14px; }

/* заголовок выдачи (reference .rhead) */
body.dg-state-results .resultheader { max-width: 880px; margin: 0 auto; padding: 24px 0 18px; column-gap: 10px; }
body.dg-state-results .rh-keyword { font-size: 21px; font-weight: 600; letter-spacing: -0.01em; color: var(--dg-text); }
body.dg-state-results .rh-stats { font-size: 13px; color: var(--dg-text-muted); }
body.dg-state-results .resultheader .scope-info-star { font-size: 13px; color: var(--dg-text-muted); }
body.dg-state-results .resultheader #variants-hint { font-size: 13px; }
body.dg-state-results .resultheader #variants-hint a { color: var(--dg-tblue); }

/* строка управления DataTable (reference .dtbar) */
body.dg-state-results #search-pane { max-width: 880px; margin: 0 auto; padding-left: 0; padding-right: 0; }
body.dg-state-results #pali_wrapper > .row, body.dg-state-results #pali-words_wrapper > .row { align-items: center; row-gap: 6px; padding: 0 0 8px; font-size: 13px; color: var(--dg-text-2); }
body.dg-state-results #pali_wrapper .dt-length, body.dg-state-results #pali-words_wrapper .dt-length,
body.dg-state-results #pali_wrapper .dt-search, body.dg-state-results #pali-words_wrapper .dt-search { display: flex; align-items: center; gap: 7px; }
body.dg-state-results #pali_wrapper .dt-length select, body.dg-state-results #pali-words_wrapper .dt-length select,
body.dg-state-results #pali_wrapper .dt-search input, body.dg-state-results #pali-words_wrapper .dt-search input {
    border: 1px solid var(--dg-border-strong); background: var(--dg-surface); color: var(--dg-text);
    border-radius: 7px; font: inherit; font-size: 13px; padding: 5px 8px; box-shadow: none; width: auto;
}
body.dg-state-results #pali_wrapper .dt-length select, body.dg-state-results #pali-words_wrapper .dt-length select { padding-right: 24px; }
body.dg-state-results #pali_wrapper .dt-search input, body.dg-state-results #pali-words_wrapper .dt-search input { max-width: 190px; }
body.dg-state-results #pali_wrapper .dt-search input:focus, body.dg-state-results #pali-words_wrapper .dt-search input:focus { border-color: var(--dg-accent); box-shadow: 0 0 0 3px var(--dg-accent-bg); outline: 0; }
body.dg-state-results #pali_wrapper .dt-search label, body.dg-state-results #pali-words_wrapper .dt-search label { margin: 0; color: var(--dg-text-2); }
body.dg-state-results #pali_wrapper .dt-search .dg-filter-plus-btn, body.dg-state-results #pali-words_wrapper .dt-search .dg-filter-plus-btn { border: 0; border-radius: 7px; background: none; color: var(--dg-text-muted); }
body.dg-state-results #pali_wrapper .dt-search .dg-filter-plus-btn:hover, body.dg-state-results #pali-words_wrapper .dt-search .dg-filter-plus-btn:hover { background: var(--dg-surface-hover); color: var(--dg-text); }
body.dg-state-results #pali_wrapper .dt-search .dg-filter-plus-btn[aria-pressed="true"], body.dg-state-results #pali-words_wrapper .dt-search .dg-filter-plus-btn[aria-pressed="true"] { background: var(--dg-accent-bg); color: var(--dg-icon-ink); }
body.dg-state-results #pali_wrapper .dt-info, body.dg-state-results #pali-words_wrapper .dt-info { font-size: 12.5px; color: var(--dg-text-muted); padding: 0; }
body.dg-state-results #pali_wrapper .dt-paging .pagination, body.dg-state-results #pali-words_wrapper .dt-paging .pagination { gap: 2px; margin: 0; }
body.dg-state-results #pali_wrapper .dt-paging .page-link, body.dg-state-results #pali-words_wrapper .dt-paging .page-link {
    min-width: 29px; height: 29px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid transparent; border-radius: 7px; background: none; color: var(--dg-text-muted); font-size: 12.5px; box-shadow: none;
}
body.dg-state-results #pali_wrapper .dt-paging .page-link:hover, body.dg-state-results #pali-words_wrapper .dt-paging .page-link:hover { border-color: var(--dg-border-strong); background: var(--dg-surface); color: var(--dg-text); }
body.dg-state-results #pali_wrapper .dt-paging .page-item.active .page-link, body.dg-state-results #pali-words_wrapper .dt-paging .page-item.active .page-link { color: var(--dg-text); font-weight: 700; background: none; border-color: transparent; }
body.dg-state-results #pali_wrapper .dt-paging .page-item.disabled .page-link, body.dg-state-results #pali-words_wrapper .dt-paging .page-item.disabled .page-link { color: var(--dg-text-muted); opacity: 0.5; }

/* сама таблица (reference table.dt): без зебры, hairline между строками, hover-подсветка */
body.dg-state-results #search-pane table.dataTable {
    --bs-table-bg: transparent; --bs-table-striped-bg: transparent; --bs-table-color: var(--dg-text);
    --bs-table-hover-bg: var(--dg-surface-hover); --bs-table-hover-color: var(--dg-text);
    --bs-table-border-color: var(--dg-border);
    font-size: 14px; border-top: 1px solid var(--dg-border); margin-top: 6px;
}
body.dg-state-results #search-pane table.dataTable > thead > tr > th {
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--dg-text-muted);
    padding: 9px 10px; border-bottom: 1px solid var(--dg-border-strong); background: none; white-space: nowrap;
}
body.dg-state-results #search-pane table.dataTable > thead > tr > th:hover { color: var(--dg-text); }
body.dg-state-results #search-pane table.dataTable > tbody > tr > td { padding: 10px; border-bottom: 1px solid var(--dg-border); vertical-align: top; line-height: 1.45; }
body.dg-state-results #search-pane table.dataTable > tbody > tr.child > td { background: var(--dg-surface-hover); padding: 14px 16px 16px 24px; }
body.dg-state-results #search-pane table.dataTable td.dt-type-numeric, body.dg-state-results #search-pane table.dataTable th.dt-type-numeric { text-align: right; font-variant-numeric: tabular-nums; }
body.dg-state-results #search-pane a.mainLink { color: var(--dg-tblue); font-weight: 500; }
body.dg-state-results #search-pane a.mainLink:hover { text-decoration: underline; }
body.dg-state-results #search-pane .dg-title-pali { font-weight: 600; letter-spacing: -0.005em; color: var(--dg-text); }
body.dg-state-results #search-pane td .dg-title-lang.text-muted { color: var(--dg-text-muted) !important; }
body.dg-state-results #search-pane td .text-muted { color: var(--dg-text-2) !important; }
body.dg-state-results #search-pane b.match, body.dg-state-results #search-pane b { color: var(--dg-match); font-weight: 600; }
body.dg-state-results #search-pane a.mirror-link { font-size: 12.5px; padding: 1px 3px; border-radius: 4px; color: var(--dg-tblue); }
body.dg-state-results #search-pane a.mirror-link:hover { background: var(--dg-accent-bg); text-decoration: underline; }
/* раскрытая цитата (reference .cseg) */
body.dg-state-results #search-pane ul.dtr-details { max-width: 76ch; }
body.dg-state-results #search-pane ul.dtr-details > li { border: 0; padding: 0; }
body.dg-state-results #search-pane .quote-segment .pli-lang { font-size: 14.5px; line-height: 1.6; color: var(--dg-text); }
body.dg-state-results #search-pane .quote-segment .right-column .quote { font-size: 13.5px; line-height: 1.6; color: var(--dg-text-2) !important; font-weight: 400; }
/* ссылки под таблицей (reference .dtlinks) */
body.dg-state-results #search-pane .dt-buttons { gap: 3px; padding: 10px 0 40px; }
body.dg-state-results #search-pane .dt-buttons .btn {
    border: 0; background: none; box-shadow: none; font-size: 13px; color: var(--dg-tblue);
    padding: 4px 8px; border-radius: 6px; text-decoration: none;
}
body.dg-state-results #search-pane .dt-buttons .btn:hover { background: var(--dg-accent-bg); text-decoration: underline; color: var(--dg-tblue); }
/* угол: стрелка "наверх" вплотную к кнопке языка (reference .corner gap 5px); сама кнопка языка
   и её цвета/прозрачность — как были (owner). */
body #scrollToTopBtn { right: 121px; }
@media (max-width: 767.98px) {
    body.dg-state-results #search-pane table.dataTable > tbody > tr > td,
    body.dg-state-results #search-pane table.dataTable > thead > tr > th { padding: 9px 7px; }
    body.dg-state-results #search-pane table.dataTable > tbody > tr.child > td { padding: 12px 10px 14px 14px; }
    body.dg-state-results .resultheader { padding: 16px 0 12px; }
}
/* --- results skin, round 2 --- */
/* zebra: legacy/bootstrap striping sets the row background per nth-child — kill it at the cell
   level (reference: no stripes, hairlines + hover only) */
body.dg-state-results #search-pane table.dataTable > tbody > tr > * { --bs-table-bg-type: transparent; --bs-table-color-type: inherit; background-color: transparent; box-shadow: none; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):hover > * { background-color: var(--dg-surface-hover); }
/* control row: 13px labels (legacy label sizing pushed them to ~18px), one line on desktop */
body.dg-state-results #pali_wrapper label, body.dg-state-results #pali-words_wrapper label { font-size: 13px; margin: 0; color: var(--dg-text-2); font-weight: 400; }
@media (min-width: 768px) {
body.dg-state-results #pali_wrapper .dt-search, body.dg-state-results #pali-words_wrapper .dt-search { flex-wrap: nowrap; justify-content: flex-end; margin-bottom: 0; }
body.dg-state-results #pali_wrapper .dt-paging, body.dg-state-results #pali-words_wrapper .dt-paging { display: flex; justify-content: center; }
body.dg-state-results #pali_wrapper > .row:first-of-type > .col-md-5, body.dg-state-results #pali-words_wrapper > .row:first-of-type > .col-md-5 { display: flex; justify-content: center; }
}
body.dg-state-results #pali_wrapper .dt-length select, body.dg-state-results #pali-words_wrapper .dt-length select { min-width: 64px; }
/* search shell on results/reader/toc (reference .shell): neutral pill, round bordered sliders and
   search buttons, conch 20px — replaces the old gray/#42426a field. */
body.dg-state-results .dg-input-shell, body.dg-state-reader .dg-input-shell, body.dg-state-toc .dg-input-shell {
    background: var(--dg-surface-hover); border-color: var(--dg-border); padding: 5px 6px 5px 14px; gap: 6px;
}
/* Dark: the filled #42426a shell from production stays (rule above) — owner: "с заливкой и стильнее". */
body.dg-state-results .dg-input-shell:focus-within, body.dg-state-reader .dg-input-shell:focus-within, body.dg-state-toc .dg-input-shell:focus-within,
body.dark.dg-state-results .dg-input-shell:focus-within, body.dark.dg-state-reader .dg-input-shell:focus-within, body.dark.dg-state-toc .dg-input-shell:focus-within { border-color: var(--dg-accent); box-shadow: 0 0 0 3px var(--dg-accent-bg); }
body.dg-state-results .dg-shell-logo img, body.dg-state-toc .dg-shell-logo img { width: 20px; height: 20px; opacity: 0.85; }
body.dg-state-reader .dg-shell-toc svg { width: 17px; height: 17px; opacity: 0.85; }
body.dg-state-results #form #paliauto.searchinput, body.dg-state-reader #form #paliauto.searchinput, body.dg-state-toc #form #paliauto.searchinput,
body.dark.dg-state-results #form #paliauto.searchinput, body.dark.dg-state-reader #form #paliauto.searchinput, body.dark.dg-state-toc #form #paliauto.searchinput { color: var(--dg-text); font-family: var(--dg-font); font-size: 16px; }
body.dg-state-results .dg-input-shell .dg-shell-btn, body.dg-state-reader .dg-input-shell .dg-shell-btn, body.dg-state-toc .dg-input-shell .dg-shell-btn { color: var(--dg-text-muted); }
body.dg-state-results .dg-shell-sep, body.dg-state-reader .dg-shell-sep, body.dg-state-toc .dg-shell-sep { display: none; }
body.dg-state-results .dg-qs-btn, body.dg-state-reader .dg-qs-btn, body.dg-state-toc .dg-qs-btn,
body.dg-state-results .dg-shell-go, body.dg-state-reader .dg-shell-go, body.dg-state-toc .dg-shell-go {
    width: 34px; height: 34px; border: 1px solid var(--dg-border-strong); background: var(--dg-surface); color: var(--dg-text-2); --dg-qs-bg: var(--dg-surface); --dg-qs-fg: var(--dg-text-2);
    transition: border-color .15s var(--dg-ease), color .15s var(--dg-ease);
}
body.dg-state-results .dg-qs-btn:hover, body.dg-state-reader .dg-qs-btn:hover, body.dg-state-toc .dg-qs-btn:hover,
body.dg-state-results .dg-shell-go:hover, body.dg-state-reader .dg-shell-go:hover, body.dg-state-toc .dg-shell-go:hover { border-color: var(--dg-accent); color: var(--dg-accent-ink); background: var(--dg-surface); --dg-qs-bg: var(--dg-surface); --dg-qs-fg: var(--dg-accent-ink); }
@media (max-width: 767.98px) {
    body.dg-state-results .dg-input-shell, body.dg-state-reader .dg-input-shell, body.dg-state-toc .dg-input-shell { padding: 4px 5px 4px 10px; gap: 4px; }
    body.dg-state-results .dg-qs-btn, body.dg-state-reader .dg-qs-btn, body.dg-state-toc .dg-qs-btn,
    body.dg-state-results .dg-shell-go, body.dg-state-reader .dg-shell-go, body.dg-state-toc .dg-shell-go { width: 30px; height: 30px; }
}

/* ============================================================================
   Ридер (production-v4 redesign, docs/design-system/.../G-reader.html): та же разметка
   megareader.js, только типографика/отступы по макету — колонка 45rem, пали 15.5px, перевод
   14.5px приглушённо, тулбар ссылок/значков, prev/next, заметка, футер: источники → prev/next
   → инструменты → права. Угол: озвучка, «наверх», пилюля языков (цвета — прежней кнопки языка).
   ============================================================================ */
body.dg-state-reader #reader-pane, body.dg-state-reader #reader-pane * { font-family: var(--dg-font); }
body.dg-state-reader #reader-toolbar .sc-link a, body.dg-state-reader #top-links-container .sc-link a, body.dg-state-reader #bottom-links-container .sc-link a {
    font-size: 13px; padding: 3px 6px; border-radius: 6px; color: var(--dg-tblue); text-decoration: none; white-space: nowrap;
}
body.dg-state-reader #reader-toolbar .sc-link a:hover, body.dg-state-reader #bottom-links-container .sc-link a:hover { background: var(--dg-accent-bg); }
body.dg-state-reader #reader-toolbar > a, body.dg-state-reader #reader-toolbar > button:not(#smart-toc-btn) {
    width: 29px; height: 29px; border-radius: 7px; display: inline-flex; align-items: center; justify-content: center; color: var(--dg-text-muted);
}
body.dg-state-reader #reader-toolbar > a:hover { background: var(--dg-surface-hover); color: var(--dg-text); }
body.dg-state-reader #smart-toc-btn {
    border: 1px solid var(--dg-border); background: var(--dg-surface); border-radius: 999px; font-size: 12.5px; color: var(--dg-text-2); padding: 4px 11px; max-width: 170px; flex: 0 1 auto; min-width: 0;
}
@media (max-width: 767.98px) { body.dg-state-reader #smart-toc-btn { max-width: 96px; padding: 4px 8px; } }
body.dg-state-reader #smart-toc-btn:hover { border-color: var(--dg-border-strong); color: var(--dg-text); }
body.dg-state-reader #reader-pane .navigation { font-size: 13px; padding: 2px 0 11px; }
body.dg-state-reader #reader-pane .navigation a { color: var(--dg-tblue); display: inline-flex; align-items: center; gap: 6px; }
body.dg-state-reader #reader-pane .navigation a:hover { text-decoration: underline; }
body.dg-state-reader #navigation { border-bottom: 1px solid var(--dg-border); }
body.dg-state-reader #navigation-bottom { border-top: 1px solid var(--dg-border); padding-top: 12px; max-width: 45rem; margin: 0 auto; }
body.dg-state-reader .warning-container p.warning { margin: 14px auto 0; max-width: 60ch; text-align: center; font-size: 13px; line-height: 1.55; color: var(--dg-match); }
body.dg-state-reader .warning-container p.warning a { color: inherit; }
body.dg-state-reader .warning-container .close-warning { color: var(--dg-match); padding-left: 4px; cursor: pointer; }
body.dg-state-reader #sutta { max-width: 45rem; margin: 0 auto; padding-bottom: 40px; }
/* issue #5: reader/css/uiextra.css's own #sutta.column-view{max-width:105rem} (ID+class,
   specificity 110) is meant to widen column (2-language side-by-side) mode on desktop — but this
   SPA-scoped rule right above it is body.dg-state-reader #sutta (element+class+ID, specificity
   111) and always won regardless, so column mode never actually got wider than single-column
   (owner: "делает на одну ширину и получается очень узко", screenshot showed a huge empty right
   half at 1920px). Same body.dg-state-reader prefix, +.column-view for the matching bump. */
body.dg-state-reader #sutta.column-view { max-width: 105rem; }
body.dg-state-reader #sutta header { margin: 22px auto 0; text-align: center; }
body.dg-state-reader #sutta header ul { list-style: none; padding: 0; margin: 0; }
body.dg-state-reader #sutta header li.division .pli-lang { font-size: 15px; color: var(--dg-text); }
body.dg-state-reader #sutta header li.division .right-column .quote { font-size: 13.5px; color: var(--dg-text-muted); }
body.dg-state-reader #sutta h1 .pli-lang { font-size: 28px; font-weight: 700; letter-spacing: -0.015em; color: var(--dg-text); }
body.dg-state-reader #sutta h1 .right-column .quote { font-size: 21px; font-weight: 600; color: var(--dg-text-2); letter-spacing: -0.01em; }
body.dg-state-reader #sutta h2 { margin: 26px 0 14px; }
/* Owner: "ИИ сделал пример с мокапа основным" — this used to hardcode var(--dg-match) (the
   search-keyword highlight color) + an accent-bg pill on EVERY h2 (every chapter heading in the
   whole reader), permanently looking "highlighted/matched". That look was only ever meant to
   demo the reader's real match/active-word highlighting (body.dg-state-reader #sutta b.match,
   .finder below) — a plain heading with no active word/search match should read like h1 above. */
body.dg-state-reader #sutta h2 .pli-lang { font-size: 19px; font-weight: 700; color: var(--dg-text); }
body.dg-state-reader #sutta h2 .right-column .quote { font-size: 18px; font-weight: 600; color: var(--dg-text-2); }
body.dg-state-reader #sutta p .pli-lang { font-size: 15.5px; line-height: 1.62; color: var(--dg-text); }
body.dg-state-reader #sutta p .right-column .quote, body.dg-state-reader #sutta .lang-2nd { font-size: 14.5px; line-height: 1.62; color: var(--dg-text-2); }
body.dg-state-reader #sutta b.match, body.dg-state-reader #sutta .finder { color: var(--dg-match); font-weight: 600; }
body.dg-state-reader #bottom-links-container { max-width: 45rem; margin: 0 auto; }
body.dg-state-reader #bottom-links-container .sc-link { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px; padding: 6px 0 14px; margin: 0; }
body.dg-state-reader #bottom-links-container .sc-link a { font-size: 14px; padding: 3px 7px; }
body.dg-state-reader #reader-pane .links-area { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; padding: 18px 0 6px; }
body.dg-state-reader #reader-pane .links-area a { width: 36px; height: 36px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; }
body.dg-state-reader #reader-pane .links-area a:hover { background: var(--dg-surface-hover); }
body.dg-state-reader #reader-pane > hr { display: none; }

/* --- corner: TTS · up · language pill. Pill colors = the old #language-button (owner). --- */
body.dg-state-reader #language-button { display: none !important; }
.dg-lpill {
    position: fixed; right: 20px; bottom: 30px; z-index: 100;
    display: flex; align-items: center; gap: 3px; padding: 2px; height: 38px; box-sizing: border-box;
    background: rgb(221, 221, 221); border: 2px solid #5a5a5a; border-radius: 32px;
    color: rgb(4, 1, 19); opacity: 0.8; font-family: var(--dg-font);
    transition: opacity 0.2s ease, background-color 0.2s ease, transform 0.2s ease;
}
.dg-lpill[hidden], body:not(.dg-state-reader):not(.dg-state-results) .dg-lpill, body.dg-busy .dg-lpill { display: none; } /* reader + results corner control */
body.dg-state-results #language-button { display: none !important; }
/* Owner: "ошибка юзера/ошибка тех - не нужна кнопка" — dg-state-ai (ai-search.js: load/empty/
   error inside #ai-pane) was never added when the rules above were written, so this legacy dead
   button (its own comment: does nothing on the results LISTING, only ever wired up in the reader)
   defaulted back to visible there instead of hidden like its reader/results siblings above. */
body.dg-state-ai #language-button { display: none !important; }
.dg-lpill:hover { opacity: 1; }
.dg-lpill button { border: 0; background: none; color: inherit; font: inherit; font-size: 13px; line-height: 1; padding: 0 9px; height: 30px; border-radius: 30px; cursor: pointer; opacity: 0.6; transition: background-color .15s ease, opacity .15s ease; }
/* Owner: the lit segment must read as "on" without hovering (translucent blue), and hover
   only reacts on the lit segment — the others get no hover at all. */
.dg-lpill button[aria-pressed="true"] { opacity: 1; background: rgba(52, 52, 190, 0.55); color: #fff; font-weight: 600; }
.dg-lpill button[aria-pressed="true"]:hover { background: #3434be; }
.dg-lpill .dg-lpill-more { width: 26px; padding: 5px 0; display: grid; place-items: center; opacity: 0.7; }
.dg-lpill .dg-lpill-more:hover { opacity: 1; }
.dg-lpill .dg-dots { display: grid; grid-template-columns: repeat(3, 2.5px); grid-auto-rows: 2.5px; gap: 2.5px; }
.dg-lpill .dg-dots i { display: block; width: 2.5px; height: 2.5px; border-radius: 50%; background: currentColor; }
body.dark .dg-lpill { background: #42426a; color: rgb(221, 221, 221); }
body.dark .dg-lpill button[aria-pressed="true"] { background: rgba(80, 80, 230, 0.6); }
body.dark .dg-lpill button[aria-pressed="true"]:hover { background: #5050f0; }
/* bottom stays 30px, same as #scrollToTopBtn (search/index.html) and .dynamic-tts-btn
   (reader/css/uiextra.css) — neither has its own mobile override, so a different bottom here
   used to drop this pill visibly below its two corner-cluster neighbors on mobile. */
@media (max-width: 767.98px) { .dg-lpill { right: 12px; bottom: 30px; } .dg-lpill button { font-size: 12.5px; padding: 0 8px; } }
/* Owner: on wide/large screens the pill (and, via placeScrollTopButton()/repositionTtsButton(),
   the "to top" arrow + the TTS play button, which both measure THIS element's live rect and
   follow it — see search/index.html and settings.js) sat glued to the browser's right edge, far
   from the reading column, which is centered and capped at 45rem (reader #sutta) / 880px
   (results #search-pane) — see body.dg-state-reader #sutta / body.dg-state-results #search-pane
   below. Pull it in to hug that column's right edge instead once there's room to (min-width
   768px keeps mobile's own right:12px above untouched — the calc() term is negative there
   anyway). 200px reserved ≈ worst-case pill width (two language buttons + the six-dot "more"
   button) so it doesn't crowd the text on the largest realistic pill. max() means this only ever
   pulls the pill INWARD from its normal 20px, never further out. */
@media (min-width: 768px) {
    body.dg-state-reader .dg-lpill { right: max(20px, calc((100vw - 45rem) / 2 - 200px)); }
    body.dg-state-results .dg-lpill { right: max(20px, calc((100vw - 880px) / 2 - 200px)); }
    /* issue #5: column-view (#sutta.column-view, max-width 105rem — see body.dg-state-reader
       #sutta.column-view above) widens the reading column a lot on large screens; the formula
       above still assumed the narrow 45rem column, so the pill it "hugs" ended up sitting ON TOP
       of the now much wider text instead of beside it (owner: "получается над текстом"). Higher
       specificity than the plain body.dg-state-reader rule above (extra :has()), same formula
       with 105rem swapped in. */
    body.dg-state-reader:has(#sutta.column-view) .dg-lpill { right: max(20px, calc((100vw - 105rem) / 2 - 200px)); }
}

/* "Языки перевода" popover — the pill's six-dot button (production-v4 mock,
   docs/Fresults-standalone.html: .langmenu/.lrow). STAGE 1 UI only, see the "без логики"
   comment in home.js (dgToggleLangMenu) — this is just the shell: hover-reveal "сделать
   основным" + a static tag on the current main row, not wired to the reader yet.
   Uses the app's own surface/border/accent tokens (design-system, always in scope — see
   body.dg-skin-minimal below), not the mockup's literal colors: it sits right above the
   legacy-styled .dg-lpill on purpose (same modern-card look as #dg-quick-btn's own sheet). */
.dg-lpmenu {
    position: fixed; right: 20px; bottom: 76px; z-index: 101;
    min-width: 210px; max-width: 290px; padding: 6px;
    /* Translator lists can make this tall (26 Russian translators exist for some texts) — scroll
       inside the popover instead of growing past the viewport. */
    max-height: min(70vh, 460px); overflow-y: auto;
    background: var(--dg-surface); border: 1px solid var(--dg-border); border-radius: 12px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .18); font-family: var(--dg-font);
}
.dg-lpmenu[hidden] { display: none; }
.dg-lpmenu-title { padding: 6px 8px 4px; font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--dg-text-muted); }
.dg-lpmenu-row { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 8px; cursor: pointer; }
.dg-lpmenu-row:hover { background: var(--dg-surface-hover); }
.dg-lpmenu-row input.dg-check { width: 16px; height: 16px; flex: none; margin: 0; accent-color: var(--dg-accent); cursor: pointer; }
.dg-lpmenu-name { margin-right: auto; font-size: 13.5px; color: var(--dg-text); }
.dg-lpmenu-tag { display: none; font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: var(--dg-accent); padding: 2px 6px; border-radius: 5px; }
.dg-lpmenu-row.is-main .dg-lpmenu-tag { display: inline-block; }
.dg-lpmenu-pin { border: 0; background: none; font: inherit; font-size: 10.5px; color: var(--dg-text-muted); padding: 3px 6px; border-radius: 5px; opacity: 0; transition: opacity .15s ease; }
.dg-lpmenu-row:hover .dg-lpmenu-pin { opacity: 1; }
.dg-lpmenu-pin:hover { background: var(--dg-border); color: var(--dg-text); }
.dg-lpmenu-row.is-main .dg-lpmenu-pin { display: none; }
@media (max-width: 767.98px) { .dg-lpmenu { right: 12px; bottom: 58px; } }
/* A language this text has no translation in (READER_MODE.availableLangs, from /api/text). */
.dg-lpmenu-row.is-missing { opacity: .55; }
.dg-lpmenu-row.is-missing .dg-lpmenu-pin { display: none; }
.dg-lpmenu-missing { display: none; font-size: 10.5px; color: var(--dg-text-muted); }
.dg-lpmenu-row.is-missing .dg-lpmenu-missing { display: inline; }


/* Byline: only the main translator shows, the rest folds under "*" (megareader.js
   translatorByline; toggle handler in home.js). */
.dg-trn-star { border: 0; background: none; color: var(--dg-accent-ink); font: inherit; font-weight: 700; font-size: .9em; line-height: 1; padding: 0 5px; cursor: pointer; vertical-align: super; }
.dg-trn-star:hover, .dg-trn-star[aria-expanded="true"] { color: var(--dg-text); }
.dg-trn-rest:not([hidden]) { display: block; }


/* ============================================================================
   TOC — шрифты и фильтр переводчиков по макету (.tocsec/.tocitem/.trfilter), логика прежняя.
   ============================================================================ */
body.dg-state-toc #toc-pane, body.dg-state-toc #toc-pane * { font-family: var(--dg-font); }
body.dg-state-toc .toc-book-header { font-size: 15px; font-weight: 500; color: var(--dg-accent-ink); }
body.dg-state-toc .toc-count { font-size: 13px; color: var(--dg-text-muted); font-weight: 400; }
body.dg-state-toc .toc-aside { border: 1px solid var(--dg-border); border-radius: 12px; padding: 14px 15px; background: var(--dg-surface); }
body.dg-state-toc .toc-aside-title { font-size: 14px; font-weight: 600; color: var(--dg-text); }
body.dg-state-toc .toc-filter-search { border: 1px solid var(--dg-border-strong); background: var(--dg-page); border-radius: 8px; font-size: 13px; padding: 7px 9px; color: var(--dg-text); margin: 0 0 12px; }
body.dg-state-toc .toc-filter-search:focus { outline: 0; border-color: var(--dg-accent); box-shadow: 0 0 0 3px var(--dg-accent-bg); }
body.dg-state-toc .toc-filter-title { font-size: 13.5px; font-weight: 600; color: var(--dg-text); }
body.dg-state-toc .toc-filter-item { font-size: 12.5px; line-height: 1.45; color: var(--dg-text-2); padding: 4px 0; }
body.dg-state-toc .toc-filter-checkbox { accent-color: var(--dg-accent); width: 14px; height: 14px; }
body.dg-state-toc .toc-filter-more, body.dg-state-toc .toc-filter-reset a { font-size: 12.5px; color: var(--dg-accent-ink); }
body.dg-state-toc .toc-filter-patimokkha.dg-toggle-row { font-size: 12.5px; padding: 8px 0; }

/* ============================================================================
   Screen enter/exit animations — owner's animations.md. Curve --dg-ease, enter 300–400ms,
   exit 200–260ms, everything off under prefers-reduced-motion. Enters are keyed on the
   body.dg-state-* class (the rule starts matching -> the animation starts), exits on the
   *-out classes that dgLeaveScreen() (search/index.html) sets for the exit duration.
   ============================================================================ */
/* Results: "the list assembles" — header slides in from the left, toolbar rises 60ms later,
   rows rise in a 30ms cascade (1st 100ms … 7th 280ms, the rest 310ms). */
@keyframes dg-in-left { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@keyframes dg-rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes dg-out-up { to { opacity: 0; transform: translateY(-14px); } }
body.dg-state-results:not(.dg-busy) #dynamicHeader { animation: dg-in-left 300ms var(--dg-ease) backwards; }
body.dg-state-results:not(.dg-busy) #results-toolbar { animation: dg-rise 300ms var(--dg-ease) 60ms backwards; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child) { animation: dg-rise 260ms var(--dg-ease) 310ms backwards; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(1) { animation-delay: 100ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(2) { animation-delay: 130ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(3) { animation-delay: 160ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(4) { animation-delay: 190ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(5) { animation-delay: 220ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(6) { animation-delay: 250ms; }
body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child):nth-child(7) { animation-delay: 280ms; }
body.results-out #dynamicHeader, body.results-out #results-toolbar, body.results-out #search-pane { animation: dg-out-up 220ms var(--dg-ease) both; }

/* Home: blocks fade in top-down (50ms step) sliding from above; the navy bar slides from under
   the top edge. Exit: the whole page moves up 40px (to where the search bar lives on the inner
   screens) and fades. The search field itself is excluded — it travels by its own transitions. */
@keyframes dg-drop-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
@keyframes dg-navbar-in { from { transform: translateY(-100%); } to { transform: none; } }
@keyframes dg-home-out { to { opacity: 0; transform: translateY(-40px); } }
/* The field moves up with the page but stays visible: it carries the busy spinner while the
   results are fetched, and becomes the inner screens' field right after. */
@keyframes dg-home-out-field { to { transform: translateY(-40px); } }
body.home-out.dg-state-home .hero-row { animation: dg-home-out-field 240ms var(--dg-ease) both; } /* outranks the drop-in rule below */
body.dg-state-home #dg-hero-navbar { animation: dg-navbar-in 300ms var(--dg-ease) backwards; }
body.dg-state-home #dg-hero-heading { animation: dg-drop-in 300ms var(--dg-ease) 50ms backwards; }
body.dg-state-home .hero-row { animation: dg-drop-in 300ms var(--dg-ease) 100ms backwards; }
body.dg-state-home #home-scope-summary { animation: dg-drop-in 300ms var(--dg-ease) 100ms backwards; }
body.dg-state-home #dg-announce { animation: dg-drop-in 300ms var(--dg-ease) 150ms backwards; }
body.dg-state-home #home-tiles, body.dg-state-home #home-slides { animation: dg-drop-in 300ms var(--dg-ease) 200ms backwards; }
body.dg-state-home #home-howto { animation: dg-drop-in 300ms var(--dg-ease) 250ms backwards; }
body.home-out #dg-hero-navbar, body.home-out #dg-hero-heading, body.home-out #home-scope-summary, body.home-out #dg-announce,
body.home-out #home-tiles, body.home-out #home-slides, body.home-out #home-howto { animation: dg-home-out 240ms var(--dg-ease) both; }

@media (prefers-reduced-motion: reduce) {
    body.dg-state-results #dynamicHeader, body.dg-state-results #results-toolbar,
    body.dg-state-results #search-pane table.dataTable > tbody > tr:not(.child),
    body.results-out #dynamicHeader, body.results-out #results-toolbar, body.results-out #search-pane,
    body.dg-state-home #dg-hero-navbar, body.dg-state-home #dg-hero-heading, body.dg-state-home #home-scope-summary, body.dg-state-home #dg-announce,
    body.dg-state-home #home-tiles, body.dg-state-home #home-slides, body.dg-state-home #home-howto,
    body.home-out #dg-hero-navbar, body.home-out #dg-hero-heading, body.home-out #home-scope-summary, body.home-out #dg-announce,
    body.home-out #home-tiles, body.home-out #home-slides, body.home-out #home-howto { animation: none; }
}
/* Quote fold (search-render.js rowFold): no scroll anchoring while the row's height animates. */
body.dg-state-results #search-pane tbody { overflow-anchor: none; }
/* overflow:hidden stays on permanently: with it switched off at the end child margins would
   collapse and the height would snap by a few px (owner: "последние миллиметры дёргается"). */
body.dg-state-results #search-pane td.child > .dtr-details { overflow-anchor: none; overflow: hidden; }

/* Toasts (showBubbleNotification, extrastyles.css): the "info" flavour was Solarized blue —
   owner: "зелёного делать классического", one green for every toast in the skin. */
body.dg-skin-minimal .bubble-notification, body.dg-skin-minimal .bubble-notification.info { background: #136857; color: #fff; }

/* Lato ships a standard "ti" ligature (t and i drawn joined — "Section" read as one blob, owner);
   the fi/fl ones look the same without it, so all standard ligatures are off. */
body.dg-skin-minimal, body.dg-skin-minimal * { font-variant-ligatures: no-common-ligatures; }
/* Lato Bold sets "t" and "i" touching at heading sizes ("Section" — owner); a hair of tracking
   on the reader headings keeps them apart. */
body.dg-state-reader #sutta h1, body.dg-state-reader #sutta h2, body.dg-state-reader #sutta h3, body.dg-state-reader #sutta h4 { letter-spacing: .015em; }
/* Results: with room, the table filter sits on the header line (word · counts · variants) instead
   of on its own row below (owner). The header keeps its 18px bottom padding, the pane is pulled
   up by header-text-height + gap so the filter row (40px) centers on the header text.
   ONLY when that control row is the single short line this pull-up assumes — #search-pane.dg-has-
   paging (updatePagingLayoutClass(), search/index.html) means real pagination is showing, an
   extra row DataTables adds beneath dt-length/dt-search, which this fixed -50px doesn't account
   for: it landed on top of the header/keyword text instead of the filter row centering on it
   (owner, screenshot: "10 per page" overlapping "kacchapa"). With pagination, skip the pull-up
   entirely — header on its own line, the whole control block normally below it. */
/* issue #15: base — controls start right under the header text, no empty row between (mt-4's
   24px was that row). Applies with pagination and on phones, where the filter can't share the line. */
body.dg-state-results #search-pane { margin-top: -8px !important; }
/* The pulled-up control row spans the header's full line: it must not swallow clicks on the header
   (scope star, variants link) — only the controls themselves take pointer events. */
body.dg-state-results #search-pane:not(.dg-has-paging) :is(#pali_wrapper, #pali-words_wrapper, #pali_wrapper > .row:first-child, #pali-words_wrapper > .row:first-child) { pointer-events: none; }
body.dg-state-results #search-pane:not(.dg-has-paging) :is(#pali_wrapper, #pali-words_wrapper) > :not(.row:first-child),
body.dg-state-results #search-pane:not(.dg-has-paging) .dt-search { pointer-events: auto; }
/* Phones: the hidden page-size selector still left its empty column's 8px gutter above the filter. */
@media (max-width: 575.98px) {
    body.dg-state-results #search-pane { margin-top: -16px !important; }
    body.dg-state-results :is(#pali_wrapper, #pali-words_wrapper) > .row:first-child > :has(> .dt-length[style*="none"]) { display: none; }
}
/* Tablets (mobile dom: filter in the right half): same header-line placement as desktop. The header
   reserves the filter's width so a long header wraps instead of running under the filter. */
@media (min-width: 576px) and (max-width: 767.98px) {
    body.dg-state-results #search-pane:not(.dg-has-paging) { margin-top: -48px !important; }
    body.dg-state-results #search-pane:not(.dg-has-paging) .dt-search { justify-content: flex-end; }
    body.dg-state-results #search-pane:not(.dg-has-paging) .dt-search input { flex: 0 1 150px; }
    body.dg-state-results:has(#search-pane:not(.dg-has-paging) .dt-container:not(.d-none)) #dynamicHeader { padding-right: 280px; }
    body.dg-state-results #search-message,
    body.dg-state-results #ai-note-wrap:has(> :not(.d-none)) { margin-top: 44px; }
}
@media (min-width: 768px) {
    body.dg-state-results:has(#search-pane:not(.dg-has-paging) .dt-container:not(.d-none)) #dynamicHeader { padding-right: 215px; }
    body.dg-state-results #search-pane:not(.dg-has-paging) { margin-top: -50px !important; }
    body.dg-state-results #search-pane:not(.dg-has-paging) #pali_wrapper > .row:first-child,
    body.dg-state-results #search-pane:not(.dg-has-paging) #pali-words_wrapper > .row:first-child { position: relative; z-index: 2; }
    body.dg-state-results #search-pane:not(.dg-has-paging) #pali_wrapper > table,
    body.dg-state-results #search-pane:not(.dg-has-paging) #pali-words_wrapper > table { margin-top: 12px; }
    /* #search-message (plain "not found"/"too short" text) and #ai-note-wrap (AI-search's "did
       you mean"/sutta-guess note + word chips, ai-search.js) are #search-pane's own first
       children — the -50px above pulls the WHOLE pane up, so whichever of them ends up the first
       VISIBLE one needs this compensation or it renders pulled into .resultheader's space (found
       live: 42px measured overlap). Scoped to the same breakpoint as -50px itself on purpose
       (owner: "в мобильной версии какой-то дикий разрыв") — #search-pane keeps its normal +24px
       (mt-4) below 768px, so there is nothing here to compensate for on mobile.
       Owner: "опять фильтр не на одной строке с заголовком... откуда регрессия?" — #search-message
       collapses to zero box entirely when .d-none (display:none takes it out of layout, margin
       included), but #ai-note-wrap itself is NEVER .d-none — only its two children (#ai-note,
       #ai-words) are — so on every ordinary successful search (nothing to do with AI at all) this
       margin was still landing on that empty-but-present wrapper, pushing the real filter/table
       row down and breaking the single-line filter-next-to-header trick above for every
       no-pagination result, not just AI-search ones. :has() scopes it to when there is actually
       a visible child to compensate for. */
    body.dg-state-results #search-message,
    body.dg-state-results #ai-note-wrap:has(> :not(.d-none)) { margin-top: 54px; }
}
/* Wide screens: more air between the header/filter row and the table, and the bottom link row
   (.footerlike: Main / History / Export …) sits at the bottom of the viewport when the table is
   short (owner: "на больших экранах просторнее … ссылки внизу к нижнему краю"). */
@media (min-width: 992px) {
    body.dg-state-results #pali_wrapper > table, body.dg-state-results #pali-words_wrapper > table { margin-top: 26px; }
    body.dg-state-results #search-pane { display: flex; flex-direction: column; min-height: calc(100vh - 112px); } /* 112 = fixed header stack; the pane ends at the viewport bottom */
    body.dg-state-results #pali_wrapper, body.dg-state-results #pali-words_wrapper { display: flex; flex-direction: column; flex: 1 0 auto; }
    /* Links line centred on the corner pill (bottom 30px, 38px tall -> centre 49px up). */
    body.dg-state-results #pali_wrapper > .footerlike, body.dg-state-results #pali-words_wrapper > .footerlike { margin-top: auto; padding: 28px 0 30px; }
    body.dg-state-results #search-pane .footerlike .dt-buttons { padding-bottom: 0; } /* its own 40px bottom padding (rule above, id-scoped) would push the links up again */
}
/* TOC: the search field sits at the same 10px as on results/reader, pinned and hidden on scroll
   down the same way — but through the SHARED header stack (search/index.html's <style> +
   autoHideHeader()/applyPadding()/stackConfig(), which now knows the toc state), not a second
   hand-rolled copy here. The old copy (fixed band + hardcoded 65px backdrop +
   #toc-pane{padding-top:62px}) is gone: it took no part in the hide-on-scroll mechanism, so on
   /toc the band stayed put over a scrolling list and covered the first rows and the Translator
   filter title (owner: "на странице toc шапка как в ридере, так не должно быть, она закрывает"),
   and its hardcoded numbers could silently drift from the band's real height. Padding, backdrop
   height and --dg-stack-height are computed in one place now, so nothing here needs a fixed
   empty stripe of its own. */
/* Folded with dgFold(): overflow stays hidden so the animated height equals the natural one
   (otherwise the last child's margin collapses when the fold ends and the panel snaps ~13px). */
#search-pane .dtsb-searchBuilder { overflow: hidden; }

/* ——— Окно «Переводы» (issue #6 этап 3, home.js tsRender) ————————————————————————————————
   Плоский список: строка = один перевод (переводчик + язык), порядок строк = порядок под
   каждой строкой пали. Заменяет дерево «язык → переводчики» в обычном чтении и мульти;
   memorize/devanagari остаются на прежнем попапе (.dg-lpmenu выше). На десктопе висит над
   кнопкой «···», на телефоне — шторка снизу: одна разметка, разная посадка. */
.dg-ts {
    position: fixed; right: 20px; bottom: 76px; z-index: 101;
    width: 360px; max-height: min(72vh, 620px);
    display: flex; flex-direction: column;
    background: var(--dg-surface); border: 1px solid var(--dg-border); border-radius: 14px;
    box-shadow: 0 8px 34px rgba(0, 0, 0, .22); font-family: var(--dg-font);
    transform-origin: 100% 100%;
    animation: dg-ts-in .26s var(--dg-ease);
}
.dg-ts[hidden] { display: none; }
@keyframes dg-ts-in { from { opacity: 0; transform: scale(.96) translateY(6px); } }
.dg-ts-head { display: flex; align-items: center; gap: 8px; padding: 11px 14px 8px; }
.dg-ts-head b { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--dg-text-muted); }
.dg-ts-count { font-size: 11.5px; color: var(--dg-text-muted); }
.dg-ts-x { border: 0; background: none; color: var(--dg-text-muted); width: 26px; height: 26px; border-radius: 50%; line-height: 1; cursor: pointer; transition: transform .1s ease-out, background .15s; }
.dg-ts-x:hover { background: var(--dg-surface-hover); color: var(--dg-text); }
.dg-ts-x:active { transform: scale(.9); }

.dg-ts-seg { display: flex; gap: 2px; margin: 0 14px; padding: 3px; background: var(--dg-surface-hover); border-radius: 10px; }
.dg-ts-seg button { flex: 1; border: 0; background: none; font: inherit; font-size: 12px; color: var(--dg-text-muted); padding: 5px 4px; border-radius: 7px; cursor: pointer; white-space: nowrap; transition: transform .1s ease-out, background .18s, color .18s; }
.dg-ts-seg button[aria-pressed="true"] { background: var(--dg-surface); color: var(--dg-text); font-weight: 600; box-shadow: 0 1px 3px rgba(0, 0, 0, .14); }
.dg-ts-seg button:active { transform: scale(.97); }

.dg-ts-chips { display: flex; gap: 5px; overflow-x: auto; padding: 9px 14px 2px; scrollbar-width: none; }
.dg-ts-chips::-webkit-scrollbar { display: none; }
.dg-ts-chip { flex: none; border: 1px solid transparent; background: var(--dg-surface-hover); color: var(--dg-text-muted); font: inherit; font-size: 11.5px; padding: 4px 10px; border-radius: 999px; cursor: pointer; transition: transform .1s ease-out, background .18s, color .18s, border-color .18s; }
.dg-ts-chip[aria-pressed="true"] { background: var(--dg-accent-bg); color: var(--dg-text); border-color: var(--dg-accent); }
.dg-ts-chip:active { transform: scale(.95); }

.dg-ts-body { overflow-y: auto; overscroll-behavior: contain; padding: 6px 8px 0; }
.dg-ts-rows { position: relative; }
.dg-ts-row { position: absolute; left: 0; right: 0; height: 44px; display: flex; align-items: center; gap: 9px; padding: 0 6px; border-radius: 10px; will-change: transform; transition: transform .18s var(--dg-ease), background .18s; }
.dg-ts-row.is-on { background: var(--dg-accent-bg); }
/* Перетаскиваемая строка идёт за пальцем 1:1 — переход здесь только мешал бы. */
.dg-ts-row.is-lift { z-index: 3; background: var(--dg-surface); box-shadow: 0 6px 22px rgba(0, 0, 0, .22); transition: none; }
.dg-ts-hnd { flex: none; width: 22px; height: 44px; display: grid; grid-template-columns: 3px 3px; grid-template-rows: repeat(3, 3px); gap: 3px; align-content: center; justify-content: center; cursor: grab; touch-action: none; opacity: .55; }
.dg-ts-hnd i { display: block; width: 3px; height: 3px; border-radius: 50%; background: var(--dg-text-muted); }
.dg-ts-rows.is-sorted .dg-ts-hnd { opacity: .15; cursor: default; }
.dg-ts-ord { flex: none; width: 12px; text-align: right; font-size: 10.5px; color: var(--dg-text-muted); font-variant-numeric: tabular-nums; }
.dg-ts-rows.is-sorted .dg-ts-ord { opacity: 0; }
.dg-ts-tick { flex: none; width: 19px; height: 19px; padding: 0; border: 1.5px solid var(--dg-text-muted); border-radius: 6px; background: transparent; position: relative; cursor: pointer; transition: transform .1s ease-out, background .16s, border-color .16s; }
.dg-ts-tick:active { transform: scale(.88); }
.dg-ts-tick[aria-checked="true"] { background: var(--dg-accent); border-color: var(--dg-accent); }
.dg-ts-tick[aria-checked="true"]::after { content: ""; position: absolute; left: 6px; top: 2px; width: 4px; height: 9px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(42deg); }
.dg-ts-name { flex: 1; min-width: 0; font-size: 13.5px; color: var(--dg-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.dg-ts-tag { flex: none; font-size: 10.5px; color: var(--dg-text-muted); background: var(--dg-surface-hover); border-radius: 6px; padding: 2px 6px; }
.dg-ts-star { flex: none; width: 26px; height: 26px; border: 0; border-radius: 50%; background: none; font-size: 13px; line-height: 1; color: var(--dg-border-strong); cursor: pointer; transition: transform .1s ease-out, color .18s; }
.dg-ts-star:hover { color: var(--dg-text-muted); }
.dg-ts-star:active { transform: scale(.85); }
.dg-ts-star.is-main { color: var(--dg-accent); }
.dg-ts-foot { border-top: 1px solid var(--dg-border); padding: 9px 14px; font-size: 11.5px; color: var(--dg-text-muted); }
.dg-ts-foot b { color: var(--dg-text); font-weight: 600; }

/* Телефон: шторка снизу во всю ширину — на 360px окно у кнопки просто не помещается. */
@media (max-width: 767.98px) {
    .dg-ts { left: 0; right: 0; bottom: 0; width: auto; border-radius: 16px 16px 0 0; border-bottom: 0;
        max-height: 82vh; padding-bottom: env(safe-area-inset-bottom);
        animation: dg-ts-up .3s var(--dg-ease); }
    @keyframes dg-ts-up { from { transform: translateY(100%); } }
}
@media (prefers-reduced-motion: reduce) { .dg-ts { animation: none; } }

/* Второй перевод того же языка в самом тексте (megareader.js entry.cueClass): имени
   переводчика над каждым абзацем нет — язык и так виден; метка появляется только там, где
   двух переводов одного языка не различить, и только у «второго мнения». */
.dg-cue { border-left: 2px solid var(--dg-cue, var(--dg-border-strong)); padding-left: 9px; }
.dg-cue-1 { --dg-cue: #d08a1e; }
.dg-cue-2 { --dg-cue: #3d7fd6; }
.dg-cue-3 { --dg-cue: #b5539c; }
.dg-cue-4 { --dg-cue: #2f9e6f; }
#trn .dg-cue { border-left-width: 3px; padding-left: 6px; }
/* Языки чтения в окне: чипы — общая настройка (dhammaReaderLangs, та же, что на /settings/),
   нажатый = язык сейчас в тексте. "+ язык" разворачивает остальные языки этого текста. */
.dg-ts-chip.is-missing { opacity: .4; cursor: default; }
.dg-ts-add { border-style: dashed !important; border-color: var(--dg-border-strong) !important; }
.dg-ts-add-list { padding: 4px 10px 2px; max-height: 240px; overflow-y: auto; }
.dg-ts-add-list[hidden] { display: none; }
.dg-ts-add-hint { margin: 2px 4px 6px; font-size: 11px; color: var(--dg-text-muted); }
.dg-ts-add-row { display: flex; width: 100%; align-items: center; gap: 8px; border: 0; background: none; font: inherit; font-size: 13px; color: var(--dg-text); padding: 7px 6px; border-radius: 8px; cursor: pointer; text-align: left; }
.dg-ts-add-row:hover { background: var(--dg-surface-hover); }
.dg-ts-add-n { margin-left: auto; font-size: 11px; color: var(--dg-text-muted); }
/* Полосок теперь до шести — с трёх переводов помечаются все строки. */
.dg-cue-5 { --dg-cue: #6a5acd; }
.dg-cue-6 { --dg-cue: #c2611f; }
/* Локальный язык — тот, которого нет в моих языках (/settings/): включён только на этом тексте. */
.dg-ts-chip.is-local { border-style: dashed; border-color: var(--dg-border-strong); }
.dg-ts-tag.is-local { border: 1px dashed var(--dg-border-strong); }
.dg-ts-add-hint a { color: var(--dg-accent-ink); }
/* Режим в шапке окна: «Читать» — набор одноразовый (пунктир, как у локального языка),
   «Мульти» — сохраняется. Судьба правок должна быть видна до того, как их сделали. */
.dg-ts-mode { margin-left: auto; font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--dg-accent-ink); background: var(--dg-accent-bg); border-radius: 6px; padding: 2px 7px; }
.dg-ts-mode.is-trial { color: var(--dg-text-muted); background: none; border: 1px dashed var(--dg-border-strong); }
.dg-ts-keep { border: 0; background: none; font: inherit; font-size: 11.5px; color: var(--dg-accent-ink); text-decoration: underline; padding: 0; cursor: pointer; }
