:root {
  --border-color: rgba(85, 85, 85, 1);

  --primary-text-color: rgba(245, 245, 245, .6);
  --primary-text-color__active: rgba(245, 245, 245, 1);

  --primary-background-color: rgba(48, 48, 48, 1);
  --container-background-color: rgba(39, 39, 39, 1);
  --container-background-color__dark: rgba(36, 36, 36, 1);
  --section-background-color: rgba(46, 46, 46, 1);
  --section-background-color__hover: rgba(53, 53, 53, 1);

  --button-text-color: rgba(245, 245, 245, 1);
  --button-background-color: rgba(58, 58, 58, 1);

  /*
    акцентные цвета контента поста: ссылка, инлайн-код, подсветка синтаксиса.
    тёплая приглушённая гамма без синего — ближе к серым сайта. это закрытый
    список: одинаково нужен и читателю (MarkdownRenderer), и автору
    (RichTextEditor), поэтому живёт здесь, а не в двух копиях внутри компонентов
  */
  --md-link: rgba(198, 155, 105, 1);
  --md-link-hover: rgba(214, 178, 132, 1);
  --md-inline-code: rgba(224, 175, 104, 1);

  --md-syntax-keyword: rgba(198, 155, 105, 1);
  --md-syntax-string: rgba(158, 190, 106, 1);
  --md-syntax-number: rgba(224, 175, 104, 1);
  --md-syntax-title: rgba(214, 140, 100, 1);
  --md-syntax-builtin: rgba(181, 168, 130, 1);
  --md-syntax-comment: rgba(150, 150, 150, .8);
  --md-syntax-deletion: rgba(214, 108, 108, 1);

  /* затемняющие оверлеи: поверх картинок и под модалкой, не цвет темы */
  --overlay-color: rgba(0, 0, 0, .5);
  --overlay-color__strong: rgba(0, 0, 0, .7);
}

/*
  светлая тема: тот же закрытый список переменных, монохромные значения. кнопка графитовая
  со светлым текстом — от неё пляшет вся гамма: поверхности идут ступенями серого от фона
  страницы к белой карточке, цвета нет нигде. направление относительно тёмной темы
  инвертировано (карточки светлее фона), но __dark по-прежнему темнее своей пары — на нём
  держатся шапка код-блока и плашка о подтверждении email. приглушённый текст ~4.7:1
  и бордер ~1.6:1 повторяют соотношения тёмной темы, поэтому читаемость не меняется.
  оверлеи не переопределяем: они лежат поверх картинок и под модалкой и затемняют всегда
*/
:root[data-theme="light"] {
  --border-color: rgba(184, 184, 184, 1);

  /* основной текст — #111, как на spy-soft.net (~18:1 на белой карточке); приглушённый — светлее, но
     не ниже 4.5:1 на белой карточке. оба сплошные, без прозрачности: они ложатся и на белую карточку,
     и на серый фон */
  --primary-text-color: rgba(115, 115, 115, 1);
  --primary-text-color__active: rgba(17, 17, 17, 1);

  --primary-background-color: rgba(232, 232, 232, 1);
  --container-background-color: rgba(245, 245, 245, 1);
  --container-background-color__dark: rgba(228, 228, 228, 1);
  --section-background-color: rgba(255, 255, 255, 1);
  /* наведение уводит карточку и таб в фон страницы: собственный оттенок между белой
     карточкой и фоном получался слишком светлым и наведение не читалось */
  --section-background-color__hover: var(--primary-background-color);

  /* кнопка графитовая, а не чёрная: чистый #000 со слепяще-белым текстом резал глаз.
     тон совпадает с основным текстом — кнопка и заголовки одного веса, контраст ~11:1 */
  --button-text-color: rgba(245, 245, 245, 1);
  --button-background-color: rgba(58, 58, 58, 1);

  /* затемнение под текстом слайдера: .7 на светлой теме читается как провал посреди
     страницы, вуали хватает и более лёгкой. второй оверлей (плашки и подложка модалки)
     остаётся общим для обеих тем */
  --overlay-color__strong: rgba(0, 0, 0, .5);

  /* ссылка в тексте поста — сине-фиолетовая, как на spy-soft.net (~8:1 на белом, подчёркивание остаётся);
     подсветка синтаксиса цветная: серыми ступенями код не читается. гамма подобрана под светлый фон —
     каждый цвет держит 5-6:1 */
  --md-link: rgba(50, 28, 255, 1);
  --md-link-hover: rgba(33, 18, 184, 1);
  --md-inline-code: rgba(74, 74, 74, 1);

  --md-syntax-keyword: rgba(166, 38, 164, 1);
  --md-syntax-string: rgba(47, 107, 46, 1);
  --md-syntax-number: rgba(138, 90, 0, 1);
  --md-syntax-title: rgba(31, 95, 191, 1);
  --md-syntax-builtin: rgba(122, 92, 30, 1);
  --md-syntax-comment: rgba(125, 125, 125, 1);
  --md-syntax-deletion: rgba(200, 52, 43, 1);
}

* {
  margin: 0 !important;
  padding: 0 !important;
  color: var(--primary-text-color) !important;
  border: none;
  outline: none !important;
  font-size: 1rem;
  -webkit-appearance: none;
    -moz-appearance: none;
      appearance: none;
  list-style: none;
  font-style: normal;
  transition: .1s all;
  box-sizing: border-box;
  font-family: "Geologica", sans-serif;
  letter-spacing: .5px;
  text-decoration: none !important;
  /* firefox: закруглённого скроллбара нет, но делаем его тонким и в цвет палитры */
  scrollbar-width: thin;
  scrollbar-color: var(--section-background-color__hover) transparent;
}

/*
  переключение темы. виновник «поэлементной» смены — глобальный "transition: .1s all":
  каждый элемент тянет свой переход сам, за 100 мс браузер не успевает перекрасить дерево,
  и тема расползается волной. поэтому на время смены общий переход подменяем, а не оставляем:

  theme-switching — переходы выключены совсем; так работает путь с view transitions,
                    где плавность даёт один кроссфейд снимка всей страницы;
  theme-fading    — запасной путь для браузеров без view transitions: один и тот же
                    переход только по цветам и на всех элементах разом.

  длительность .35s продублирована в stores/ui.js (THEME_FADE_MS) — менять надо обе
*/
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: none !important;
}

:root.theme-fading *,
:root.theme-fading *::before,
:root.theme-fading *::after {
  transition: background-color .35s ease, color .35s ease, border-color .35s ease, fill .35s ease !important;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .35s;
  animation-timing-function: ease;
}

/* выделение текста — из палитры, а не константой: пара «кнопка» описана в обеих темах
   и всегда даёт контрастную подложку под текст выделения */
*::selection {
  color: var(--button-text-color);
  background-color: var(--button-background-color);
}

/* закругляем углы у всех скроллбаров, включая общий (chrome, safari, opera) */
  *::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }

  *::-webkit-scrollbar-track {
    background-color: transparent;
  }

  *::-webkit-scrollbar-thumb {
    background-color: var(--section-background-color__hover);
    border-radius: 8px;
  }
/* закругляем углы у всех скроллбаров */

/* в светлой теме цвет наведения совпадает с фоном страницы, и ползунок на нём растворялся —
   берём тон обводки: он виден и на фоне, и на белой карточке */
:root[data-theme="light"] * {
  scrollbar-color: var(--border-color) transparent;
}

:root[data-theme="light"] *::-webkit-scrollbar-thumb {
  background-color: var(--border-color);
}

body {
  background-color: var(--primary-background-color) !important;
}

body > .wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

p, ul {
  margin: 0;
  padding: 0;
}

/* поля ввода не растягиваются: высоту задаёт вёрстка (rows), а ручка ресайза
   ломала раскладку форм и модалок. !important обязателен — bootstrap подключается
   после global.css, и его reboot (textarea { resize: vertical }) перебивал правило */
textarea {
  resize: none !important;
}

/* заголовки — моноширинный акцент капсом; общий для карточек, постов и markdown.
   .heading — для заголовков, которые не h1–h6 (шапка модалки, тост, блоки сайдбара),
   .forum-selector — табы. шрифт ставим и потомкам: сброс «* { font-family }» выше
   красит каждый элемент отдельно, и вложенный span иначе остался бы на Geologica */
h1, h2, h3, h4, h5, h6,
.heading,
.forum-selector {
  text-transform: uppercase;
}

/* вес 600 у всех заголовков; :root поднимает специфичность выше утилит bootstrap
   (.fw-bold, .fw-normal с !important), иначе они перебивали бы вес на отдельных заголовках */
:root :is(h1, h2, h3, h4, h5, h6, .heading, .forum-selector) {
  font-weight: 600 !important;
}

h1, h2, h3, h4, h5, h6,
.heading,
.forum-selector,
h1 *, h2 *, h3 *, h4 *, h5 *, h6 *,
.heading *,
.forum-selector * {
  font-family: "IBM Plex Mono", monospace;
}

.wrapper {
  max-width: 1280px;
  margin: 0 auto !important;
}

.separator {
  width: 100%;
  height: 2px;
  margin: 0;
  border: none;
  border-radius: 5px;
  background-color: var(--border-color);
}

.button {
  color: var(--button-text-color) !important;
  cursor: pointer;
  background-color: var(--button-background-color);
}

.button::selection {
  background-color: transparent !important;
}

.button:hover, .button:active, .button:focus {
  filter: invert(100%) saturate(0%) brightness(120%);
  box-shadow: 0px 0px 2px rgba(0, 0, 0, 1);
}

/*
  сброс выше красит каждый элемент отдельно и с !important, поэтому цвет кнопки не доходит
  до вложенных span и иконок — они берут обычный текстовый цвет. в тёмной теме это незаметно
  (кнопка светлее фона), в светлой кнопка тёмная и содержимое на ней пропадает. красим
  поддерево целиком: подписи и иконки в кнопках «Обо мне», навбаре и панелях
*/
:root[data-theme="light"] .button,
:root[data-theme="light"] .button * {
  color: var(--button-text-color) !important;
}

/* в светлой теме кнопка тёмная: полная инверсия сделала бы её белой и она пропала бы
   на белой карточке. поэтому на наведении не переворачиваем, а подсветляем на ступень —
   светлый текст и иконки внутри уходят в светло-серый вместе с фоном */
:root[data-theme="light"] .button:hover,
:root[data-theme="light"] .button:active,
:root[data-theme="light"] .button:focus {
  filter: invert(15%);
  box-shadow: none;
}

.hover-transparency:hover {
  opacity: .8;
}

/*
  оформление текста поста — ОДНО на читателя (MarkdownRenderer) и автора (RichTextEditor):
  автор должен видеть ровно то, что получится после публикации, поэтому правила лежат здесь,
  а не копиями в двух компонентах. margin/padding требуют !important — сброс выше обнуляет
  их у каждого элемента. шаг отступов — стандартный для сайта, 1rem (как p-3 и mb-3).
  акцентные цвета (--md-*) объявлены в :root
*/
.post-content {
  padding: 0 0.25rem !important;
  line-height: 1.6;
}

.post-content h1,
.post-content h2,
.post-content h3,
.post-content h4 {
  margin: 1.5rem 0 1rem !important;
  font-weight: 700;
  line-height: 1.35;
  text-transform: none;
}

/* первый блок не должен отталкиваться от верха лишним отступом */
.post-content :first-child {
  margin-top: 0 !important;
}

.post-content h2 {
  font-size: 1.2rem;
}

.post-content h3 {
  font-size: 1.05rem;
}

.post-content p {
  margin: 0 0 1rem !important;
}

/* сброс выше снимает подчёркивание, маркеры и курсив у каждого элемента — возвращаем */
.post-content a {
  color: var(--md-link) !important;
  text-decoration: underline !important;
}

.post-content a:hover {
  color: var(--md-link-hover) !important;
}

/* отступ слева — место под маркеры, чтобы список не сливался с абзацем; сами маркеры задаются
   пунктам: li не наследует их от списка */
.post-content ul,
.post-content ol {
  margin: 0 0 1rem 2rem !important;
}

.post-content ul > li {
  list-style: disc;
}

.post-content ul ul > li {
  list-style: circle;
}

.post-content ol > li {
  list-style: decimal;
}

.post-content li {
  margin-bottom: 0.5rem !important;
}

.post-content li p {
  margin-bottom: 0 !important;
}

.post-content em {
  font-style: italic;
}

.post-content del,
.post-content s {
  text-decoration: line-through !important;
}

.post-content u,
.post-content ins {
  text-decoration: underline !important;
}

.post-content blockquote {
  position: relative;
  margin: 0 0 1rem !important;
  padding: 1rem 1rem 1rem 2.1rem !important;
  border-left: 3px solid var(--border-color);
  border-radius: 8px;
  background-color: var(--container-background-color);
}

/* внутри примечания — только текст: его нижний отступ убираем, иначе к padding добавился бы
   ещё и margin абзаца, и снизу вышло бы заметно больше, чем сверху */
.post-content blockquote p:last-child {
  margin-bottom: 0 !important;
}

/* декоративная открывающая кавычка в углу примечания */
.post-content blockquote::before {
  content: "\201E";
  position: absolute;
  top: 0.1rem;
  left: 0.7rem;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
  color: var(--md-link);
  opacity: 0.6;
}

.post-content code {
  padding: 0.15rem 0.4rem !important;
  border-radius: 4px;
  font-size: 0.85rem;
  color: var(--md-inline-code) !important;
  background-color: var(--container-background-color);
}

/* блок кода: шапка (язык, копирование, сворачивание) и тело (номера строк + код) — единая
   скруглённая карточка, поэтому радиус и фон висят на обёртке */
.post-content .code-block {
  margin: 0 0 1rem !important;
  overflow: hidden;
  border-radius: 8px;
  background-color: var(--container-background-color);
}

.post-content .code-block__header {
  cursor: pointer;
  padding: 0.5rem 1rem !important;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  list-style: none;
  /* темнее тела блока и фона страницы — граница шапки читается без разделителя */
  background-color: var(--container-background-color__dark);
}

.post-content .code-block__header::-webkit-details-marker {
  display: none;
}

.post-content .code-block__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.post-content .code-block__chevron {
  font-size: 0.7rem;
  opacity: 0.55;
  transition: transform 0.15s ease;
}

.post-content .code-block:not([open]) .code-block__chevron {
  transform: rotate(-90deg);
}

.post-content .code-block__lang {
  font-size: 0.75rem;
  text-transform: uppercase;
  opacity: 0.6;
}

.post-content .code-block__copy {
  cursor: pointer;
  font-size: 0.9rem;
  line-height: 1;
  background-color: transparent;
}

.post-content .code-block__copy:hover {
  opacity: 0.7;
}

.post-content .code-block__body {
  display: flex;
}

/* сброс навязывает Geologica каждому элементу — коду и номерам строк возвращаем моноширинный */
.post-content code,
.post-content .code-block__gutter {
  font-family: Consolas, "Cascadia Mono", "Courier New", monospace;
}

/* колонка номеров строк: тот же line-height и font-size, что у кода, — строки совпадают по высоте
   (длинные строки не переносятся, а уходят вбок); отступы равные и совпадают с шапкой (1rem) */
.post-content .code-block__gutter {
  flex-shrink: 0;
  padding: 1rem !important;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 0.85rem;
  line-height: 1.5;
  user-select: none;
  background-color: var(--container-background-color__dark);
}

.post-content .code-block__gutter span {
  display: block;
  opacity: 0.4;
}

.post-content .code-block__body pre {
  flex: 1;
  min-width: 0;
}

.post-content pre {
  padding: 1rem !important;
  overflow-x: auto;
  line-height: 1.5;
}

.post-content pre code {
  padding: 0 !important;
  color: var(--primary-text-color__active) !important;
  background-color: transparent;
}

/* подсветка синтаксиса (классы highlight.js): свой набор цветов вместо готовой темы —
   готовые темы перебивались бы сбросом цвета выше */
.post-content .hljs-comment,
.post-content .hljs-quote {
  color: var(--md-syntax-comment) !important;
  font-style: italic;
}

.post-content .hljs-keyword,
.post-content .hljs-selector-tag,
.post-content .hljs-subst {
  color: var(--md-syntax-keyword) !important;
}

.post-content .hljs-string,
.post-content .hljs-regexp,
.post-content .hljs-addition,
.post-content .hljs-doctag {
  color: var(--md-syntax-string) !important;
}

.post-content .hljs-number,
.post-content .hljs-literal,
.post-content .hljs-variable,
.post-content .hljs-template-variable,
.post-content .hljs-attr,
.post-content .hljs-attribute {
  color: var(--md-syntax-number) !important;
}

.post-content .hljs-title,
.post-content .hljs-section,
.post-content .hljs-selector-id,
.post-content .hljs-selector-class {
  color: var(--md-syntax-title) !important;
  font-weight: 600;
}

.post-content .hljs-built_in,
.post-content .hljs-builtin-name,
.post-content .hljs-type,
.post-content .hljs-tag,
.post-content .hljs-name {
  color: var(--md-syntax-builtin) !important;
}

.post-content .hljs-deletion {
  color: var(--md-syntax-deletion) !important;
}

.post-content .hljs-emphasis {
  font-style: italic;
}

.post-content .hljs-strong {
  font-weight: 700;
}

/* картинки — на всю ширину колонки, вровень с постером и разделителями: боковой отступ
   текста (0.25rem) они перекрывают; высота по пропорции */
.post-content img {
  display: block;
  width: calc(100% + 0.5rem);
  max-width: none;
  height: auto;
  margin: 0 -0.25rem 1rem !important;
  border-radius: 8px;
}

/* видео в тексте: плеер youtube/vimeo держит пропорцию 16:9, файл видео занимает ширину текста */
.post-content .video-embed {
  position: relative;
  width: 100%;
  margin: 0 0 1rem !important;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  background-color: var(--container-background-color);
}

.post-content .video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.post-content .video-file {
  display: block;
  width: 100%;
  max-width: 100%;
  margin: 0 0 1rem !important;
  border-radius: 8px;
}

.post-content table {
  margin-bottom: 1rem !important;
  border-collapse: collapse;
}

.post-content th,
.post-content td {
  padding: 0.5rem 1rem !important;
  border: 1px solid var(--border-color);
}

/* ряд с горизонтальной прокруткой без полосы: вкладки, чипы тегов */
.scroll-row {
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.scroll-row::-webkit-scrollbar {
  display: none;
}

/* телефон: внешние панели уже, иначе отступы страницы и вложенных панелей съедают ширину */
@media (max-width: 575.98px) {
  #app.p-3,
  nav.p-3,
  article.p-3,
  aside.p-3,
  footer.p-3 {
    padding: 0.5rem !important;
  }
}

/* сенсорные экраны: любое поле (BaseInput, BaseTextarea, кнопка BaseSelect) не ниже 44px */
@media (pointer: coarse) {
  .field {
    min-height: 44px;
  }
}