/* stepforge_site/assets/css/dl.css
 *
 * "Daylight" (design/redesign_v2_light_simple.md) — рабочий CSS редизайна
 * публичного сайта. Реализует §3 (шапка/подвал), §5 (компоненты) и разметку
 * из четырёх вьюх §4 (главная, каталог, карточка приложения, форум) —
 * статический прототип design/redesign_preview_v2_daylight.html здесь
 * превращён в боевые классы для реальных PHP-страниц.
 *
 * ═══════════════════════════════════════════════════════════════════════
 * ГРАНИЦА СКОУПА ЭТОЙ ЗАДАЧИ (важно прочитать перед правкой) — Daylight
 * покрывает только 4 вьюхи: home.php, apps_browse.php, app_detail.php,
 * forum_categories.php/forum_threads.php/forum_thread_view.php/
 * forum_thread_new.php. Все остальные страницы маркетплейса (account.php,
 * login.php, developer_*.php, google_callback.php, telegram_web_exchange.php,
 * sitemap.php, lang.php) СОЗНАТЕЛЬНО не редизайнятся сейчас — под них нет
 * утверждённой спеки, и превращать их в Daylight означало бы придумывать
 * дизайн без утверждения владельца. Эти страницы рендерятся через тот же
 * _chrome.php и те же marketplace.css/forum.css — этот файл их не трогает
 * (см. секцию 1 ниже про единственное осознанное исключение — шапку/подвал).
 * ═══════════════════════════════════════════════════════════════════════
 *
 * ОБНОВЛЕНИЕ 2026-07-20 (design/redesign_v2_light_simple.md §10) — граница
 * выше расширена ДВАЖДЫ в один день: сначала login.php, затем account.php —
 * оба теперь ТОЖЕ Daylight (готовые конверсии, см. §19 ниже и сами файлы;
 * account.php потребовал одного мелкого добавочного компонента сверх
 * буквального текста §10 — .dl-account-profile-row/-facts, §19.11, обёртка
 * "аватар + факты профиля", которой не было ни у одной из 4 исходных
 * Daylight-вьюх). marketplace/pages/developer_*.php по-прежнему ждут своей
 * конверсии следующим шагом — CSS для них уже добавлен (§19), разметка тех
 * файлов пока не тронута этой задачей.
 *
 * Подключать ПОСЛЕДНИМ в стеке <head> (см. _chrome.php) — после dl-tokens.css
 * (переменные) и после marketplace.css/forum.css (чтобы секция 1 ниже
 * гарантированно выигрывала каскад при равной специфичности селектора).
 *
 * Namespace — только новые классы .dl-*, ничего существующего не
 * переименовано и не удалено (design/redesign_v2_light_simple.md §9: чистый
 * namespace, не мост поверх --mk-* / --sf-*).
 */

/* ═══════════════════════════════════════════════════════════════════════
 * 0. Холст страницы — opt-in через <body class="dl-page">
 * ═══════════════════════════════════════════════════════════════════════
 * mk_render_header() принимает необязательный параметр $bodyClass (см.
 * _chrome.php) — только 4 редизайненные страницы передают 'dl-page' и
 * получают светлый холст/системный шрифт Daylight на уровне <body>; все
 * остальные страницы параметр не передают, класс отсутствует, это правило
 * не совпадает — их текущий фон/типографика (marketplace.css, --sf-bg и
 * т.д.) не меняются НИ НА БИТ. Без этого класса-переключателя пришлось бы
 * либо переопределять глобальный body{} (тогда все НЕ-Daylight страницы
 * тоже получили бы холст Daylight под всё ещё Foundry-контентом — разъезд),
 * либо оставить Daylight-страницы плавать на голубом фоне Foundry поверх
 * белых карточек Daylight — тоже разъезд. opt-in класс — самый безопасный
 * аддитивный вариант.
 */
body.dl-page {
  background: var(--dl-bg);
  color: var(--dl-ink);
  font-family: var(--dl-font-sans);
  font-variant-numeric: tabular-nums;
}
/* :where() держит специфичность этого правила на уровне голого `a` (0,0,1) —
   без него `body.dl-page a` (0,1,2) перебивал бы любой одноклассовый
   цветовой рецепт вида `.dl-tabs-item { color: ... }`/`.mk-header__nav a
   { color: ... }` (оба (0,1,0)/(0,1,1)), молча стирая задуманный цвет
   (найдено живым ревью 2026-07-20: активная/неактивная вкладка таб-бара
   кабинета разработчика оказались неотличимы по цвету на первых страницах,
   где одновременно есть и body.dl-page, и .dl-tabs — тот же корень тише
   гасит и .mk-header__nav a на уже отгруженных страницах). */
:where(body.dl-page) a { color: inherit; text-decoration: none; }
body.dl-page img, body.dl-page svg { display: block; max-width: 100%; }

@media (prefers-reduced-motion: reduce) {
  body.dl-page *, body.dl-page *::before, body.dl-page *::after {
    transition: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 1. Рескин общей шапки/подвала (.mk-header/.mk-footer) — ЕДИНСТВЕННОЕ
 *    отклонение от чистой аддитивности в этом файле, и оно осознанное.
 * ═══════════════════════════════════════════════════════════════════════
 * .mk-header/.mk-footer рендерятся из _chrome.php и используются АБСОЛЮТНО
 * ВСЕМИ страницами маркетплейса, включая страницы вне скоупа Daylight —
 * альтернативы переопределению не было (нельзя сделать "две шапки", не
 * задваивая разметку в _chrome.php ради 4 страниц из ~25). Решение:
 * перекрасить существующую шапку/подвал ВИЗУАЛЬНО везде, СТРУКТУРУ
 * (разметку, классы, ссылки навигации — "Apps", переключатель языка,
 * логин/дропдоу пользователя) не менять ни на одной странице. Т.е. на
 * страницах вне скоупа (аккаунт, кабинет разработчика, логин...) после этой
 * задачи будет светлая/зелёная шапка Daylight над всё ещё голубым Foundry-
 * контентом ниже — это временный, наглядный, но безопасный разъезд стилей
 * (структура и работоспособность страниц не затронуты), который снимается
 * будущим редизайном тех страниц. Спека явно допускает такой путь (см.
 * design/redesign_v2_light_simple.md §3.1/§3.2 — "то же дерево навигации,
 * просто перекрашено").
 *
 * НЕ добавлены (сознательно): пункты навигации "Forum"/"About" и строка
 * поиска из прототипа — на сайте нет ни общесайтового /forum (форум
 * привязан к приложению: /apps/{slug}/forum), ни /about, ни бэкенда поиска.
 * Дорисовать несуществующие ссылки/красивую, но неработающую строку поиска
 * значило бы нарушить принцип "honest-disabled", уже принятый в этом
 * кодбейзе (footer __soon, mk_render_dev_subnav no-op) — вместо этого
 * навигация остаётся как есть, просто в новых цветах/шрифте.
 *
 * .mk-btn-foundry переиспользуется на несвязанных страницах (login.php,
 * apps_browse.php, home.php, google_callback.php) — поэтому его
 * переопределение ниже намеренно СКОУПЛЕНО селектором `.mk-header
 * .mk-btn-foundry`, а не голым `.mk-btn-foundry`: красится только кнопка
 * "Войти" внутри самой шапки, кнопка с тем же классом на остальных
 * страницах остаётся прежней Foundry-кнопкой (не в скоупе задачи).
 */
.mk-header {
  background: var(--dl-surface);
  box-shadow: none;
  border-bottom: 1px solid var(--dl-border);
}
.mk-header__inner {
  max-width: var(--dl-content-max);
  min-height: 56px;
  padding: 0 var(--dl-space-5);
  gap: var(--dl-space-6);
  font-family: var(--dl-font-sans);
}
.mk-header__wordmark {
  color: var(--dl-ink);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  gap: var(--dl-space-2);
}
.mk-header__nav a {
  color: var(--dl-ink-soft);
  font-size: 15px;
  font-weight: 400;
  transition: color .12s ease-out;
}
.mk-header__nav a:hover { color: var(--dl-ink); }
.mk-header__auth { gap: var(--dl-space-4); }

.mk-lang-switch__select {
  font-family: var(--dl-font-sans);
  font-size: 13px;
  color: var(--dl-ink-soft);
  background: var(--dl-surface-2);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-sm);
  padding: 5px 8px;
  cursor: pointer;
}

.mk-user-menu__toggle {
  font-family: var(--dl-font-sans);
  font-size: 14px;
  color: var(--dl-ink-soft);
}
.mk-user-menu__avatar {
  background: var(--dl-accent);
  font-family: var(--dl-font-sans);
}
.mk-user-menu__dropdown {
  background: var(--dl-surface);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-md);
  box-shadow: var(--dl-shadow-float);
  font-family: var(--dl-font-sans);
}
.mk-user-menu__dropdown a,
.mk-user-menu__logout { color: var(--dl-ink); font-size: 14px; }
.mk-user-menu__dropdown a:hover,
.mk-user-menu__logout:hover { background: var(--dl-surface-2); color: var(--dl-accent); }

/* Имя/email пользователя в шапке (marketplace.css/_chrome.php mk_render_header():
   mk-user-menu__name раньше вообще не имел правил — $displayName берётся из
   display_name ИЛИ, если оно пустое, из сырого email (см. _chrome.php), т.е.
   могло быть произвольной длины и распирать шапку на любой ширине экрана, не
   только на мобильном. Обрезаем многоточием — полное имя всё равно видно в
   дропдауне под кнопкой и на /account, здесь это просто ярлык. */
.mk-user-menu__name {
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mk-header .mk-btn-foundry {
  font-family: var(--dl-font-sans);
  font-weight: 600;
  font-size: 14px;
  color: #fff;
  background: var(--dl-accent-strong);
  border: none;
  border-radius: var(--dl-radius-sm);
  box-shadow: none;
  padding: 8px 16px;
  transition: background .12s ease-out;
}
.mk-header .mk-btn-foundry:hover { background: #095332; box-shadow: none; }
.mk-header .mk-btn-foundry:active { transform: none; background: #083f26; }
.mk-header .mk-btn-foundry:focus-visible { outline: 2px solid var(--dl-accent); outline-offset: 2px; }

.mk-footer {
  background: var(--dl-surface);
  color: var(--dl-ink-soft);
  border-top: 1px solid var(--dl-border);
  margin-top: var(--dl-space-9);
  font-family: var(--dl-font-sans);
}
.mk-footer__inner {
  max-width: var(--dl-content-max);
  padding: var(--dl-space-8) var(--dl-space-5) var(--dl-space-6);
}
.mk-footer__wordmark { color: var(--dl-ink); font-size: 16px; }
.mk-footer__tagline { color: var(--dl-ink-soft); font-size: 14px; line-height: 1.6; }
.mk-footer__columns h3 {
  color: var(--dl-ink-soft);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.mk-footer__columns a { color: var(--dl-ink); font-size: 15px; }
.mk-footer__columns a:hover { color: var(--dl-accent); text-decoration: underline; }
.mk-footer__soon { color: var(--dl-ink-faint); }
.mk-footer__soon-tag { border-color: var(--dl-ink-faint); color: var(--dl-ink-faint); border-radius: var(--dl-radius-sm); }
.mk-footer__bottom { color: var(--dl-ink-faint); font-size: 13px; border-top: 1px solid var(--dl-border); padding-top: var(--dl-space-5); }

@media (max-width: 767px) {
  /* ─── Фикс "лого и название налазят на приложение" (owner, n/n5.md live-фидбек
     на только что задеплоенный Daylight) ───────────────────────────────────
     На ~375px сумма минимальных ширин wordmark(+добавленная сегодня иконка-
     логотип) + пункт нава "Приложения"/"Apps" + переключатель языка + меню
     пользователя реально превышает ширину экрана — а .mk-header__inner
     (marketplace.css) это display:flex БЕЗ flex-wrap и без min-width:0 ни на
     одном ребёнке, так что строка не переносится и не сжимается ниже
     min-content каждого элемента: лишнее либо вылезает за край экрана, либо
     наезжает на соседний элемент. Три меры вместе (не хак с одним свойством):
       1) иконка-логотип (чисто декоративная, alt="") скрывается первой — она
          не несёт уникальной информации (текст "StepForge" рядом её дублирует
          по смыслу) и именно она добавила лишние ~32px и спровоцировала
          переполнение;
       2) имя пользователя дополнительно ужимается (базовое правило — выше, у
          .mk-user-menu__name — работает на всех ширинах, здесь только меньше
          max-width для тесного экрана);
       3) flex-wrap — честный отходной путь на случай, когда даже после (1) и
          (2) не помещается (напр. залогиненный пользователь с длинным именем
          на самом узком телефоне): блок языка/аккаунта целиком переносится на
          вторую строку, а НЕ наезжает на текст и не обрезается за экраном. */
  .mk-header__inner {
    padding: 0 var(--dl-space-4);
    gap: var(--dl-space-3);
    flex-wrap: wrap;
    row-gap: var(--dl-space-2);
  }
  .mk-header__wordmark {
    /* Бренд-текст никогда не сжимается и не переносится — при нехватке места
       первой уступает место иконка (правило ниже), не сам текст "StepForge". */
    flex-shrink: 0;
  }
  .mk-header__logo-mark { display: none; }
  .mk-header__auth {
    /* 16px (--dl-space-4) — тот же зазор, что и на десктопе, где места
       достаточно; на телефоне ужимаем до 8px ради освобождения места под
       переключатель языка + меню пользователя. min-width:0 разрешает этому
       блоку сжиматься ниже суммарного min-content своих детей — без него
       ужатый .mk-user-menu__name (см. правило выше) не смог бы реально
       уменьшить ширину всего блока auth в расчётах flex-строки. */
    gap: var(--dl-space-2);
    min-width: 0;
    margin-left: auto; /* если auth целиком переносится на вторую строку — прижимаем её к правому краю, как на десктопе, а не к левому */
  }
  .mk-user-menu { min-width: 0; }
  .mk-user-menu__name { max-width: 92px; }
  .mk-footer__inner { padding: var(--dl-space-6) var(--dl-space-4) var(--dl-space-5); }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 2. Контейнер / ритм секций (§2.3) — далее всё аддитивно, новые .dl-*
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-container { max-width: var(--dl-content-max); margin: 0 auto; padding: 0 var(--dl-space-5); }
@media (max-width: 767px) { .dl-container { padding: 0 var(--dl-space-4); } }

.dl-section { margin-top: var(--dl-space-9); }
.dl-section:first-of-type { margin-top: 0; }
@media (max-width: 767px) { .dl-section { margin-top: var(--dl-space-7); } }

/* Утилита моно-цифр внутри sans-текста (версии/даты/счётчики) — намеренно
   .dl-mono, а не голый .mono из прототипа: короткие неймспейс-свободные
   имена классов рискуют когда-нибудь столкнуться с чужим правилом в общем
   CSS, весь новый код этой задачи держится в .dl-* без исключений. */
.dl-mono { font-family: var(--dl-font-mono); }

/* ═══════════════════════════════════════════════════════════════════════
 * 3. Типографика — роли по §2.2
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-eyebrow { font-size: 13px; font-weight: 600; letter-spacing: .04em; color: var(--dl-ink-soft); text-transform: uppercase; margin: 0 0 var(--dl-space-3); }
.dl-hero-h { font-size: 40px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; margin: 0; max-width: 20ch; color: var(--dl-ink); }
.dl-h1 { font-size: 28px; font-weight: 700; letter-spacing: -0.01em; margin: 0; color: var(--dl-ink); }
.dl-h2 { font-size: 20px; font-weight: 600; margin: 0; color: var(--dl-ink); }
.dl-h3 { font-size: 16px; font-weight: 600; margin: 0; color: var(--dl-ink); }
.dl-lead { font-size: 18px; font-weight: 400; color: var(--dl-ink-soft); line-height: 1.5; margin: var(--dl-space-4) 0 0; max-width: 56ch; }
.dl-body { font-size: 16px; line-height: 1.6; color: var(--dl-ink); max-width: 66ch; margin: 0; }
.dl-body + .dl-body { margin-top: var(--dl-space-4); }
.dl-meta { font-size: 14px; color: var(--dl-ink-soft); }
@media (max-width: 767px) {
  .dl-hero-h { font-size: 30px; max-width: none; }
  .dl-h1 { font-size: 24px; }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 4. Кнопки и ссылки (§5) — скруглённый прямоугольник, НЕ таблетка
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-btn-primary {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--dl-accent-strong); color: #fff; border: none;
  border-radius: var(--dl-radius-sm); padding: 12px 20px;
  font-family: var(--dl-font-sans); font-size: 15px; font-weight: 600;
  line-height: 1.2; cursor: pointer; text-decoration: none;
  transition: background .12s ease-out;
}
.dl-btn-primary:hover { background: #095332; }
.dl-btn-primary:active { background: #083f26; }
.dl-btn-primary:focus-visible { outline: 2px solid var(--dl-accent); outline-offset: 2px; }

.dl-btn-secondary {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--dl-surface); color: var(--dl-ink); border: 1px solid var(--dl-border-strong);
  border-radius: var(--dl-radius-sm); padding: 11px 20px;
  font-family: var(--dl-font-sans); font-size: 15px; font-weight: 600;
  line-height: 1.2; cursor: pointer; text-decoration: none;
  transition: border-color .12s ease-out, background .12s ease-out;
}
.dl-btn-secondary:hover { background: var(--dl-surface-2); }

.dl-btn-disabled {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--dl-surface-2); color: var(--dl-ink-faint); border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-sm); padding: 12px 20px;
  font-family: var(--dl-font-sans); font-size: 15px; font-weight: 600;
  line-height: 1.2; cursor: default;
}

.dl-link { font-family: var(--dl-font-sans); font-size: 15px; font-weight: 600; color: var(--dl-accent); background: none; border: none; cursor: pointer; padding: 0; text-decoration: none; }
.dl-link:hover { text-decoration: underline; }
.dl-link-quiet { font-family: var(--dl-font-sans); font-size: 15px; color: var(--dl-ink-soft); background: none; border: none; cursor: pointer; padding: 0; text-decoration: none; }
.dl-link-quiet:hover { color: var(--dl-ink); }

/* ═══════════════════════════════════════════════════════════════════════
 * 5. Чипы/теги (§5) — sans 12/600, radius-sm, никогда таблетка
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-chip { display: inline-flex; align-items: center; gap: 5px; font-family: var(--dl-font-sans); font-size: 12px; font-weight: 600; border-radius: var(--dl-radius-sm); padding: 5px 10px; line-height: 1.2; }
.dl-chip-verified { background: var(--dl-accent-soft); color: var(--dl-accent); }
.dl-chip-role { background: var(--dl-accent-soft); color: var(--dl-accent); font-size: 11px; padding: 3px 8px; text-transform: uppercase; letter-spacing: .03em; }

/* ═══════════════════════════════════════════════════════════════════════
 * 6. Строка фактов (герой главной) — §5 .dl-factline
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-factline { font-family: var(--dl-font-sans); font-size: 15px; color: var(--dl-ink-soft); margin-top: var(--dl-space-5); }
.dl-factline .pos { color: var(--dl-accent); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════════
 * 7. Иконка приложения — квадрат radius-lg, буква-заглушка если нет icon_url
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-appicon { flex: none; display: flex; align-items: center; justify-content: center; background: var(--dl-surface-2); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-lg); font-family: var(--dl-font-sans); font-weight: 700; color: var(--dl-ink); overflow: hidden; }
.dl-appicon img { width: 100%; height: 100%; object-fit: cover; }
.dl-appicon-56 { width: 56px; height: 56px; font-size: 22px; }
.dl-appicon-72 { width: 72px; height: 72px; font-size: 28px; }

/* ═══════════════════════════════════════════════════════════════════════
 * 8. Карточка приложения — §5 .dl-appcard (рендерится
 *    marketplace/_cards.php::mk_render_app_card_daylight(), см. её докблок)
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-appcard {
  display: block; background: var(--dl-surface); border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); padding: 28px;
  transition: border-color .12s ease-out, box-shadow .12s ease-out;
}
a.dl-appcard { text-decoration: none; color: inherit; }
.dl-appcard:hover { border-color: var(--dl-border-strong); box-shadow: 0 2px 4px rgba(20,25,35,.06), 0 8px 20px rgba(20,25,35,.08); }
.dl-appcard-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--dl-space-4); }
.dl-appcard-name { display: flex; align-items: center; gap: var(--dl-space-4); }
.dl-appcard-name h2, .dl-appcard-name h3 { font-size: 20px; font-weight: 600; margin: 0; color: var(--dl-ink); }
.dl-appcard-tag { font-size: 16px; color: var(--dl-ink-soft); margin: var(--dl-space-3) 0 0; }
.dl-appcard-meta { font-size: 14px; color: var(--dl-ink-soft); margin-top: var(--dl-space-4); display: flex; align-items: center; justify-content: space-between; gap: var(--dl-space-3); flex-wrap: wrap; }
.dl-appcard-meta .pos { color: var(--dl-accent); }
.dl-appcard-view { font-size: 14px; font-weight: 600; color: var(--dl-accent); flex: none; }

.dl-catalog-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--dl-space-5); }
.dl-catalog-list { display: flex; flex-direction: column; gap: var(--dl-space-4); }
@media (max-width: 767px) { .dl-catalog-grid { grid-template-columns: 1fr; } }

/* ═══════════════════════════════════════════════════════════════════════
 * 9. "Почему StepForge" — три колонки, §4.1 п.3
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-why-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--dl-space-6); margin-top: var(--dl-space-6); }
.dl-why-item .check { color: var(--dl-accent); font-size: 18px; font-weight: 700; }
.dl-why-item h3 { font-size: 16px; font-weight: 600; margin: 10px 0 6px; color: var(--dl-ink); }
.dl-why-item p { font-size: 15px; color: var(--dl-ink-soft); line-height: 1.5; margin: 0; }
@media (max-width: 767px) { .dl-why-grid { grid-template-columns: 1fr; gap: var(--dl-space-5); } }

/* ═══════════════════════════════════════════════════════════════════════
 * 11. Шапка страницы-списка (каталог §4.2, форум-лендинг §4.4 — общий приём)
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--dl-space-4); flex-wrap: wrap; }
.dl-page-count { font-size: 14px; color: var(--dl-ink-soft); }
.dl-page-sub-row { display: flex; align-items: center; justify-content: space-between; gap: var(--dl-space-4); margin-top: 10px; flex-wrap: wrap; }

/* ═══════════════════════════════════════════════════════════════════════
 * 12. Карточка приложения (детальная страница) — §4.3 identity-блок
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-identity-card { background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); padding: var(--dl-space-6); }
.dl-identity-top { display: flex; align-items: flex-start; gap: var(--dl-space-5); }
.dl-identity-name-row { display: flex; align-items: center; gap: var(--dl-space-4); flex-wrap: wrap; }
.dl-identity-name-row h1 { font-size: 28px; font-weight: 700; letter-spacing: -0.01em; margin: 0; color: var(--dl-ink); }
.dl-identity-tag { font-size: 16px; color: var(--dl-ink-soft); margin: var(--dl-space-2) 0 0; }
.dl-identity-cat { font-size: 14px; color: var(--dl-ink-soft); margin: 6px 0 0; }
.dl-identity-cta-row { display: flex; align-items: center; gap: var(--dl-space-4); flex-wrap: wrap; margin-top: var(--dl-space-5); }
.dl-identity-cta-meta { font-size: 14px; color: var(--dl-ink-soft); }
.dl-identity-cta-meta .pos { color: var(--dl-accent); }

@media (max-width: 767px) {
  .dl-identity-card { padding: var(--dl-space-5); }
  .dl-identity-top { gap: var(--dl-space-4); }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 13. Двухколоночная сетка карточки приложения + липкий сайдбар — §4.3/§6
 * ═══════════════════════════════════════════════════════════════════════
 * Брейкпоинт 1024px — из спеки §6 ("desktop >= 1024px"). Ниже него сайдбар
 * (.dl-sidebar-stack) скрыт, а страница обязана показать инлайн-дубликаты
 * At a glance / Forum через классы .dl-glance--inline/.dl-forum-card--inline
 * прямо в identity-блоке (см. §4.3 "mobile order") — сами карточки .dl-glance/
 * .dl-forum-card переиспользуются 1:1 в обоих местах, меняется только обёртка.
 */
.dl-detail-grid { display: grid; grid-template-columns: 1fr; gap: 0; margin-top: var(--dl-space-7); }
@media (min-width: 1024px) {
  .dl-detail-grid { grid-template-columns: 2fr 1fr; gap: var(--dl-space-7); align-items: start; }
  .dl-glance--inline, .dl-forum-card--inline { display: none; }
}
/* n/n5.md item 7/8 (live-фидбек, 2026-07-20) — правый сайдбар "уезжал" на
   десктопе, а на мобильном страница скроллилась вбок шире экрана. Один и
   тот же корень: grid-item'ы (.dl-main/<aside>) по умолчанию получают
   content-based `min-width: auto`, а не 0 — значит fr-колонка вынуждена
   резервировать место под самый широкий "неразбиваемый" узел внутри
   .dl-main (скриншоты/картинки), даже если у ТОГО узла есть собственный
   overflow-x:auto (§8: "flex/grid item needs min-width:0 to respect
   overflow-x:auto on a descendant"). Итог — 2fr-колонка требовала больше
   места, чем ей причиталось (сайдбар сжимался/съезжал), а на мобильном
   (единственная 1fr-колонка) весь `.dl-detail-grid` мог стать шире
   `.dl-container` и вытолкнуть страницу в горизонтальный скролл. Один
   `min-width: 0` на обоих grid-item'ах убирает и то, и другое — сами
   скриншоты по-прежнему скроллятся горизонтально ВНУТРИ своей колонки
   (.dl-shots ниже), просто колонка больше не "просит" лишнего у сетки. */
.dl-detail-grid > * { min-width: 0; }
.dl-sidebar-stack { display: none; }
@media (min-width: 1024px) {
  .dl-sidebar-stack { display: flex; flex-direction: column; gap: var(--dl-space-5); position: sticky; top: 88px; }
}

.dl-main h2 { font-size: 20px; font-weight: 600; margin: 0 0 var(--dl-space-4); color: var(--dl-ink); }
.dl-main-block { margin-top: var(--dl-space-7); }
.dl-main-block:first-child { margin-top: 0; }

/* ── Скриншоты — горизонтальный скролл, ленивая загрузка на стороне <img> ──
   n/n5.md item 7: ширина сужена 200px → 165px (то же соотношение сторон,
   ~9:16) — вместе с min-width:0 выше это даёт ровную границу правого края
   сетки с сайдбаром на десктопе, при этом сам скролл-ряд остаётся тем же
   .dl-shots{overflow-x:auto}. .dl-shot-frame теперь <button>, не <a>
   (n/n5.md item 6 — открывает лайтбокс вместо перехода на файл картинки),
   поэтому явно сброшены дефолтные стили кнопки (padding/appearance/font). */
.dl-shots { display: flex; gap: var(--dl-space-4); overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
.dl-shot { flex: none; width: 165px; }
.dl-shot-frame {
  display: block; width: 165px; height: 293px;
  background: var(--dl-surface-2); border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-lg); overflow: hidden; padding: 0;
  appearance: none; -webkit-appearance: none; font: inherit; cursor: pointer;
}
.dl-shot-frame:focus-visible { outline: 2px solid var(--dl-accent); outline-offset: 2px; }
.dl-shot-frame img { width: 100%; height: 100%; object-fit: cover; }

/* ═══════════════════════════════════════════════════════════════════════
 * 14. Панель фактов "At a glance" — §5 .dl-glance/.dl-factline (общий приём)
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-glance { background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); padding: var(--dl-space-5); }
.dl-glance--inline { margin-top: var(--dl-space-4); }
.dl-glance-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--dl-space-3); padding: 10px 0; border-bottom: 1px solid var(--dl-border); }
.dl-glance-row:first-child { padding-top: 0; }
.dl-glance-row:last-child { border-bottom: none; }
.dl-glance-key { font-family: var(--dl-font-mono); font-size: 13px; font-weight: 500; color: var(--dl-ink-soft); flex: none; }
.dl-glance-val { font-family: var(--dl-font-mono); font-size: 14px; font-weight: 500; color: var(--dl-ink); text-align: right; }
.dl-glance-val.pos { color: var(--dl-accent); }
.dl-glance-prov { margin-top: var(--dl-space-4); padding-top: var(--dl-space-4); border-top: 1px solid var(--dl-border); font-size: 13px; line-height: 1.5; color: var(--dl-ink-soft); }

/* ═══════════════════════════════════════════════════════════════════════
 * 15. Карточка форума в сайдбаре — §4.3 amendment (n/n4.md item 2, §0.1)
 * ═══════════════════════════════════════════════════════════════════════
 * Тот же белый корпус, что .dl-glance (граница/радиус/тень/паддинг — читаются
 * одной "семьёй" в стопке сайдбара), но грамматика строк — sans-список
 * категорий/тредов (.dl-board-row из §16), а не mono key/value факт-панели.
 * Источник данных на реальной странице — mk_ensure_forum_categories_seeded()/
 * mk_forum_category_highlights() из app_detail.php (см. спеку §9 — визуальный
 * рескин уже рабочего кода, не новая фича; эта задача сама разметку страницы
 * app_detail.php не пишет, только готовит для неё CSS-компонент).
 */
.dl-forum-card { background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); padding: var(--dl-space-5); }
/* forum_thread_view.php's .dl-main — unlike forum_categories.php/forum_threads.php/
   forum_threads_all.php (whose .dl-main already wraps a white .dl-list-card),
   the thread view's H1/meta/posts/composer sat directly on the page canvas
   with no card of their own — visually mismatched next to the white sidebar
   beside it (live feedback, 2026-07-22). Same white-card recipe as
   .dl-forum-card, additive class — bare .dl-main stays untouched (shared with
   app_detail.php's deliberately flat/cardless main column, §4.3). */
.dl-forum-main-card { background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); padding: var(--dl-space-6); }
.dl-forum-card--inline { margin-top: var(--dl-space-5); }
.dl-forum-card-title { font-size: 16px; font-weight: 600; color: var(--dl-ink); margin: 0 0 4px; }
.dl-forum-cat { padding: 14px 0; border-bottom: 1px solid var(--dl-border); }
.dl-forum-cat:first-child { padding-top: 0; }
.dl-forum-cat:last-child { border-bottom: none; padding-bottom: 0; }
.dl-forum-cat-name { font-size: 15px; font-weight: 600; color: var(--dl-accent); text-decoration: none; overflow-wrap: break-word; }
.dl-forum-cat-name:hover { text-decoration: underline; }
.dl-forum-cat-meta { font-size: 13px; color: var(--dl-ink-soft); margin: 5px 0 0; }
.dl-forum-cat-meta a { color: var(--dl-accent); text-decoration: none; }
.dl-forum-cat-meta a:hover { text-decoration: underline; }
.dl-forum-cat-meta.empty { color: var(--dl-ink-faint); }
.dl-forum-card-foot { margin-top: var(--dl-space-4); padding-top: var(--dl-space-4); border-top: 1px solid var(--dl-border); }

/* ── Форум-строка быстрой навигации (§0.2 amendment, 2026-07-22) — карточка
 * "Forum" в правом сайдбаре forum_threads.php/forum_thread_view.php/
 * forum_threads_all.php (design/redesign_v2_light_simple.md §0.2 Decision 3,
 * компонент §5 "Forum nav row"). Тот же корпус .dl-forum-card, что и выше, но
 * своя грамматика строки: у навигационной ссылки нет мета-строки (только имя
 * категории/"All threads"), поэтому не переиспользует двухстрочную
 * .dl-forum-cat/-name/-meta разметку — блочная ссылка, hairline-разделитель
 * между строками, та же "своя семья" (:first-child/:last-child), что и
 * .dl-glance-row/.dl-board-row выше. */
.dl-forum-nav-row { display: block; padding: 10px 0; border-bottom: 1px solid var(--dl-border); font-size: 15px; font-weight: 600; color: var(--dl-accent); text-decoration: none; overflow-wrap: break-word; }
.dl-forum-nav-row:hover { text-decoration: underline; }
.dl-forum-nav-row:first-child { padding-top: 0; }
.dl-forum-nav-row:last-child { border-bottom: none; padding-bottom: 0; }
/* Текущее местоположение (aria-current="page") рендерится как обычный текст
   (<span>, не <a>) — тот же приём, что хлебные крошки этих же страниц уже
   применяют для своего последнего сегмента. --accent-soft тонировка, а не
   второй акцентный цвет — тот же принцип "positive/selected", что у
   .dl-chip-verified. */
.dl-forum-nav-row--active { background: var(--dl-accent-soft); border-radius: var(--dl-radius-sm); padding-left: var(--dl-space-3); padding-right: var(--dl-space-3); cursor: default; }

.dl-related-card { display: flex; align-items: center; gap: var(--dl-space-4); background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); padding: var(--dl-space-5); text-decoration: none; color: inherit; transition: border-color .12s ease-out; }
.dl-related-card:hover { border-color: var(--dl-border-strong); }
.dl-related-card .txt { flex: 1; min-width: 0; }
.dl-related-card h3 { font-size: 16px; font-weight: 600; margin: 0 0 4px; color: var(--dl-ink); }
.dl-related-card p { font-size: 14px; color: var(--dl-ink-soft); margin: 0; }
.dl-related-card .arrow { color: var(--dl-ink-faint); flex: none; }

/* ── Липкая мобильная плашка "Get" — §6, появляется когда identity-блок
     уходит за пределы экрана (см. dl.js::dlInitGetBar) ── */
.dl-getbar { display: none; }
@media (max-width: 767px) {
  .dl-getbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    background: var(--dl-surface); border-top: 1px solid var(--dl-border);
    box-shadow: var(--dl-shadow-float); padding: var(--dl-space-3) var(--dl-space-4);
    align-items: center; justify-content: space-between; gap: var(--dl-space-3);
    transform: translateY(100%); transition: transform .16s ease-out;
  }
  .dl-getbar.show { display: flex; transform: translateY(0); }
  .dl-getbar .who { min-width: 0; }
  .dl-getbar .who .n { font-size: 14px; font-weight: 600; color: var(--dl-ink); }
  .dl-getbar .who .p { font-size: 12px; color: var(--dl-ink-soft); }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 16. Форум — списки (лендинг форума приложения §4.4, читается как единый
 *     примитив с карточкой форума в сайдбаре §15 — .dl-board-row/.dl-thread-row)
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-list-card { background: var(--dl-surface); border: 1px solid var(--dl-border); border-radius: var(--dl-radius-md); box-shadow: var(--dl-shadow-card); overflow: hidden; }
.dl-board-row, .dl-thread-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--dl-space-4);
  padding: 18px 20px; border-bottom: 1px solid var(--dl-border);
  text-decoration: none; color: inherit;
}
.dl-board-row:last-child, .dl-thread-row:last-child { border-bottom: none; }
.dl-board-row:hover, .dl-thread-row:hover { background: var(--dl-surface-2); }
.dl-board-name { font-size: 16px; font-weight: 600; color: var(--dl-accent); margin: 0 0 4px; overflow-wrap: break-word; }
/* Описание канонической категории форума под названием строки — 2026-07-22,
   forum_categories.description (VARCHAR(255) NULL). Тот же размер/цвет, что
   .dl-thread-board/.dl-field-hint (13px, --dl-ink-soft, приглушённая вторая
   строка); margin сброшен явно (не только margin-top), т.к. это <p> без
   общего сброса дефолтных браузерных отступов у тега. Рендерится, только
   когда описание непустое (developer-категории обычно NULL) — см.
   forum_categories.php. */
.dl-board-desc { font-size: 13px; color: var(--dl-ink-soft); margin: 4px 0 0; overflow-wrap: break-word; }
.dl-board-meta { font-size: 13px; color: var(--dl-ink-soft); flex: none; text-align: right; }
.dl-thread-title { font-size: 15px; color: var(--dl-ink); overflow-wrap: break-word; }
.dl-thread-board { font-size: 13px; color: var(--dl-ink-soft); margin-top: 4px; }
.dl-thread-meta { font-size: 13px; color: var(--dl-ink-soft); flex: none; text-align: right; }
.dl-row-title { flex: 1 1 auto; min-width: 0; }
@media (max-width: 600px) {
  .dl-board-row, .dl-thread-row { flex-direction: column; align-items: flex-start; gap: 6px; }
  .dl-board-meta, .dl-thread-meta { text-align: left; }
}

/* ── Тред форума — хлебная крошка, посты, композер (§4.5) ── */
.dl-breadcrumb { font-family: var(--dl-font-sans); font-size: 14px; color: var(--dl-ink-soft); background: none; border: none; padding: 0; text-decoration: none; }
.dl-breadcrumb:hover { color: var(--dl-ink); }
.dl-thread-meta-strip { font-size: 14px; color: var(--dl-ink-soft); margin-top: 8px; }

.dl-post { padding: var(--dl-space-5) 0; border-bottom: 1px solid var(--dl-border); max-width: 66ch; }
.dl-post:first-of-type { border-top: 1px solid var(--dl-border); margin-top: var(--dl-space-5); }
.dl-post-byline { display: flex; align-items: center; gap: 10px; margin-bottom: var(--dl-space-3); flex-wrap: wrap; }
.dl-post-name { font-size: 14px; font-weight: 600; color: var(--dl-ink); }
.dl-post-time { font-size: 13px; color: var(--dl-ink-soft); }
.dl-post p { font-size: 16px; line-height: 1.6; color: var(--dl-ink); margin: 0; white-space: pre-wrap; }
.dl-post code { font-family: var(--dl-font-mono); background: var(--dl-surface-2); padding: 1px 5px; border-radius: 4px; font-size: 14px; }

/* .dl-post-body — обёртка тела поста форума (mk_forum_render_body(),
   marketplace/_forum.php): заменила голый <p> (тот больше не может нести
   вложенный блочный HTML — blockquote/details от [quote]/[spoiler] внутри
   <p> невалидны). Те же значения типографики, что были на .dl-post p, БЕЗ
   white-space: pre-wrap — mk_forum_render_body() уже вставляет <br> через
   nl2br() для каждого переноса строки; добавление pre-wrap поверх этого
   удвоило бы визуальный отступ (браузер показал бы и <br>, и сохранённый
   pre-wrap'ом исходный символ переноса рядом с ним). */
/* §0.2 Decision 5 (2026-07-22, owner live feedback "всё сьезжает" на мобильном) —
   .dl-composer-editor ниже уже несёт overflow-wrap: break-word, а этот соседний
   по смыслу класс — нет: длинный неразрывный токен (URL, вставленный
   стектрейс) внутри уже ОТПРАВЛЕННОГО поста раздвигал .dl-post за пределы
   .dl-container и пропагировал горизонтальный скролл на весь <body> (ни
   .dl-post, ни .dl-container не имеют overflow-x, между ними нет grid/flex-
   item'а, который бы это перехватил — иной механизм бага, чем min-width:0 у
   grid-item'ов §13 выше). Свойство наследуется — каскадирует на все
   вложенные <p>/<blockquote>/<details>, которые рендерит
   mk_forum_render_body(), без отдельных правил на каждый тег. word-break —
   явный fallback. */
.dl-post-body { font-size: 16px; line-height: 1.6; color: var(--dl-ink); overflow-wrap: break-word; word-break: break-word; }
/* .dl-composer-editor добавлен в один селектор с .dl-post-body (не
   продублирован отдельным правилом, см. §16 ниже) — тот же визуал цитаты
   нужен и готовому посту, и черновику в WYSIWYG-редакторе форума
   (dl.js::dlInitComposerToolbar()). */
.dl-post-body blockquote,
.dl-composer-editor blockquote {
  margin: var(--dl-space-3) 0; padding: 10px var(--dl-space-4);
  border-left: 3px solid var(--dl-border); background: var(--dl-surface-2);
  color: var(--dl-ink-soft);
}
.dl-post-body details { margin: var(--dl-space-3) 0; }
.dl-post-body summary { cursor: pointer; font-weight: 600; }

/* .dl-post-image — вложение к посту форума (forum_posts.image_url,
   загружается mk_uploads_forum_post_store(), marketplace/_uploads.php). */
.dl-post-image {
  max-width: 100%; max-height: 500px; height: auto; display: block;
  margin-top: var(--dl-space-3); border-radius: var(--dl-radius-md);
  object-fit: contain;
}

.dl-composer { margin-top: var(--dl-space-6); max-width: 66ch; }
.dl-composer textarea {
  width: 100%; box-sizing: border-box; min-height: 110px;
  border: 1px solid var(--dl-border); border-radius: var(--dl-radius-sm);
  background: var(--dl-surface); padding: 14px;
  font-family: var(--dl-font-sans); font-size: 15px; color: var(--dl-ink); resize: vertical;
}
.dl-composer textarea:focus { outline: none; border-color: var(--dl-border-strong); box-shadow: 0 0 0 3px var(--dl-accent-soft); }
.dl-composer .helper { font-size: 13px; color: var(--dl-ink-soft); margin: 8px 0 14px; }

/* ── Панель форматирования (BBCode-кнопки) — dl.js::dlInitComposerToolbar().
   Один и тот же .dl-composer-btn на обеих формах (реплай/новая тема);
   radius-sm — тот же компактный квадратный рецепт, что уже использует
   .dl-icon-btn (§19.5), не выдумываем отдельный токен. */
.dl-composer-toolbar {
  display: flex;
  gap: var(--dl-space-2);
  margin-bottom: var(--dl-space-3);
}
.dl-composer-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--dl-border-strong);
  border-radius: var(--dl-radius-sm);
  background: var(--dl-surface);
  color: var(--dl-ink);
  font-family: var(--dl-font-sans);
  font-size: 14px;
  cursor: pointer;
  transition: background .12s ease-out, color .12s ease-out;
}
.dl-composer-btn:hover { background: var(--dl-surface-2); }
.dl-composer-btn:focus-visible { outline: 2px solid var(--dl-accent); outline-offset: 2px; }

/* ── WYSIWYG-редактор (contenteditable) — видимая замена реальной textarea,
   которая теперь скрыта JS'ом (dl.js::dlInitComposerToolbar() докблок).
   display:none по умолчанию — прогрессивное усиление: до JS-инициализации
   виден обычный .dl-composer textarea выше, а не пустой невидимый блок; если
   скрипт не выполнился вовсе, пользователь просто печатает в textarea, как
   раньше. Типографика/паддинги/рамка скопированы с .dl-composer textarea
   (тот же компонент визуально, просто на contenteditable-теге), min-height
   не меньше, чем было у textarea. white-space: pre-wrap НЕ нужен —
   contenteditable сам управляет переносами через <br> (см. сериализатор в
   dl.js) — та же причина, что уже отмечена у .dl-post-body (не задваивать
   отступы pre-wrap'ом поверх уже расставленных <br>). */
.dl-composer-editor {
  display: none;
  width: 100%; box-sizing: border-box; min-height: 110px;
  border: 1px solid var(--dl-border); border-radius: var(--dl-radius-sm);
  background: var(--dl-surface); padding: 14px;
  font-family: var(--dl-font-sans); font-size: 15px; color: var(--dl-ink);
  line-height: 1.6; overflow-wrap: break-word;
}
.dl-composer-editor:focus { outline: none; border-color: var(--dl-border-strong); box-shadow: 0 0 0 3px var(--dl-accent-soft); }
/* contenteditable не поддерживает нативный атрибут placeholder — CSS-приём
   на основе :empty (пусто ровно тогда, когда автор ещё ничего не напечатал
   и не вставил через dlBbcodeToEditorHtml() при инициализации, см. dl.js). */
.dl-composer-editor:empty:before {
  content: attr(data-placeholder);
  color: var(--dl-ink-faint);
  pointer-events: none;
}

/* Маркер спойлера ВНУТРИ редактора — визуально отличим, но НЕ скрыт (это
   черновик автора, а не чужой готовый пост: он должен видеть, что сам
   написал). Сворачивание в <details> — только у готового поста на сервере
   (mk_forum_render_body(), _forum.php), другой рендер, не трогаем здесь. Имя
   класса читается из data-dl-spoiler-class на .dl-composer в dl.js — тут
   жёстко задано ровно то же имя буквально (CSS не умеет читать
   data-атрибуты за пределами content:attr(), только dl.js это связывает). */
.dl-spoiler-mark {
  background: var(--dl-surface-2);
  border-bottom: 1px dashed var(--dl-border-strong);
  border-radius: 2px;
  padding: 0 2px;
}

/* ═══════════════════════════════════════════════════════════════════════
 * 17. Пустые/скудные состояния (§5) — переиспользует общий .mk-empty-state?
 * ═══════════════════════════════════════════════════════════════════════
 * НЕТ — .mk-empty-state (marketplace.css) используется на страницах вне
 * скоупа (developer_*), не трогаем её. Для Daylight-страниц — свой вариант.
 */
.dl-empty { text-align: center; padding: var(--dl-space-7) var(--dl-space-4); color: var(--dl-ink-faint); }
.dl-empty p { font-size: 15px; margin: var(--dl-space-3) 0 0; }

/* ═══════════════════════════════════════════════════════════════════════
 * 18. Лайтбокс скриншотов (n/n5.md item 6, app_detail.php only) —
 *     click-to-enlarge вместо прямой ссылки на файл картинки,
 *     dl.js::dlInitLightbox() переключает [hidden]/img.src, разметка —
 *     app_detail.php (единственная страница с .dl-shots).
 * ═══════════════════════════════════════════════════════════════════════ */
.dl-lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 20, 25, .92);
  padding: var(--dl-space-7) var(--dl-space-8);
}
.dl-lightbox[hidden] { display: none; }
.dl-lightbox-img {
  display: block; max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  border-radius: var(--dl-radius-md);
  box-shadow: var(--dl-shadow-float);
}
/* Кнопки закрытия/навигации — фиксированы к вьюпорту (не к картинке), 44px —
   минимальный тач-таргет из §6 на ЛЮБОЙ ширине, включая мобильную (там
   меняются только отступы от края в media-запросе ниже, не сам размер). */
.dl-lightbox-close,
.dl-lightbox-nav {
  position: fixed;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .14); color: #fff; border: none;
  border-radius: var(--dl-radius-sm); font-size: 24px; line-height: 1;
  cursor: pointer; transition: background .12s ease-out;
}
.dl-lightbox-close:hover,
.dl-lightbox-nav:hover { background: rgba(255, 255, 255, .26); }
.dl-lightbox-close:focus-visible,
.dl-lightbox-nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.dl-lightbox-close { top: var(--dl-space-4); right: var(--dl-space-4); }
.dl-lightbox-nav { top: 50%; transform: translateY(-50%); font-size: 28px; }
.dl-lightbox-prev { left: var(--dl-space-4); }
.dl-lightbox-next { right: var(--dl-space-4); }
@media (max-width: 767px) {
  .dl-lightbox { padding: var(--dl-space-8) var(--dl-space-2) var(--dl-space-2); }
  .dl-lightbox-close { top: var(--dl-space-2); right: var(--dl-space-2); }
  .dl-lightbox-prev { left: var(--dl-space-1); }
  .dl-lightbox-next { right: var(--dl-space-1); }
}

/* ═══════════════════════════════════════════════════════════════════════
 * 19. Foundation extension — login / account / кабинет разработчика
 *     (design/redesign_v2_light_simple.md §10, corrective extension,
 *     2026-07-20) — владелец протестировал первую поставку Daylight вживую
 *     и указал три конкретные вещи: "на логине всё ещё оранжевое", "на
 *     account нет отступов", "страницы приложения разработчика — всё
 *     свалено в кучу, плохо расставлено". Эта секция расширяет уже
 *     принятую систему токенов и .dl.css-компонентов на login.php,
 *     account.php и все marketplace/pages/developer_*.php — БЕЗ второй
 *     параллельной системы, без переименования уже существующих токенов.
 *     Единственный новый токен — --dl-danger-strong (dl-tokens.css §10.0).
 *     Секция строго аддитивна: ни одно значение существующих .dl-* правил
 *     выше не меняется.
 * ═══════════════════════════════════════════════════════════════════════ */

/* ── 19.1 Поле формы (§10.1) — .dl-field вместо .mk-field: margin-bottom
   24px вместо старых 16px, это и есть главный рычаг против "всё в кучу". */
.dl-field { margin-bottom: var(--dl-space-5); }
.dl-field-label { font-size: 14px; font-weight: 600; color: var(--dl-ink); margin-bottom: var(--dl-space-2); display: block; }
/* Тихий информационный маркер обязательности — НЕ danger-цвет: danger
   зарезервирован только под реальные ошибки, а не под "это поле нужно". */
.dl-field-required { color: var(--dl-ink-soft); font-weight: 400; }

.dl-input, .dl-textarea, .dl-select {
  width: 100%;
  font-family: var(--dl-font-sans);
  font-size: 15px;
  color: var(--dl-ink);
  background: var(--dl-surface);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-sm);
  padding: 10px 14px;
  line-height: 1.4;
}
.dl-input:focus, .dl-textarea:focus, .dl-select:focus {
  outline: none;
  border-color: var(--dl-border-strong);
  box-shadow: 0 0 0 3px var(--dl-accent-soft);
}
.dl-textarea { min-height: 140px; resize: vertical; }
.dl-input:disabled, .dl-textarea:disabled, .dl-select:disabled {
  background: var(--dl-surface-2);
  color: var(--dl-ink-faint);
  cursor: not-allowed;
}

/* Read-only "код"-вариант — client_id, webhook-секрет: моно + тонировка
   говорит "это значение для копирования, не для ввода". */
.dl-input-code {
  font-family: var(--dl-font-mono);
  font-size: 13px;
  background: var(--dl-surface-2);
}

.dl-input-invalid { border-color: var(--dl-danger); }
.dl-input-invalid:focus { box-shadow: 0 0 0 3px var(--dl-danger-soft); }

.dl-field-hint { font-size: 13px; color: var(--dl-ink-soft); margin-top: var(--dl-space-2); }
.dl-field-error { font-size: 13px; color: var(--dl-danger); margin-top: var(--dl-space-2); font-weight: 500; }

.dl-field-checkbox { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--dl-ink); }
.dl-field-checkbox input[type="checkbox"] { accent-color: var(--dl-accent); }

/* Группировка полей (внешние ссылки формы приложения) — видимый разделитель
   это и есть реальный фикс "всё слиплось", а не косметика. */
.dl-field-group { border: none; padding-top: var(--dl-space-5); margin: var(--dl-space-6) 0 0; border-top: 1px solid var(--dl-border); }
.dl-field-group-legend { font-size: 16px; font-weight: 600; margin: 0 0 var(--dl-space-4); color: var(--dl-ink); }

/* Дропзона загрузки картинки (иконка/баннер/скриншот) — раньше голый
   <input type=file> без единого правила стиля. */
.dl-dropzone {
  display: flex;
  align-items: center;
  gap: var(--dl-space-4);
  border: 1px dashed var(--dl-border-strong);
  border-radius: var(--dl-radius-md);
  background: var(--dl-surface-2);
  padding: var(--dl-space-5);
}
.dl-dropzone-preview {
  border-radius: var(--dl-radius-md);
  object-fit: cover;
  border: 1px solid var(--dl-border);
  flex: none;
}
.dl-dropzone-preview-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--dl-surface-2);
  border: 1px dashed var(--dl-border-strong);
  color: var(--dl-ink-faint);
  border-radius: var(--dl-radius-md);
  flex: none;
}
.dl-dropzone-body { flex: 1; min-width: 0; }
.dl-dropzone-input::file-selector-button {
  background: var(--dl-surface);
  border: 1px solid var(--dl-border-strong);
  border-radius: var(--dl-radius-sm);
  padding: 8px 14px;
  font-weight: 600;
  color: var(--dl-ink);
  cursor: pointer;
  margin-right: var(--dl-space-3);
  font-family: var(--dl-font-sans);
}
.dl-dropzone-input::file-selector-button:hover { background: var(--dl-surface-2); }

/* 6 слотов скриншотов — раньше один слитный блок, теперь построчно
   с нумерованным кружком, как .dl-glance-row/.dl-board-row по духу. */
.dl-screenshot-row {
  display: flex;
  align-items: center;
  gap: var(--dl-space-4);
  padding: var(--dl-space-3) 0;
  border-bottom: 1px solid var(--dl-border);
}
.dl-screenshot-row:last-child { border-bottom: none; }
.dl-screenshot-index {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--dl-surface-2);
  color: var(--dl-ink-soft);
  font-size: 12px;
  font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.dl-screenshot-preview {
  width: 64px; height: 64px;
  border-radius: var(--dl-radius-sm);
  object-fit: cover;
  border: 1px solid var(--dl-border);
  flex: none;
}

/* Код/JSON-блоки (developer_app_steps_api.php curl-примеры) — буквально
   то применение --dl-surface-2, которое комментарий dl-tokens.css уже
   анонсировал ("код-блоки"). */
.dl-code-block {
  background: var(--dl-surface-2);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-sm);
  padding: var(--dl-space-4);
  font-family: var(--dl-font-mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--dl-ink);
  overflow-x: auto;
  white-space: pre-wrap;
}

/* ── 19.2 Карточка секции контента (§10.2) — замена .sf-card/.mk-docs-block
   для account.php и кабинета разработчика. Отдельное имя от .dl-appcard/
   .dl-identity-card — те про листинг приложений, это про контент кабинета. */
.dl-card {
  background: var(--dl-surface);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-md);
  box-shadow: var(--dl-shadow-card);
  padding: var(--dl-space-6);
}
.dl-card + .dl-card { margin-top: var(--dl-space-5); }
.dl-card-title { font-size: 20px; font-weight: 600; margin: 0 0 var(--dl-space-4); color: var(--dl-ink); }
.dl-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--dl-space-4);
  margin-bottom: var(--dl-space-4);
  flex-wrap: wrap;
}

/* ── 19.3 Таб-бар кабинета приложения (§10.3) — зелёное подчёркивание
   вместо старого off-palette --sf-primary. */
.dl-tabs {
  display: flex;
  gap: var(--dl-space-6);
  border-bottom: 1px solid var(--dl-border);
  margin: 0 0 var(--dl-space-6);
}
.dl-tabs-item {
  padding: var(--dl-space-3) 0;
  color: var(--dl-ink-soft);
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: border-color .12s ease-out, color .12s ease-out;
}
.dl-tabs-item:hover { color: var(--dl-ink); }
.dl-tabs-item--active { color: var(--dl-ink); font-weight: 600; border-bottom-color: var(--dl-accent); }

/* ── 19.4 Деструктивные действия (§10.4) — красный остаётся красным
   сознательно (accessibility-конвенция + зелёный уже занят под "positive"),
   danger-strong (dl-tokens.css §10.0) — hover/pressed оттенок. */
.dl-link-danger {
  font-family: var(--dl-font-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--dl-danger);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  text-decoration: none;
}
.dl-link-danger:hover { text-decoration: underline; color: var(--dl-danger-strong); }

.dl-btn-danger {
  background: var(--dl-surface);
  color: var(--dl-danger);
  border: 1px solid var(--dl-danger);
  border-radius: var(--dl-radius-sm);
  padding: 11px 20px;
  font-family: var(--dl-font-sans);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.dl-btn-danger:hover { background: var(--dl-danger-soft); }

.dl-danger-zone { margin-top: var(--dl-space-7); padding-top: var(--dl-space-5); border-top: 1px solid var(--dl-border); }

/* ── 19.5 Icon-button (§10.5) — стрелки reorder категорий/тредов форума
   кабинета разработчика, сейчас совсем неоформленные браузерные кнопки. */
.dl-icon-btn {
  width: 32px; height: 32px;
  border: 1px solid var(--dl-border-strong);
  border-radius: var(--dl-radius-sm);
  background: var(--dl-surface);
  color: var(--dl-ink-soft);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  cursor: pointer;
  transition: background .12s ease-out, color .12s ease-out;
}
.dl-icon-btn:hover { background: var(--dl-surface-2); color: var(--dl-ink); }
.dl-icon-btn:disabled { opacity: .35; cursor: default; border-color: var(--dl-border); }

/* ── 19.6 Флэш/алерт-баннер (§10.6) — объединяет три несогласованных
   грамматики (.mk-flash--*, .mk-form__errors, .mk-login__error) в одну. */
.dl-flash {
  display: flex;
  align-items: flex-start;
  gap: var(--dl-space-3);
  border-radius: var(--dl-radius-sm);
  padding: var(--dl-space-3) var(--dl-space-4);
  font-size: 14px;
  font-weight: 500;
  margin: 0 0 var(--dl-space-5);
}
.dl-flash-success { background: var(--dl-accent-soft); border: 1px solid var(--dl-accent); color: var(--dl-accent-strong); }
.dl-flash-error { background: var(--dl-danger-soft); border: 1px solid var(--dl-danger); color: var(--dl-danger); }
.dl-flash ul { margin: 0; padding-left: var(--dl-space-5); }

/* ── 19.7 Аватар / буква-заглушка (§10.7) — единственная сознательная
   pill-форма в системе (dl-tokens.css сам это разрешает). Своя аватарка
   пользователя — зелёная (как уже перекрашенная шапка), сторонние
   провайдеры (Google/Telegram) — нейтральные, чтобы не выглядеть
   "под брендом StepForge". */
.dl-avatar {
  background: var(--dl-accent);
  color: #fff;
  font-family: var(--dl-font-sans);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px; /* таблетка — сознательное единственное исключение из radius-sm/md/lg (см. dl-tokens.css §"Радиусы"), своего --dl-radius-pill токена в системе нет, поэтому буквальное значение, а не мнимая переменная */
  flex: none;
  overflow: hidden; /* нужно для реального фото профиля (account.php: user.avatar_url из Google) — та же роль, что overflow:hidden уже играет у .dl-appicon (§7) для его img */
}
.dl-avatar-40 { width: 40px; height: 40px; font-size: 16px; }
.dl-avatar-64 { width: 64px; height: 64px; font-size: 24px; }
/* Реальное фото внутри .dl-avatar (буква-заглушка — просто текст, ей это не
   нужно) — идентичный рецепт .dl-appicon img (§7). */
.dl-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dl-avatar-neutral {
  background: var(--dl-surface-2);
  color: var(--dl-ink-soft);
  border: 1px solid var(--dl-border);
  border-radius: var(--dl-radius-sm);
}
/* Размер иконки-приложения для компактных строк списка (account-apps) —
   добавка к уже существующей семье .dl-appicon (dl.css §7), не новый
   компонент. */
.dl-appicon-44 { width: 44px; height: 44px; font-size: 18px; }

/* ── 19.8 Компактные строки (§10.8) — три конкретных ряда, общая грамматика
   flex-row + hairline-разделитель сверху, как у .dl-glance-row/.dl-board-row. */
.dl-account-identity-row {
  display: flex;
  align-items: center;
  gap: var(--dl-space-4);
  padding: var(--dl-space-4) 0;
  border-top: 1px solid var(--dl-border);
}
.dl-account-identity-row:first-child { border-top: none; padding-top: 0; }
.dl-account-identity-meta { flex: 1; min-width: 160px; }
.dl-account-identity-name { font-size: 15px; font-weight: 600; color: var(--dl-ink); }

.dl-account-app { padding: var(--dl-space-5) 0; border-top: 1px solid var(--dl-border); }
.dl-account-app:first-child { border-top: none; padding-top: 0; }
.dl-account-app-head { display: flex; align-items: center; gap: var(--dl-space-4); margin-bottom: var(--dl-space-3); flex-wrap: wrap; }
.dl-account-app-actions { display: flex; gap: var(--dl-space-4); align-items: center; }
.dl-account-app-progress { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.dl-forum-admin-row {
  display: flex;
  align-items: center;
  gap: var(--dl-space-3);
  padding: var(--dl-space-3) 0;
  border-top: 1px solid var(--dl-border);
}
.dl-forum-admin-row:first-child { border-top: none; padding-top: 0; }
.dl-forum-admin-reorder { display: flex; flex-direction: column; gap: 2px; }
.dl-forum-admin-name { flex: 1; min-width: 0; font-size: 15px; color: var(--dl-ink); font-weight: 500; }
.dl-chip-pinned { background: var(--dl-accent-soft); color: var(--dl-accent); }

/* ── 19.9 Логин (§10.9) — .dl-login-shell заменяет .mk-login, убирает
   единственный оставшийся оранжевый ("owner: login still has orange" —
   старый .mk-btn-foundry вне шапки красился в --mk-accent-deep, потому что
   переопределение в §1 этого файла нарочно заскоуплено `.mk-header
   .mk-btn-foundry`; здесь мы просто перестаём использовать .mk-btn-foundry
   вовсе, см. login.php). */
.dl-login-shell { display: flex; justify-content: center; padding: var(--dl-space-8) var(--dl-space-4); }
.dl-login-card { max-width: 400px; width: 100%; padding: var(--dl-space-6) var(--dl-space-5); text-align: center; }
.dl-login-title { font-size: 24px; font-weight: 700; color: var(--dl-ink); margin: 0; text-align: center; }
.dl-login-subtitle { font-size: 14px; color: var(--dl-ink-soft); margin: var(--dl-space-2) 0 var(--dl-space-6); text-align: center; }
.dl-login-divider {
  display: flex;
  align-items: center;
  color: var(--dl-ink-faint);
  font-size: 13px;
  margin: var(--dl-space-5) 0;
}
.dl-login-divider::before, .dl-login-divider::after { content: ""; flex: 1; height: 1px; background: var(--dl-border); }
.dl-login-divider span { padding: 0 var(--dl-space-3); }

.dl-oauth-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--dl-space-2);
  font-family: var(--dl-font-sans);
  font-weight: 600;
  font-size: 15px;
  padding: 12px 20px;
  margin-top: var(--dl-space-3);
  border-radius: var(--dl-radius-sm);
  border: 1px solid var(--dl-border-strong);
  background: var(--dl-surface);
  color: var(--dl-ink);
  cursor: pointer;
  text-decoration: none;
  transition: background .12s ease-out;
}
.dl-oauth-btn:hover { background: var(--dl-surface-2); }
.dl-oauth-btn[disabled] {
  opacity: .5;
  cursor: not-allowed;
  background: var(--dl-surface-2);
  color: var(--dl-ink-faint);
  border-color: var(--dl-border);
}
.dl-oauth-btn-icon { flex: none; width: 20px; text-align: center; font-weight: 700; }
.dl-oauth-note { font-size: 13px; color: var(--dl-ink-soft); margin: var(--dl-space-2) 0 0; }

/* ── 19.10 Бонус-компоненты (§10.10) — статус-чипы приложения, переиспользуют
   .dl-chip базу (dl.css §5) и уже провизионированные --dl-warn*/--dl-danger*. */
.dl-chip-draft { background: var(--dl-surface-2); color: var(--dl-ink-soft); }
.dl-chip-pending { background: var(--dl-warn-soft); color: var(--dl-warn); }
.dl-chip-published { background: var(--dl-accent-soft); color: var(--dl-accent); }
.dl-chip-suspended { background: var(--dl-danger-soft); color: var(--dl-danger); }

/* ── 19.11 Профиль-факты аккаунта (account.php, 2026-07-20) — спека §10
   явно даёт замену только для самой аватарки (.dl-avatar, §19.7), но не
   заводит своего класса для обёртки "аватар + список фактов" (имя/email/
   даты регистрации/последнего входа) — этого узла не было ни у одной из
   4 исходных Daylight-вьюх. Минимальный аддитивный компонент, та же шкала
   --dl-space-*/--dl-ink*, что и весь остальной §19 (было на --sf-space-*/
   --sf-ink* в старой .mk-account-profile__row/__facts — численно те же
   значения, но чужой namespace, см. dl-tokens.css "clean-room" докблок). */
.dl-account-profile-row {
  display: flex;
  align-items: center;
  gap: var(--dl-space-4);
  flex-wrap: wrap;
}
.dl-account-profile-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--dl-space-3) var(--dl-space-5);
  flex: 1;
  margin: 0;
}
.dl-account-profile-facts dt { font-size: 12px; color: var(--dl-ink-soft); margin: 0; }
.dl-account-profile-facts dd { font-size: 14px; font-weight: 600; margin: 0; color: var(--dl-ink); }

/* ── 19.12 Компактный ряд быстрых ссылок в тайле "Мои приложения"
   (developer_dashboard.php, 2026-07-20) — контекстная модификация уже
   существующего .dl-link-quiet (§4 выше), НЕ новый компонент: та же
   грамматика/цвета, просто уменьшенный кегль (13px вместо 15px), т.к. это
   узкая карта грида (marketplace.css .mk-grid, minmax(220px,1fr)) с пятью
   ссылками подряд (Настройки · Steps API · Тарифы · Форум · Статистика),
   а не полноразмерный текстовый блок кабинета, как везде в остальном §19. */
.dl-dev-tile-links { font-size: 13px; }
.dl-dev-tile-links .dl-link-quiet { font-size: inherit; }

/* ── 19.13 Обёртка формы кабинета приложения (developer_app_form.php,
   2026-07-20) — спека §10.1 держит саму форму на "640px-эквиваленте
   .mk-form", не заводя для неё отдельного класса; здесь минимальные
   аддитивные .dl-form-shell/.dl-form-actions вместо переиспользования
   .mk-form/.mk-form__actions (marketplace.css) — та же логика "не
   оставлять голые Foundry-имена на редизайненной странице", что и у §19.11/
   §19.12 выше. Оба класса чисто layout, без цвета — .mk-form/.mk-form__actions
   тоже были чисто layout, только на --sf-space-* шкале. */
.dl-form-shell { max-width: 640px; margin-top: var(--dl-space-5); }
.dl-form-actions { display: flex; gap: var(--dl-space-3); margin-top: var(--dl-space-6); flex-wrap: wrap; }

/* ── 19.14 Пост темы форума (developer_forum_posts.php, 2026-07-20) — §10.8
   спеки предметно описывает только однострочный "forum admin row"
   (категории/треды: reorder-стрелки + имя + счётчик), не пост с
   многострочным телом; минимальный одноразовый компонент той же
   грамматики hairline-строк, что и остальные ряды §19 (.dl-account-app/
   .dl-forum-admin-row), но flex-column вместо flex-row — контент поста
   (автор+дата, тело, действие) не влезает в одну строку. */
.dl-forum-post { padding: var(--dl-space-4) 0; border-top: 1px solid var(--dl-border); }
.dl-forum-post:first-child { border-top: none; padding-top: 0; }
.dl-forum-post-meta {
  display: flex;
  align-items: center;
  gap: var(--dl-space-2);
  font-size: 13px;
  color: var(--dl-ink-soft);
  margin-bottom: var(--dl-space-2);
}
.dl-forum-post-author { font-weight: 600; color: var(--dl-ink); }
.dl-forum-post-body { color: var(--dl-ink); white-space: pre-line; }
.dl-forum-post-deleted { color: var(--dl-ink-faint); font-style: italic; }
.dl-forum-post-actions { margin-top: var(--dl-space-2); text-align: right; }

/* ── 19.16 Реордер-стрелки категорий форума — форма как ребёнок flex-колонки
   (developer_forum_categories.php, 2026-07-20) — .dl-forum-admin-reorder
   (§19.8) в спеке описан как "holding two .dl-icon-btns", но по факту каждая
   стрелка обёрнута в свою <form> (нужна для CSRF/hidden category_id/action —
   один POST на клик, без лишнего JS), иначе реальная разметка не совпадает с
   абстракцией спеки. Тот же приём, что был у старого
   .mk-forum-category-row__reorder form { display: contents } — форма не
   создаёт собственного бокса и не ломает flex-column из двух кнопок. */
.dl-forum-admin-reorder form { display: contents; }

/* ── 19.15 Инлайн-тир-лок (developer_forum_threads.php, 2026-07-20) — спека
   §10 предметно не описывает компонент "заблокированный контрол + подпись
   рядом" (mk_render_tier_lock_inline(), marketplace/_forum.php) — его не
   было ни на одной из 4 исходных Daylight-вьюх. Минимальный аддитивный
   .dl-tier-lock-inline — только layout (flex-row + перенос строк), кнопка и
   подпись переиспользуют уже существующие .dl-link-quiet/.dl-field-hint
   типографику, а не заводят собственный цвет/кегль. */
.dl-tier-lock-inline { display: inline-flex; align-items: center; gap: var(--dl-space-2); flex-wrap: wrap; }
.dl-tier-lock-inline-caption { font-size: 13px; color: var(--dl-ink-soft); }
.dl-link-quiet:disabled { opacity: .45; cursor: not-allowed; }

/* ── 19.17 Блочный/компактный тир-лок (mk_render_tier_lock(),
   marketplace/_forum.php) — закрытие пробела, найденного живым ревью
   2026-07-20: обе ветки этой функции оставались последним Foundry-островом
   (.mk-tier-lock/.sf-btn) на уже полностью Daylight-страницах
   developer_forum_categories.php (non-compact) и developer_forum_posts.php
   (compact). --dl-warn/--dl-warn-soft — токены именно под "предупреждение,
   не ошибка" (см. их комментарий в dl-tokens.css), а не --dl-danger —
   недостаточный тир не деструктивен и не является сбоем. */
.dl-tier-lock-compact {
  background: var(--dl-warn-soft);
  border-radius: var(--dl-radius-sm);
  padding: var(--dl-space-3) var(--dl-space-4);
  margin-bottom: var(--dl-space-4);
}
.dl-tier-lock-compact p { margin: 0; font-size: 14px; color: var(--dl-warn); }

.dl-tier-lock {
  text-align: center;
  padding: var(--dl-space-7) var(--dl-space-5);
}
.dl-tier-lock__icon {
  font-size: 32px;
  line-height: 1;
  margin-bottom: var(--dl-space-3);
}
.dl-tier-lock h2 { margin: 0 0 var(--dl-space-2); }
.dl-tier-lock .dl-body { margin: 0 auto var(--dl-space-5); max-width: 48ch; }

/* ── 19.18 Инлайн-редактирование никнейма (account.php, 2026-07-21) —
   владелец: "в этом же модуле и на сайте должна быть функция изменения
   никнейма... редактировать только в этом модуле". Кнопка-карандаш рядом со
   значением имени (.dl-link, §4) переключает видимость формы ниже через уже
   существующий общий data-dl-toggle (dl.js::dlInitOlderToggles(), §19.15
   уже переиспользует его же для тир-лока) — класс .open здесь получает
   реальное display-правило (единственный компонент §19, которому это
   понадобилось; сам .open в dl.js по умолчанию ничего не красит). */
.dl-account-name-toggle { margin-left: var(--dl-space-2); font-size: 13px; }
.dl-account-name-edit { display: none; margin-top: var(--dl-space-4); max-width: 420px; }
.dl-account-name-edit.open { display: block; }

/* ── 19.19 Юридическая проза (privacy.php, /privacy — политика
   конфиденциальности, релиз-блокер Wayfare для Google Play + GDPR,
   2026-07-22). Спека §10 карточно-таблична и не описывает «страницу
   сплошного длинного текста» (политика/условия) как компонент; базовый
   dl.css тоже нигде не задаёт типографический ритм <p>/<ul>/<table>
   (везде точечные инлайн-отступы, ср. developer_billing_stub.php). Поэтому
   здесь ОДИН scoped prose-контейнер .dl-legal внутри .dl-card, читающий
   ТОЛЬКО существующие --dl-*-токены (ink/space/accent/border/radius/
   surface-2), без нового off-namespace значения — тем же принципом
   «переиспользуй токены, не заводи параллельный неймспейс», что и весь §19.
   Переиспользуемо будущей страницей /terms. */
.dl-legal { color: var(--dl-ink-soft); font-size: 15px; line-height: 1.7; }
.dl-legal .dl-h1 { margin-bottom: var(--dl-space-2); }
.dl-legal h2 {
  font-size: 18px;
  font-weight: 600;
  color: var(--dl-ink);
  margin: var(--dl-space-6) 0 var(--dl-space-3);
}
.dl-legal p { margin: 0 0 var(--dl-space-4); }
.dl-legal ul { margin: 0 0 var(--dl-space-4); padding-left: var(--dl-space-5); }
.dl-legal li { margin-bottom: var(--dl-space-2); }
.dl-legal li:last-child { margin-bottom: 0; }
.dl-legal strong { color: var(--dl-ink); font-weight: 600; }
.dl-legal a { color: var(--dl-accent); text-decoration: none; }
.dl-legal a:hover { text-decoration: underline; }
.dl-legal__effective {
  color: var(--dl-ink);
  font-weight: 600;
  margin-bottom: var(--dl-space-5) !important;
}
/* Обёртка вокруг <table> — узкий вьюпорт не должен растягивать 3-колоночную
   таблицу оснований GDPR и толкать всю страницу в горизонтальный скролл;
   скроллится только сама таблица (тот же приём локализации overflow-x, что
   §19-строки про .dl-container в комментариях выше по файлу). */
.dl-legal__table-wrap { overflow-x: auto; margin: 0 0 var(--dl-space-4); }
.dl-legal table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.dl-legal th,
.dl-legal td {
  text-align: left;
  padding: var(--dl-space-3);
  border: 1px solid var(--dl-border);
  vertical-align: top;
}
.dl-legal th {
  background: var(--dl-surface-2);
  color: var(--dl-ink);
  font-weight: 600;
}
