/* ==========================================================================
   04-prose.css — оформление длинных текстов: страница статьи, .post-content
   и вся подсветка кода (переопределения Prism).
   Подключается ПОСЛЕДНИМ из ядра, и это принципиально: правила здесь
   уточняют и компоненты (.post-content code перебивает общий .card-text),
   и, что важнее, конкурируют с prism.min.css — та подключена в base.html
   ПОСЛЕ всех наших стилей, поэтому здесь используются либо префикс :root
   (поднимает вес до 0-2-0), либо !important. Отодвинуть 04 выше по порядку
   нельзя: часть переопределений Prism держится ровно на этом.

   Внутри (в исходном порядке blog.css):
     • .blog-post*, .post-content (типографика, медиа, таблицы), .post-tags,
       .back-link;
     • блок CODE SYNTAX HIGHLIGHTING: .post-content pre/code[class*=language-],
       номера строк, ярлыки языков, тёмная и светлая правки;
     • :root .token.* — палитра Prism, привязанная к теме сайта;
     • кнопка «копировать», адаптив, инлайновый код.

   О ПОРЯДКЕ: блок .blog-post/.post-content в blog.css лежал ВЫШЕ .row/
   .col-md-6 и облака тегов, которые ушли в 03-components.css, — то есть
   здесь он оказался ниже них. Это безопасно: селекторы .post-content*,
   .post-tags, .back-link и .row/.col-md-6/.main-content .tag-cloud-* не
   пересекаются ни на одном элементе. Переменные --prism-* переехали
   в 00-tokens.css, правила :root .token.* остались тут.
   ========================================================================== */

/* Post detail styles */
.blog-post {
    background-color: var(--card);
    border-radius: var(--radius);
    padding: 2rem;
    border: 1px solid var(--border);
    margin-bottom: 2rem;
}

.blog-post-title {
    color: var(--foreground);
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 1rem;
    line-height: 1.2;
}

.blog-post-meta {
    color: var(--muted-foreground);
    font-size: 0.875rem;
    margin-bottom: 1.5rem;
}

.post-content {
    color: var(--foreground);
    line-height: 1.75;
    font-size: 1.0625rem; /* ~17px — comfortable long-form reading size */
}

.post-content h1,
.post-content h2,
.post-content h3,
.post-content h4,
.post-content h5,
.post-content h6 {
    color: var(--foreground);
    margin-top: 2rem;
    margin-bottom: 1rem;
}

.post-content p {
    margin-bottom: 1rem;
}

.post-content code {
    background-color: var(--muted);
    color: var(--foreground);
    padding: 0.2rem 0.4rem;
    border-radius: 0.25rem;
    font-family: var(--font-mono);
    font-size: 0.875em;
}

.post-content pre {
    background-color: var(--muted);
    color: var(--foreground);
    padding: 1rem;
    border-radius: var(--radius);
    overflow-x: auto;
    margin: 1rem 0;
}

.post-content pre code {
    background-color: transparent;
    padding: 0;
}

/* Media and wide content inside rendered articles. post.content is authored
   markdown rendered raw, so images/tables/iframes can be wider than the
   phone viewport. Constrain them so the article body never forces horizontal
   scroll; wide tables scroll within their own box instead of the page. */
/* Порядок двух объявлений значим: word-wrap — это устаревшее имя того же
   свойства overflow-wrap, поэтому legacy-алиас идёт ПЕРВЫМ, а актуальное
   значение вторым, иначе оно затрётся.
   `anywhere` вместо `break-word` выбрано осознанно: переносят они одинаково
   (слово рвётся, только если целиком не влезает в строку), но `anywhere`, в
   отличие от `break-word`, УЧИТЫВАЕТСЯ при расчёте min-content. Именно это
   нужно после снятия Bootstrap: длинный URL или неразрывный идентификатор в
   абзаце больше не раздувает дорожку грида (см. min-width: 0 в 02-layout.css).
   На вид ничего не меняется, меняется внутренняя ширина блока. */
.post-content {
    word-wrap: break-word;
    overflow-wrap: anywhere;
}
.post-content img {
    max-width: 100%;
    height: auto;
}
.post-content table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    /* Отменяем унаследованный от .post-content `anywhere` — он губителен
       именно для таблиц. `anywhere` учитывается при расчёте min-content, то
       есть минимальная ширина колонки становится равной ОДНОЙ БУКВЕ: вместо
       прокрутки таблица схлопывается, а текст ячеек рассыпается в вертикальный
       столбик (замерено: 10 колонок по 27px при высоте строки 240px).
       `break-word` переносит длинные слова так же, но на min-content не влияет —
       колонки сохраняют ширину по самому длинному слову, а таблица целиком
       уезжает в собственную горизонтальную прокрутку, как и задумано. */
    overflow-wrap: break-word;
}
.post-content iframe,
.post-content video,
.post-content embed {
    max-width: 100%;
}
/* ДЛИННАЯ СТРОКА КОДА: ПРОКРУТКА ВНУТРИ БЛОКА, А НЕ РАЗРЫВ ИДЕНТИФИКАТОРА.

   Вместе с Bootstrap ушло его `pre { word-break: break-all; word-wrap:
   break-word }`. Оно рвало строку в произвольном месте — `getElement` мог
   разъехаться на `getEle` + `ment`, — зато держало min-content блока
   маленьким, и никто не замечал, что дорожка грида не умеет сжиматься.
   Возвращать break-all не нужно: для кода это плохо читается. Правильное
   поведение — строка остаётся целой, а блок прокручивается сам:

     white-space: pre     — перенос запрещён, идентификатор не рвётся
                            (это же UA-умолчание для <pre>, но объявляем явно:
                            дальше по файлу и в prism.min.css есть свои правила);
     overflow-wrap: normal — гасит унаследованный от .post-content `anywhere`.
                            Он нужен абзацам, но если <pre> когда-нибудь получит
                            white-space: pre-wrap (плагин переноса у Prism,
                            другая тема), `anywhere` начнёт рвать код посреди
                            слова. Здесь это отключено адресно;
     overflow-x: auto     — горизонтальная полоса появляется У БЛОКА;
     max-width/min-width  — блок не шире родителя и не мешает дорожке грида
                            сжаться, если сам окажется элементом сетки.

   Селекторы перечислены оба: подсвеченный Prism <pre class="language-…">
   иначе получил бы эти свойства из prism.min.css, а она подключена ПОСЛЕ
   наших стилей. Специфичность (0,2,1) против её (0,1,1) — наше побеждает. */
.post-content pre,
.post-content pre[class*="language-"] {
    white-space: pre;
    overflow-wrap: normal;
    word-break: normal;
    overflow-x: auto;
    max-width: 100%;
    min-width: 0;
}

.post-tags a {
    text-decoration: none;
}

.post-tags a:hover {
    text-decoration: underline;
}

.back-link {
    margin-bottom: 1rem;
}

.back-link a {
    color: var(--primary);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
}

.back-link a:hover {
    text-decoration: underline;
}
/* ========================================================================== */
/* CODE SYNTAX HIGHLIGHTING STYLES */
/* ========================================================================== */

/* Override Prism.js default styles to match our theme */
.post-content pre[class*="language-"] {
    background-color: transparent !important;
    border: none;
    border-radius: 0;
    padding: 1.5rem 0 !important;
    margin: 1.5rem 0 !important;
    overflow-x: auto;
    position: relative;
    font-size: 0.9rem;
    line-height: 1.7;
    box-shadow: none;
}

.post-content code[class*="language-"] {
    background: transparent !important;
    padding: 0 !important;
    border-radius: 0 !important;
    font-family: var(--font-mono) !important;
    font-size: inherit !important;
    color: inherit !important;
    font-weight: 400 !important;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Line numbers styling */
.post-content .line-numbers .line-numbers-rows {
    border-right: 1px solid var(--border);
    padding-right: 1rem;
    margin-right: 1rem;
    color: var(--muted-foreground);
    user-select: none;
    pointer-events: none;
}

.post-content .line-numbers-rows > span {
    display: block;
    line-height: 1.6;
    font-size: 0.875rem;
    font-family: var(--font-mono);
}

/* Language label */
.post-content pre[class*="language-"]::before {
    content: attr(class);
    position: absolute;
    top: 0.5rem;
    right: 0rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--muted-foreground);
    background-color: transparent;
    padding: 0.25rem 0.5rem;
    border-radius: 0;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    opacity: 0.6;
    border-bottom: 1px solid var(--border);
}

/* Remove language prefix from label */
.post-content pre[class*="language-"]::before {
    content: attr(class);
    content: attr(class);
    content: attr(class);
}

.post-content pre[class*="language-go"]::before { content: "Go"; }
.post-content pre[class*="language-python"]::before { content: "Python"; }
.post-content pre[class*="language-javascript"]::before { content: "JavaScript"; }
.post-content pre[class*="language-js"]::before { content: "JavaScript"; }
.post-content pre[class*="language-typescript"]::before { content: "TypeScript"; }
.post-content pre[class*="language-java"]::before { content: "Java"; }
.post-content pre[class*="language-cpp"]::before { content: "C++"; }
.post-content pre[class*="language-c"]::before { content: "C"; }
.post-content pre[class*="language-csharp"]::before { content: "C#"; }
.post-content pre[class*="language-php"]::before { content: "PHP"; }
.post-content pre[class*="language-ruby"]::before { content: "Ruby"; }
.post-content pre[class*="language-rust"]::before { content: "Rust"; }
.post-content pre[class*="language-markup"]::before { content: "HTML"; }
.post-content pre[class*="language-css"]::before { content: "CSS"; }
.post-content pre[class*="language-sql"]::before { content: "SQL"; }
.post-content pre[class*="language-bash"]::before { content: "Bash"; }
.post-content pre[class*="language-yaml"]::before { content: "YAML"; }
.post-content pre[class*="language-json"]::before { content: "JSON"; }
.post-content pre[class*="language-markdown"]::before { content: "Markdown"; }
.post-content pre[class*="language-dockerfile"]::before { content: "Dockerfile"; }
.post-content pre[class*="language-nginx"]::before { content: "Nginx"; }

/* Dark theme adjustments for code blocks */
body[data-theme="dark"] .post-content pre[class*="language-"] {
    background-color: transparent !important;
    border: none;
    box-shadow: none;
}

body[data-theme="dark"] .post-content .line-numbers .line-numbers-rows {
    border-right-color: rgba(255, 255, 255, 0.1);
    color: rgba(255, 255, 255, 0.4);
}

body[data-theme="dark"] .post-content pre[class*="language-"]::before {
    background-color: transparent;
    color: rgba(255, 255, 255, 0.6);
    font-weight: 600;
}

body[data-theme="dark"] .post-content code[class*="language-"] {
    color: #e6e6e6 !important;
    text-shadow: none;
}

/* Light theme adjustments for code blocks */
body[data-theme="light"] .post-content pre[class*="language-"] {
    background-color: transparent !important;
    border: none;
    box-shadow: none;
}

body[data-theme="light"] .post-content .line-numbers .line-numbers-rows {
    border-right-color: rgba(0, 0, 0, 0.1);
    color: rgba(0, 0, 0, 0.4);
}

body[data-theme="light"] .post-content pre[class*="language-"]::before {
    background-color: transparent;
    color: rgba(0, 0, 0, 0.6);
    font-weight: 600;
}

body[data-theme="light"] .post-content code[class*="language-"] {
    color: #2d3748 !important;
    text-shadow: none;
}
/* --------------------------------------------------------------------------
   Палитра Prism, привязанная к теме сайта.

   В <head> подключается ровно одна нейтральная (светлая) тема Prism 1.29.0
   с cdnjs. Раньше рядом с ней висела тёмная через
   media="(prefers-color-scheme: dark)", но тема сайта живёт в localStorage и
   выставляется атрибутом data-theme — из-за этого подсветка кода расходилась
   с интерфейсом (светлая ОС + тёмная тема сайта = светлый код на тёмном фоне).
   Здесь тот же набор токенов задаётся дважды — для светлой и тёмной темы
   сайта, — и применяется к селекторам Prism.

   Про специфичность: prism.min.css подключён ПОСЛЕ ядра стилей (этот файл —
   последний из пяти), поэтому правила
   вида `.token.comment` (0,1,0) проигрывают ему при равном весе. Префикс
   `:root` поднимает вес до (0,2,0) и делает переопределение рабочим без
   !important.
   -------------------------------------------------------------------------- */
:root code[class*="language-"],
:root pre[class*="language-"] {
  color: var(--prism-fg);
  text-shadow: var(--prism-text-shadow);
}

:root :not(pre) > code[class*="language-"],
:root pre[class*="language-"] {
  background: var(--prism-bg);
}

:root code[class*="language-"]::selection,
:root pre[class*="language-"]::selection,
:root code[class*="language-"] ::selection,
:root pre[class*="language-"] ::selection {
  background: var(--prism-selection-bg);
  text-shadow: none;
}

:root .token.comment,
:root .token.prolog,
:root .token.doctype,
:root .token.cdata {
  color: var(--prism-comment);
}

:root .token.punctuation {
  color: var(--prism-punctuation);
}

:root .token.property,
:root .token.tag,
:root .token.boolean,
:root .token.number,
:root .token.constant,
:root .token.symbol,
:root .token.deleted {
  color: var(--prism-property);
}

:root .token.selector,
:root .token.attr-name,
:root .token.string,
:root .token.char,
:root .token.builtin,
:root .token.inserted {
  color: var(--prism-string);
}

:root .token.operator,
:root .token.entity,
:root .token.url,
:root .language-css .token.string,
:root .style .token.string {
  color: var(--prism-operator);
  background: var(--prism-operator-bg);
}

:root .token.atrule,
:root .token.attr-value,
:root .token.keyword {
  color: var(--prism-keyword);
}

:root .token.function,
:root .token.class-name {
  color: var(--prism-function);
}

:root .token.regex,
:root .token.important,
:root .token.variable {
  color: var(--prism-variable);
}
/* Copy button styling */
.post-content pre[class*="language-"] {
    position: relative;
}

.post-content .copy-code-btn {
    position: absolute;
    top: 0.5rem;
    right: 3rem;
    background-color: transparent;
    color: var(--muted-foreground);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    cursor: pointer;
    opacity: 0.6;
    transition: all 0.2s ease;
    z-index: 10;
    font-weight: 500;
}

.post-content .copy-code-btn:hover {
    opacity: 1;
    /* На ховере кнопка заливается, а подпись «Копировать» лежит поверх. */
    background-color: var(--primary-surface);
    color: var(--primary-foreground);
    border-color: var(--primary-surface);
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .post-content pre[class*="language-"] {
        padding: 1rem 0 !important;
        font-size: 1.1rem;
        margin: 1rem 0 !important;
        line-height: 1.6;
    }
    
    .post-content pre[class*="language-"]::before {
        font-size: 0.7rem;
        top: 0.25rem;
        right: 0.75rem;
    }
    
    .post-content .copy-code-btn {
        font-size: 0.7rem;
        top: 0.25rem;
        right: 2.5rem;
        padding: 0.2rem 0.4rem;
    }
}

/* Inline code styling (not in pre blocks) */
.post-content code:not([class*="language-"]) {
    background-color: transparent;
    color: var(--foreground);
    padding: 0.2rem 0.4rem;
    border-radius: 0;
    font-family: var(--font-mono);
    font-size: 1.1em;
    border: none;
    font-weight: 500;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    border-bottom: 1px solid var(--border);
}

body[data-theme="dark"] .post-content code:not([class*="language-"]) {
    background-color: transparent;
    border-color: rgba(255, 255, 255, 0.2);
    color: #e6e6e6;
}

body[data-theme="light"] .post-content code:not([class*="language-"]) {
    background-color: transparent;
    border-color: rgba(0, 0, 0, 0.2);
    color: #2d3748;
}

/* ==========================================================================
   ПОЛЬЗОВАТЕЛЬСКИЕ ПРЕДПОЧТЕНИЯ В ПРОЗЕ (этап 10.6)

   prefers-reduced-motion здесь СОЗНАТЕЛЬНО ПУСТ. Во всём файле ровно один
   источник движения — `transition: all 0.2s ease` у .copy-code-btn, и его
   полностью закрывает глобальное правило из 01-base.css: кнопка просто
   меняет вид мгновенно, конечное состояние прежнее. Заводить здесь блок
   ради «чтобы был» — лишний код, который потом придётся синхронизировать.
   ========================================================================== */

@media (prefers-contrast: more) {
  /* Кнопка «Копировать» живёт при opacity: 0.6, чтобы не спорить с кодом.
     Замер (цвет --muted-foreground, подложка --muted, sRGB после конверсии
     из oklch):
       светлая: #50565A на #E9F0F5 → 6.43:1, но при opacity 0.6 фактический
                цвет становится #8D9398 → 2.67:1
       тёмная:  #8F8F8F на #0B0B0B → 6.08:1, при opacity 0.6 → #5A5A5A → 2.86:1
     Прозрачность гасит и рамку кнопки: та падает ниже 3:1 из SC 1.4.11.
     При запросе повышенного контраста снимаем прозрачность целиком —
     возвращаются те самые 6.43:1 / 6.08:1.

     ВНИМАНИЕ: 2.67:1 — это провал AA (нужно 4.5:1) и в ОБЫЧНОМ режиме тоже.
     Здесь правка ограничена prefers-contrast намеренно: безусловное
     изменение поменяло бы внешний вид всем, а это уже вопрос контрастного
     аудита, а не этапа про движение. Вынесено в отчёт этапа. */
  .post-content .copy-code-btn {
    opacity: 1;
  }

  /* Инлайновый <code> обведён рамкой с альфой 0.2 — на фоне статьи это
     примерно 1.6:1, то есть рамки фактически нет. Токен --border под
     prefers-contrast: more уже подменён на --border-interactive
     (01-base.css), поэтому здесь достаточно перестать перебивать его
     хардкодом с альфой: обе ветки темы возвращаются на токен и получают
     3.4–3.9:1. Селекторы повторяют исходные (0,3,1) — иначе не перебить. */
  body[data-theme="dark"] .post-content code:not([class*="language-"]),
  body[data-theme="light"] .post-content code:not([class*="language-"]) {
    border-color: var(--border);
  }
}
