/* ════════════════════════════════════════════════════════════════════════
   КОНТЕНТ-СТРАНИЦЫ, СОБРАННЫЕ ГЕНЕРАТОРОМ (_build/)
   ────────────────────────────────────────────────────────────────────────
   Отдельный файл, а не дополнение components.css, сознательно: components.css
   подключён на всех 57 страницах, и правка в нём — это правка всего сайта
   разом. Здесь только классы, которых раньше не было, и подключается файл
   лишь на сгенерированных страницах. Регрессия на старых страницах невозможна
   по построению.

   Палитра — только токены из tokens.css. Правило бренда «1–2 акцента на экран»
   соблюдается: бирюза несёт смысл «навигация/структура», красный — только риск,
   жёлтый здесь не используется вовсе (он закреплён за CTA-кнопкой).
   ════════════════════════════════════════════════════════════════════════ */

/* ── Callout: совет / риск / заметка ─────────────────────────────────── */
.article-body .callout {
  display:block; margin:32px 0; padding:20px 24px;
  border:1px solid var(--line-2); border-left:3px solid var(--teal);
  border-radius:var(--r-md); background:var(--bg-2);
}
.article-body .callout-head {
  font-family:var(--font-mono); font-size:12px; letter-spacing:1px;
  text-transform:uppercase; color:var(--teal); margin-bottom:10px;
}
.article-body .callout-body > :first-child { margin-top:0; }
.article-body .callout-body > :last-child  { margin-bottom:0; }
.article-body .callout-risk { border-left-color:var(--code-red); }
.article-body .callout-risk .callout-head { color:var(--code-red); }
.article-body .callout-note { border-left-color:var(--line-2); }
.article-body .callout-note .callout-head { color:var(--txt-3); }

/* ── Таблицы ─────────────────────────────────────────────────────────── */
.article-body .tbl-wrap { overflow-x:auto; margin:28px 0; -webkit-overflow-scrolling:touch; }
/* ⚠️ min-width обязателен. Без него таблица с width:100% на узком экране не
   прокручивается, а СЖИМАЕТСЯ: колонки схлопываются и заголовки рвутся по
   слогам («ИНСТРУМЕ НТ»). Обёртка с overflow-x сама по себе не помогает —
   прокручивать нечего, пока содержимое не шире обёртки. Та же природа, что
   у ADR-0014 про горизонтальный выезд. */
.article-body .tbl-wrap table { min-width:460px; }
.article-body table {
  width:100%; border-collapse:collapse; font-size:15px;
  background:var(--bg-2); border:1px solid var(--line); border-radius:var(--r-md);
}
.article-body th, .article-body td {
  padding:12px 16px; text-align:left; border-bottom:1px solid var(--line);
}
.article-body th {
  font-family:var(--font-mono); font-size:12px; letter-spacing:.6px;
  text-transform:uppercase; color:var(--txt-3); font-weight:500;
}
.article-body td { color:var(--txt-2); }
.article-body tr:last-child td { border-bottom:0; }

/* ── Код ─────────────────────────────────────────────────────────────── */
.article-body pre {
  margin:28px 0; padding:18px 20px; background:var(--bg-3);
  border:1px solid var(--line); border-radius:var(--r-md); overflow-x:auto;
}
.article-body pre code { font-family:var(--font-mono); font-size:13.5px; color:var(--txt-2); }
.article-body :not(pre) > code {
  font-family:var(--font-mono); font-size:.9em; padding:2px 6px;
  background:var(--bg-3); border:1px solid var(--line); border-radius:var(--r-sm);
  color:var(--teal-l);
}

/* ── Картинка с подписью ─────────────────────────────────────────────── */
.article-body .art-fig { margin:32px 0; }
.article-body .art-fig img {
  width:100%; height:auto; display:block;
  border:1px solid var(--line); border-radius:var(--r-md);
}
.article-body .art-fig figcaption {
  margin-top:10px; font-family:var(--font-mono); font-size:12px;
  color:var(--txt-3); letter-spacing:.3px;
}

/* ── FAQ-аккордеон ───────────────────────────────────────────────────── */
.article-body .faq { margin:8px 0 40px; }
.article-body .faq-item {
  border-bottom:1px solid var(--line); padding:4px 0;
}
.article-body .faq-item summary {
  cursor:pointer; list-style:none; padding:16px 36px 16px 0; position:relative;
  font-weight:600; color:var(--txt); font-size:16.5px;
}
.article-body .faq-item summary::-webkit-details-marker { display:none; }
.article-body .faq-item summary::after {
  content:"+"; position:absolute; right:6px; top:50%; transform:translateY(-50%);
  font-family:var(--font-mono); font-size:20px; color:var(--teal); line-height:1;
  transition:transform var(--motion-fast) ease;
}
.article-body .faq-item[open] summary::after { content:"−"; }
.article-body .faq-a { padding:0 36px 18px 0; color:var(--txt-2); line-height:1.65; }

/* ── Источники ───────────────────────────────────────────────────────── */
.article-body .art-sources {
  margin:40px 0; padding:18px 22px; background:var(--bg-2);
  border:1px solid var(--line); border-radius:var(--r-md);
}
.article-body .art-sources h5 {
  margin:0 0 10px; font-family:var(--font-mono); font-size:11px;
  letter-spacing:1px; text-transform:uppercase; color:var(--txt-3); font-weight:500;
}
.article-body .art-sources ul { margin:0; padding-left:18px; }
.article-body .art-sources li { margin-bottom:6px; font-size:14.5px; }
.article-body .art-sources a { color:var(--txt-2); }
.article-body .art-sources a:hover { color:var(--teal); }

/* ── Карточка автора ─────────────────────────────────────────────────── */
.article-body .author-card {
  display:flex; gap:20px; align-items:flex-start; margin:40px 0;
  padding:24px; background:var(--bg-card); border:1px solid var(--line);
  border-radius:var(--r-card);
}
.article-body .author-photo {
  width:72px; height:72px; border-radius:50%; flex-shrink:0; object-fit:cover;
  border:1px solid var(--line-2);
}
.article-body .av-fallback {
  display:flex; align-items:center; justify-content:center;
  background:rgba(30,162,177,.14); color:var(--teal);
  font-family:var(--font-display); font-size:30px;
}
.article-body .author-name {
  font-family:var(--font-display); font-size:19px; text-transform:uppercase;
  letter-spacing:-.2px; color:var(--txt); text-decoration:none;
}
.article-body .author-name:hover { color:var(--teal); }
.article-body .author-exp {
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.5px;
  text-transform:uppercase; color:var(--txt-3); margin-top:4px;
}
.article-body .author-bio { margin:10px 0 0; font-size:15px; color:var(--txt-2); line-height:1.6; }
.article-body .author-links { margin-top:10px; display:flex; gap:14px; }
.article-body .author-links a { font-size:14px; color:var(--teal); }

/* ── CTA в Telegram ──────────────────────────────────────────────────── */
.article-body .tg-cta {
  display:flex; gap:24px; align-items:center; justify-content:space-between;
  flex-wrap:wrap; margin:40px 0; padding:28px;
  background:radial-gradient(600px 220px at 15% -40%, rgba(30,162,177,.18), transparent 70%), var(--bg-card);
  border:1px solid rgba(30,162,177,.32); border-radius:var(--r-card);
}
.article-body .tg-cta-title {
  font-family:var(--font-display); font-size:clamp(20px,2.4vw,26px);
  text-transform:uppercase; letter-spacing:-.4px; color:var(--txt);
}
.article-body .tg-cta-sub { margin:8px 0 0; font-size:15px; color:var(--txt-2); max-width:44ch; }

/* ── Читайте также ───────────────────────────────────────────────────── */
.article-body .art-related { margin:44px 0 8px; }
.article-body .art-related h5 {
  margin:0 0 16px; font-family:var(--font-mono); font-size:11px;
  letter-spacing:1px; text-transform:uppercase; color:var(--txt-3); font-weight:500;
}
.article-body .related-grid {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:14px;
}
.article-body .related-card {
  display:block; padding:18px 20px; background:var(--bg-2);
  border:1px solid var(--line); border-radius:var(--r-md);
  text-decoration:none; transition:border-color var(--motion-fast) ease;
}
.article-body .related-card:hover { border-color:rgba(30,162,177,.45); }
.article-body .related-cat {
  display:block; font-family:var(--font-mono); font-size:10.5px;
  letter-spacing:1px; text-transform:uppercase; color:var(--teal); margin-bottom:8px;
}
.article-body .related-title { color:var(--txt); font-weight:600; line-height:1.4; }

@media (max-width:640px) {
  .article-body .author-card { flex-direction:column; gap:14px; }
  .article-body .tg-cta { flex-direction:column; align-items:flex-start; }
}

/* ════════════════════════════════════════════════════════════════════════
   ХАБ ЗНАНИЙ — компоненты, перенесённые из инлайновых стилей courses.html
   ────────────────────────────────────────────────────────────────────────
   ⚠️ Правила скопированы, а не вынесены: courses.html остаётся нетронутой.
   Вынос означал бы правку боевой страницы ради новой — риск без нужды, пока
   /courses не переехал окончательно. Дубль временный и снимается вместе
   с переездом.

   Карточка материала, фильтры и переключатель разделов должны выглядеть
   ровно так же, как на остальном сайте: посетитель не должен видеть, что
   часть страниц собирает генератор, а часть написана руками.
   ════════════════════════════════════════════════════════════════════════ */
/* ════ ОБУЧЕНИЕ · хаб: КУРСЫ + СТАТЬИ-ОБУЧАЛКИ + ВИДЕО-УРОКИ ════
   Курсы — существующий каталог. Статьи-обучалки — вобрали blog-* объяснялки.
   Видео-уроки — вобрали контент /video (Kinescope-фасад). /video теперь редиректит сюда (#video).
   Стиль наследует courses/news/video: scoped .wrap/.sec/.sec-tag/.reveal + фасад-плеер. */
.wrap{max-width:var(--container);margin:0 auto}
.sec-tag{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--acc,var(--teal));margin-bottom:16px}
.sec-tag::before{content:"";width:18px;height:1px;background:var(--acc,var(--teal))}
.sec h2 .ac{color:var(--acc,var(--teal))}
.sec-lede{color:var(--txt-2);font-size:16px;line-height:1.6;max-width:660px}
.sec-headrow{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:40px}
/* ── ХАБ-НАВИГАЦИЯ (табы разделов) ── */
.hubnav{position:sticky;top:0;z-index:20;background:var(--bg-2);border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:14px var(--page-px)}
.hubnav-in{max-width:var(--container);margin:0 auto;display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.hubtab{font-family:var(--font-mono);font-size:12px;letter-spacing:.5px;text-transform:uppercase;color:var(--txt-2);background:var(--bg-3);border:1px solid var(--line);border-radius:var(--r-pill);padding:10px 18px;text-decoration:none;transition:color var(--motion-base),border-color var(--motion-base),background var(--motion-base)}
.hubtab:hover{border-color:var(--line-2);color:var(--txt)}
.hubtab.on{color:#001;background:linear-gradient(150deg,var(--teal),var(--teal-d));border-color:transparent;font-weight:600}



.hubtab{flex:none;white-space:nowrap}
.hh-name .ac{color:var(--teal)}
.artgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.artcard{position:relative;display:flex;flex-direction:column;background:var(--bg-card);border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;text-decoration:none;transition:transform var(--motion-base) var(--ease),border-color var(--motion-base)}
.artcard:hover{transform:translateY(-4px);border-color:var(--teal-d)}
.artcover{position:relative;aspect-ratio:16/8;background:linear-gradient(160deg,#15191b,#0c0e0f);color:var(--teal);overflow:hidden}
.artcover svg{position:absolute;inset:0;width:100%;height:100%}
.art-day{position:absolute;top:12px;right:12px;font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.6px;color:var(--teal);background:rgba(8,8,8,.7);border:1px solid rgba(30,162,177,.4);padding:4px 10px;border-radius:var(--r-pill)}
/* Плашка рубрики — ВНИЗУ СПРАВА, а не сверху слева: на обложках
   логотип DOBERINVEST стоит в левом верхнем углу, и плашка садилась
   ровно на него. Правый верхний занят датой, низ слева — подписью
   самой обложки. Свободен только правый нижний. */
.art-tag{position:absolute;bottom:12px;right:12px;font-family:var(--font-mono);font-size:10px;text-transform:uppercase;letter-spacing:.6px;color:var(--code-green-neon);background:rgba(8,8,8,.7);border:1px solid rgba(39,224,122,.4);padding:4px 10px;border-radius:var(--r-pill)}
.artbody{padding:20px;display:flex;flex-direction:column;gap:10px;flex:1}
.artcard h3{font-family:var(--font-display);text-transform:uppercase;font-size:17px;line-height:1.1;letter-spacing:-.3px;margin:0;color:var(--txt)}
.art-meta{margin-top:auto;display:flex;gap:10px;font-family:var(--font-mono);font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--txt-3)}
.vcard.hide{display:none}


.artfilters{margin:6px 0 22px}
.af-row{display:flex;flex-wrap:wrap;gap:8px}
.af-row.af-sub{margin-top:10px;padding-top:10px;border-top:1px solid rgba(255,255,255,.07)}
.af{font-family:var(--font-mono,'JetBrains Mono',monospace);font-size:12.5px;color:var(--txt-2,rgba(255,255,255,.65));background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.14);border-radius:100px;padding:8px 15px;cursor:pointer;transition:all .18s ease;white-space:nowrap;line-height:1}
.af:hover{border-color:var(--teal,#1EA2B1);color:#fff}
.af.on{background:rgba(30,162,177,.16);border-color:var(--teal,#1EA2B1);color:var(--teal-l,#2BC0D1);font-weight:600}

/* ── Обложка-заглушка для материалов без картинки ───────────────────────
   Половина материалов пока без обложки. Пустой <img> дал бы битую иконку,
   а карточка без обложки — разъехавшуюся сетку. Рисуем градиент с буквой
   раздела: место занято, сетка ровная, подмены смысла нет. */
.artcover.is-blank {
  display:flex; align-items:center; justify-content:center;
  background:
    radial-gradient(420px 200px at 20% -20%, rgba(30,162,177,.30), transparent 70%),
    linear-gradient(140deg, var(--bg-3), var(--bg-2));
}
.artcover.is-blank .blank-mark {
  font-family:var(--font-display); font-size:44px; font-weight:600;
  letter-spacing:-1px; color:rgba(255,255,255,.13); text-transform:uppercase;
}

/* ── Переключатель типа материала ───────────────────────────────────────
   Визуально это те же .hubtab, что на /courses, но здесь они фильтруют,
   а не прокручивают. Поэтому <button>, а не <a>: элемент без адреса не
   должен выглядеть ссылкой для программы чтения с экрана. */
.hubnav-in .hubtab { border:0; cursor:pointer; font:inherit; background:none; }

/* ⚠️ `background:none` выше снимал заливку и с АКТИВНОЙ вкладки тоже: правило
   идёт после `.hubtab.on` и при равной специфичности побеждает. Цвет текста
   при этом оставался от `.on` — почти чёрный, рассчитанный на бирюзовый фон.
   Получалось чёрное по тёмному: название выбранного раздела пропадало с
   экрана, а счётчик рядом исчезал совсем. Возвращаем заливку адресно. */
.hubnav-in .hubtab.on {
  background:linear-gradient(150deg, var(--teal), var(--teal-d));
  color:#001;
}

/* Скрытие отфильтрованного. Карточки остаются в HTML — их должен видеть
   поисковик; от посетителя прячется только то, что он сам отфильтровал. */
.artcard.hide { display:none; }

/* ⚠️ БЕЗ ЭТОГО ПРАВИЛА ФИЛЬТР НЕ РАБОТАЕТ ВООБЩЕ.
   Скрипт прячет сетки через `el.hidden = true`. Атрибут [hidden] даёт
   display:none стилем БРАУЗЕРА, а он слабее любого авторского правила —
   и `.artgrid{display:grid}` его перебивал. Три сетки (материалы, новости,
   лента канала) оставались на экране одновременно, поэтому в каждой рубрике
   показывалось одно и то же, а «События 0» открывали чужие карточки.
   Правило общее, а не только для .artgrid: та же ловушка ждёт любой
   элемент с display в стилях, который потом решат прятать атрибутом. */
[hidden] { display:none !important; }

/* ── Пустое состояние ──────────────────────────────────────────────────── */
.hub-empty { color:var(--txt-3); font-size:15px; padding:28px 0; }


/* ── Переключатель типа: доводка ────────────────────────────────────────
   ⚠️ При переносе стилей из courses.html я потерял обёртки @media, и правила
   из мобильной секции применились ко всем ширинам: ряд вкладок стал nowrap
   и обрезался справа — на 390px из пяти вкладок было видно две с половиной,
   без намёка на прокрутку. Ниже — явные правила вместо унаследованной каши. */
/* ⚠️ Шапка сайта — position:fixed высотой 91px на мобильном и 99px на десктопе
   (замерено, а не подобрано). Липкий ряд вкладок с top:0 уезжал ПОД неё, и
   верхняя строка вкладок была не видна. Сдвигаем на высоту шапки и даём
   scroll-margin, чтобы переход по якорю тоже не прятал ряд под шапкой. */
.hubnav { position:sticky; top:99px; z-index:20; scroll-margin-top:110px; }
.hubnav-in { flex-wrap:wrap; overflow:visible; }

/* Счётчик у вкладки. Без собственных стилей он слипался с подписью
   и читался как опечатка: «ВСЁ28», «КУРСЫ5». */
.hubtab .n {
  margin-left:8px; padding:2px 7px; border-radius:var(--r-pill);
  background:rgba(255,255,255,.08); color:var(--txt-3);
  font-size:11px; line-height:1.4; font-weight:500;
}
.hubtab.on .n { background:rgba(0,0,0,.22); color:rgba(0,0,0,.72); }

/* Активная вкладка должна читаться как активная. В исходном наборе .on давала
   тёмный текст на бирюзовом, но рядом с неактивными на тёмном фоне выглядела
   ТУСКЛЕЕ их — глаз выбирал не ту. Добавлен контур и вес. */
.hubtab { font-weight:500; }
.hubtab.on { box-shadow:0 0 0 1px rgba(43,192,209,.55), 0 6px 18px rgba(30,162,177,.22); }

@media (max-width: 560px) {
  /* На узком экране перенос по строкам честнее прокрутки: все типы видны
     сразу, и не нужно догадываться, что ряд можно листать вбок. */
  /* ⚠️ Перенос по строкам на телефоне давал ТРИ строки вкладок — липкий блок
     занимал треть экрана и закрывал карточки при прокрутке. Возвращаем одну
     строку с горизонтальной прокруткой, но с видимой подсказкой края: без неё
     ряд выглядит просто обрезанным, и о прокрутке никто не догадывается. */
  .hubnav { position:sticky; top:91px; scroll-margin-top:100px; }
  .hubnav-in {
    flex-wrap:nowrap; overflow-x:auto; gap:8px; -webkit-overflow-scrolling:touch;
    scrollbar-width:none; padding-right:26px;
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 34px),transparent);
            mask-image:linear-gradient(90deg,#000 calc(100% - 34px),transparent);
  }
  .hubnav-in::-webkit-scrollbar { display:none; }
  .hubtab { padding:9px 14px; font-size:11.5px; flex:0 0 auto; }
  /* Стрелка-подсказка поверх затухания: «здесь ещё есть». */
  .hubnav { position:sticky; }
  .hubnav::after {
    content:"›"; position:absolute; right:calc(var(--page-px) - 2px); top:50%;
    transform:translateY(-50%); font-family:var(--font-mono); font-size:20px;
    color:var(--txt-3); pointer-events:none;
  }
}

/* Мета карточки: ведущий разделитель «·» без первого элемента выглядел
   как случайная точка. Теперь разделители ставит сам список. */
.artcard .art-meta > span + span::before { content:"·"; margin:0 6px; color:var(--txt-4); }


/* ── Сетка карточек по ширинам ──────────────────────────────────────────
   ⚠️ В courses.html эти правила лежат в @media 960px и 640px. При переносе
   обёртки потерялись, три правила схлопнулись в одно, и победило последнее —
   мобильное. На десктопе 28 карточек выстроились В ОДНУ КОЛОНКУ, и заметить
   это по коду было нельзя: каждое правило по отдельности выглядело верным.
   Восстановлено с медиа-запросами; ширины те же, что на остальном сайте. */
@media (max-width: 960px) { .artgrid { grid-template-columns:1fr 1fr; } }
@media (max-width: 640px) { .artgrid { grid-template-columns:1fr; } }

/* Подсказка под рядом рубрик: «что произошло», «как сделать». Снимает вопрос,
   чем рубрики отличаются, не требуя отдельного объясняющего абзаца. */
.hub-hint {
  margin:14px 0 22px; font-family:var(--font-mono); font-size:12px;
  letter-spacing:.6px; text-transform:uppercase; color:var(--txt-3);
}

/* Метка черновика. Видна только на стенде: в бою черновики не отдаются вовсе.
   Нужна, чтобы при просмотре раздела было сразу понятно, что уже опубликовано,
   а что ещё нет — иначе стенд врёт о состоянии сайта. */
.artcard .draft-mark {
  display:inline-block; vertical-align:middle; margin-left:8px; padding:2px 8px;
  border-radius:var(--r-pill); background:rgba(255,179,0,.14); color:var(--warn);
  font-family:var(--font-mono); font-size:10px; letter-spacing:.8px;
  text-transform:uppercase; font-weight:500;
}

/* Плашка черновика на стенде. Без неё черновик на вид неотличим от боевой
   страницы, и легко решить, что материал уже опубликован. */
.draft-banner {
  display:inline-block; margin-bottom:18px; padding:8px 16px;
  border:1px solid rgba(255,179,0,.4); border-radius:var(--r-pill);
  background:rgba(255,179,0,.10); color:var(--warn);
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:.6px;
  text-transform:uppercase;
}

/* ── «Данные недели» внутри рубрики новостей ────────────────────────────
   Компактный список вышедших макро-релизов. На странице /news это был
   большой блок с группировкой по дням; здесь он сжат до сути — что вышло
   и с каким значением. Полную версию тащить не стали: она завязана на
   десяток элементов той страницы, и перенос означал бы перенос половины
   страницы ради одного блока. */
.eco-week {
  margin:0 0 26px; padding:20px 24px; background:var(--bg-2);
  border:1px solid var(--line); border-radius:var(--r-md);
}
.eco-week h3 {
  margin:0 0 14px; font-family:var(--font-mono); font-size:11px;
  letter-spacing:1px; text-transform:uppercase; color:var(--txt-3); font-weight:500;
}
.eco-week ul { margin:0; padding:0; list-style:none; }
.eco-week li {
  display:flex; justify-content:space-between; gap:16px; padding:9px 0;
  border-bottom:1px solid var(--line);
}
.eco-week li:last-child { border-bottom:0; }
.eco-name { color:var(--txt-2); font-size:14.5px; }
.eco-val  { font-family:var(--font-mono); font-size:13.5px; color:var(--teal); white-space:nowrap; }

/* ── Лента чужих новостей ────────────────────────────────────────────────
   Список, а не карточки. У новости в снапшоте нет картинки ни у одной из
   девяноста с лишним: карточки давали стену серых прямоугольников с буквой
   «Н». Список показывает то, что у чужого заголовка реально есть, —
   источник, время и сам заголовок. */
/* ⚠️ Колонки потоком (columns), а не grid. В сетке строка тянется по самому
   высокому элементу: у новости с описанием высота вдвое больше, чем у голого
   заголовка, и рядом с ней оставалась дыра в полкарточки. Поток раскладывает
   элементы по высоте и дыр не создаёт. */
.newsfeed {
  list-style:none; margin:0; padding:0;
  columns:2; column-gap:16px;
}
.newsfeed li { break-inside:avoid; margin:0 0 10px; }
.nf-item {
  display:block; padding:14px 16px; text-decoration:none;
  background:var(--bg-2); border:1px solid var(--line);
  border-left:2px solid var(--line-2); border-radius:var(--r-md);
  transition:border-color var(--motion-base), background var(--motion-base);
}
.nf-item:hover { border-color:var(--line-2); border-left-color:var(--teal); background:var(--bg-3); }
.nf-head {
  display:flex; align-items:center; gap:10px; margin-bottom:7px;
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.6px;
  text-transform:uppercase;
}
.nf-src { color:var(--teal); }
.nf-time { color:var(--txt-4); }
.nf-time::before { content:"·"; margin-right:10px; color:var(--txt-4); }
.nf-title {
  margin:0; font-family:var(--font-body); font-weight:600;
  font-size:15px; line-height:1.35; color:var(--txt);
  letter-spacing:0; text-transform:none;
}
.nf-item:hover .nf-title { color:var(--teal-l); }
.nf-sum { margin:6px 0 0; font-size:13.5px; line-height:1.5; color:var(--txt-3); }

@media (max-width: 900px) { .newsfeed { columns:1; } }

/* Код страны перед названием показателя: без него «Инфляция CPI» четырёх
   разных стран в одном списке выглядит как одна строка, повторённая четырежды. */
.eco-cc {
  display:inline-block; min-width:26px; margin-right:10px;
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.6px;
  color:var(--txt-4); text-transform:uppercase;
}
/* Прогноз приглушён: факт и ожидание не должны читаться одинаково. */
.eco-val.is-fc { color:var(--txt-3); }

/* ════════════════════════════════════════════════════════════════════════
   КАРТА РАЗДЕЛА «ЖУРНАЛ»
   ────────────────────────────────────────────────────────────────────────
   Заменила плоский ряд пилюль. По пилюлям нельзя было понять, что внутри,
   не потыкав каждую: семь одинаковых овалов с числами и ничего больше.
   Плитка несёт номер, имя, счётчик, строку о содержимом и полосу объёма.

   Торговый характер собран из того, что в терминале и так есть, а не из
   украшений: моноширинные табличные цифры, нумерация позиций, полоса
   объёма под строкой. Полоса — это данные (доля рубрики от самой крупной),
   поэтому она имеет право на существование; декоративной графики здесь нет.
   ════════════════════════════════════════════════════════════════════════ */
.jmap { margin:0 0 28px; }
.jmap-head {
  display:flex; align-items:baseline; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin-bottom:14px;
  padding-bottom:12px; border-bottom:1px solid var(--line);
}
.jmap-kicker {
  font-family:var(--font-mono); font-size:11px; letter-spacing:1.4px;
  text-transform:uppercase; color:var(--teal);
}
.jmap-pulse {
  font-family:var(--font-mono); font-size:11px; letter-spacing:.6px;
  text-transform:uppercase; color:var(--txt-3);
  font-variant-numeric:tabular-nums;
}

.jmap-grid { display:grid; grid-template-columns:repeat(3, 1fr); gap:10px; }

.jtile {
  display:flex; flex-direction:column; gap:4px;
  padding:14px 16px 12px; text-align:left; cursor:pointer;
  background:var(--bg-2); border:1px solid var(--line);
  border-radius:var(--r-md); font:inherit; color:inherit;
  transition:border-color var(--motion-base), background var(--motion-base),
             transform var(--motion-base) var(--ease);
}
.jtile:hover { border-color:var(--teal-d); background:var(--bg-3); transform:translateY(-2px); }
.jtile:focus-visible { outline:2px solid var(--teal); outline-offset:2px; }

.jt-top { display:flex; align-items:baseline; justify-content:space-between; }
.jt-idx {
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:1px;
  color:var(--txt-4); font-variant-numeric:tabular-nums;
}
.jt-n {
  font-family:var(--font-mono); font-size:17px; font-weight:600;
  color:var(--teal); font-variant-numeric:tabular-nums; line-height:1;
}
.jt-name {
  font-family:var(--font-display); font-size:17px; text-transform:uppercase;
  letter-spacing:-.2px; color:var(--txt); line-height:1.05;
}
.jt-hint { font-size:13px; color:var(--txt-3); line-height:1.35; }

/* Полоса объёма: доля рубрики от самой крупной. Считается от максимума,
   а не от суммы — иначе крупнейшая занимала бы полплитки, а остальные
   сливались бы с нулём и читались как пустые. */
.jt-bar {
  display:block; height:2px; margin-top:8px; border-radius:2px;
  background:rgba(255,255,255,.06); overflow:hidden;
}
.jt-bar i {
  display:block; height:100%; border-radius:2px;
  background:linear-gradient(90deg, var(--teal-d), var(--teal));
  transition:filter var(--motion-base);
}
.jtile:hover .jt-bar i { filter:brightness(1.35); }

/* Пустая рубрика приглушена, но остаётся нажимаемой: она честно показывает
   план раздела. Спрятать её — значит скрыть от читателя, что тут будет. */
.jtile.is-empty { opacity:.5; }
.jtile.is-empty .jt-n { color:var(--txt-4); }
.jtile.is-empty .jt-bar { background:rgba(255,255,255,.04); }

.jtile.on {
  border-color:var(--teal);
  background:linear-gradient(150deg, rgba(30,162,177,.16), rgba(30,162,177,.05));
  box-shadow:0 0 0 1px rgba(43,192,209,.35), 0 8px 22px rgba(30,162,177,.14);
  opacity:1;
}
.jtile.on .jt-n { color:var(--teal-l); }

.jmap-all {
  margin-top:10px; width:100%; padding:11px 16px; cursor:pointer;
  font-family:var(--font-mono); font-size:11.5px; letter-spacing:1px;
  text-transform:uppercase; color:var(--txt-2);
  background:var(--bg-2); border:1px solid var(--line);
  border-radius:var(--r-md);
  transition:color var(--motion-base), border-color var(--motion-base), background var(--motion-base);
}
.jmap-all:hover { color:var(--txt); border-color:var(--line-2); }
.jmap-all .n {
  margin-left:10px; color:var(--teal); font-variant-numeric:tabular-nums;
}
.jmap-all.on {
  color:#001; background:linear-gradient(150deg, var(--teal), var(--teal-d));
  border-color:transparent; font-weight:600;
}
.jmap-all.on .n { color:rgba(0,0,0,.66); }

/* «Где я сейчас»: внутри рубрики читатель не должен прокручивать обратно
   к карте, чтобы вспомнить, что он выбрал. */
.jnow {
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  margin:0 0 18px; padding:10px 14px;
  background:var(--bg-2); border:1px solid var(--line);
  border-left:2px solid var(--teal); border-radius:var(--r-md);
}
.jnow-label {
  font-family:var(--font-mono); font-size:11px; letter-spacing:1px;
  text-transform:uppercase; color:var(--txt-2); font-variant-numeric:tabular-nums;
}
.jnow-reset {
  flex:none; cursor:pointer; padding:5px 12px;
  font-family:var(--font-mono); font-size:10.5px; letter-spacing:.8px;
  text-transform:uppercase; color:var(--txt-3);
  background:none; border:1px solid var(--line); border-radius:var(--r-pill);
  transition:color var(--motion-base), border-color var(--motion-base);
}
.jnow-reset:hover { color:var(--teal); border-color:var(--teal-d); }

@media (max-width: 860px) { .jmap-grid { grid-template-columns:repeat(2, 1fr); } }
@media (max-width: 480px) {
  /* Две колонки, а не одна: шесть плиток в столбик занимали пол-экрана
     прокрутки до первого материала. Содержимое плитки короткое и в 170px
     помещается, поэтому сжатие ничего не ломает. */
  .jmap-grid { gap:8px; }
  .jtile { padding:11px 12px 9px; }
  .jt-name { font-size:15px; }
  .jt-n { font-size:15px; }
  .jt-hint { font-size:12px; }
  .jmap-head { flex-direction:column; align-items:flex-start; gap:6px; }
  .jnow { flex-direction:column; align-items:flex-start; gap:10px; }
}

/* ⚠️ Верхний отступ раздела урезан с 160px до 40px, и только на хабе.
   Токен --section-py задуман для смысловых блоков главной, где воздух
   между ними — часть ритма. Здесь под шапкой идёт КАРТА РАЗДЕЛА, то есть
   навигация: она относится к заголовку, а не живёт отдельной секцией.
   При 160px сверху плюс 60px снизу у шапки между ними зияло 220 пикселей
   пустоты, и первый экран не показывал ничего, кроме заголовка. */
.section-hub { padding-top:40px; }

/* Кнопка «показать всё» — это состояние по умолчанию, поэтому кричать ей
   не о чем. Сплошная бирюзовая полоса во всю ширину перетягивала внимание
   с плиток, ради которых карта и сделана. Внутри рубрики та же кнопка
   становится дорогой назад — там заметность уместна, но не заливкой. */
.jmap-all.on {
  color:var(--teal-l);
  background:linear-gradient(150deg, rgba(30,162,177,.14), rgba(30,162,177,.04));
  border-color:rgba(43,192,209,.45);
  font-weight:500;
}
.jmap-all.on .n { color:var(--teal); }
