/* ============================================================
   Knowledge base — three skins × two themes, tokens only.
   Skin:  <html data-skin="paper" | "quiet" | "dense">
   Theme: светлая всегда; тёмная — только явным <html data-theme="dark">
   No JS, no external resources. Icons: emoji / inline data-URI SVG.

   Layer order:
     1. primitives (spacing, motion, focus)
     2. palettes  (--l-* light, --d-* dark; per skin overrides)
     3. theme mapping (semantic tokens -> palette)
     4. skin metrics (type scale, density, geometry)
     5. components (read tokens only)
     6. skin layout deltas (minimal)
     7. responsive (<=860px drawer)

   Drawer (no JS available here): the sidebar is off-canvas below 860px
   and slides in for any of
     .app.is-drawer-open | .app[data-drawer="open"] | .sidebar:focus-within
   ============================================================ */

/* ---------- 1. primitives ------------------------------------ */

:root {
  --u: 4px;
  --sp-1: var(--u);
  --sp-2: calc(var(--u) * 2);
  --sp-3: calc(var(--u) * 3);
  --sp-4: calc(var(--u) * 4);
  --sp-5: calc(var(--u) * 5);
  --sp-6: calc(var(--u) * 6);
  --sp-8: calc(var(--u) * 8);
  --sp-10: calc(var(--u) * 10);
  --sp-12: calc(var(--u) * 12);

  --font-ui: "Golos Text", "Golos fallback", system-ui, -apple-system, sans-serif;
  --font-read: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Consolas, monospace;

  --dur: 120ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);

  --focus-width: 2px;
  --focus-offset: 2px;

  /* Светлая — и полосы прокрутки, и поля ввода, которые рисует сам браузер.
     `light dark` здесь означало бы «решай сам», а решать за него не надо. */
  color-scheme: light;
}

@media (prefers-reduced-motion: reduce) {
  :root { --dur: 1ms; }
}

/* ---------- 2. palettes -------------------------------------- */
/* Values live here once. Themes only re-point the semantic tokens. */

:root {
  /* light */
  --l-canvas: #f3f1ec;
  --l-surface: #fbfaf8;
  --l-surface-2: #f0ede6;
  --l-surface-3: #e7e3da;
  --l-line: #ddd8ce;
  --l-line-strong: #c8c1b4;
  --l-text: #1c1b18;          /* 14.8:1 on surface */
  --l-text-2: #46423b;        /* 8.9:1  */
  --l-text-3: #635e55;        /* 5.6:1  — smallest allowed for body-size text */
  --l-accent: #8a5a25;        /* 5.3:1 on surface */
  --l-accent-quiet: #f4ead9;
  --l-accent-line: #e3d2b4;
  --l-accent-contrast: #ffffff;
  --l-ok: #2f6a4a;
  --l-ok-quiet: #e4efe7;
  --l-bad: #a03028;
  --l-bad-quiet: #f7e6e3;
  --l-warn: #8a5a25;
  --l-warn-quiet: #f6ecdb;
        --l-mark: #f6e2b8;
  --l-shadow: 0 18px 40px -22px rgba(28, 27, 24, 0.35);
  --l-shadow-pop: 0 22px 48px -18px rgba(28, 27, 24, 0.42);

  /* dark */
  --d-canvas: #0f0f0e;
  --d-surface: #161615;
  --d-surface-2: #1d1d1b;
  --d-surface-3: #262521;
  --d-line: #2c2b27;
  --d-line-strong: #454239;
  --d-text: #f2efe8;          /* 14.1:1 on surface */
  --d-text-2: #cec8bd;        /* 9.4:1  */
  --d-text-3: #a29c91;        /* 5.4:1  */
  --d-accent: #dca871;        /* 8.3:1 on surface */
  --d-accent-quiet: #241d14;
  --d-accent-line: #3d3122;
  --d-accent-contrast: #17140f;
  --d-ok: #86bd9c;
  --d-ok-quiet: #16211c;
  --d-bad: #e59a91;
  --d-bad-quiet: #251a18;
  --d-warn: #dca871;
  --d-warn-quiet: #241d14;
  --d-info: #8fbcdf;
  --d-info-quiet: #14202a;
  --d-info-line: #24384a;
  --d-mark: #4a3a22;
  --d-shadow: 0 20px 44px -24px rgba(0, 0, 0, 0.8);
  --d-shadow-pop: 0 30px 64px -22px rgba(0, 0, 0, 0.88);
}

/*
 * paper — деловой вики-документ.
 *
 * Отличий от quiet в цвете немного, и все они об одном: лист бумаги лежит на
 * столе. Обвязка (шапка, боковая панель, правая колонка) на полтона темнее
 * самого листа, поэтому лист видно как лист, а не как продолжение окна. В
 * quiet и dense обе поверхности одного цвета — там лист и есть окно.
 */
:root[data-skin="paper"] {
  /*
   * ДЕЙСТВИЕ И ПРЕДУПРЕЖДЕНИЕ РАЗВЕДЕНЫ, и это главная правка в языке цвета.
   *
   * До сих пор --accent и --warn были одним и тем же #8a5a25. Следствие: любая
   * ссылка выглядела тревожной, а предупреждение ничем не отличалось от
   * действия. Человек не мог по цвету понять, зовут его нажать или просят
   * остановиться.
   *
   * --info УБРАН СОВСЕМ: справочное берёт цвет действия. Пять сигнальных
   * цветов на деловой странице — на один больше, чем глаз различает при
   * быстром просмотре. Осталось четыре: действие/справка, внимание, готово,
   * сломано.
   */
  --l-accent:       #2d4a63;   /* чернильно-синий: действие, ссылка, справка */
  --l-accent-quiet: #eef3f7;
  --l-accent-line:  #ccd7e0;
  --l-accent-contrast: #ffffff;
  --l-warn:         #a8722c;   /* охра: внимание, «в работе» */
  --l-warn-quiet:   #fdf7ec;
  --l-warn-line:    #e6d9bf;
  --l-ok:           #3d8a5f;
  --l-ok-quiet:     #eff6f1;
  --l-ok-line:      #cfe0d4;
  --l-bad:          #a03028;
  --l-bad-quiet:    #f7e6e3;
  --l-bad-line:     #e4bdb7;
  --l-mark:         #f6e2b8;

  /* поверхности */
  --l-canvas: #f2efe9;         /* обвязка: шапка, панели, шапка таблицы */
  --l-surface: #fbfaf8;        /* сам лист */
  --l-surface-2: #f0ede6;      /* углубление: код, поле, наведение */
  --l-surface-3: #e7e3da;      /* нажатое, аватары */
  --l-surface-sel: #e6e1d6;    /* подложка активного документа в дереве */

  /*
   * ЛЕСТНИЦА ЛИНИЙ: внешняя рамка темнее внутренних, внутренние вертикальные
   * темнее горизонтальных. Решётка таблицы перестаёт спорить с текстом —
   * читают строки, а не сетку.
   */
  --l-line: #ddd8ce;           /* внешняя рамка блока */
  --l-line-soft: #e4e0d7;      /* вертикальные разделители таблицы */
  --l-line-hair: #efece5;      /* горизонтальные линии строк */
  --l-line-strong: #c2bcaf;    /* точки перечней */

  /*
   * Четвёртая ступень серого — для счётчиков, номеров и подписей.
   *
   * 2.85:1 на листе: это НИЖЕ порога для текста, и потому здесь можно набирать
   * только то, что дублируется рядом. Номер строки читается вместе со строкой,
   * счётчик — вместе с названием раздела. Ничего самостоятельного этим цветом
   * набирать нельзя.
   */
  --l-text: #1c1b18;
  --l-text-2: #46423b;
  --l-text-4: #9c9587;

  /*
   * ТРЕТЬЯ СТУПЕНЬ: 3.81:1 на листе. Это НИЖЕ порога 4.5, и решение принято
   * с открытыми глазами.
   *
   * Раньше здесь стоял #635e55 (6.17:1), и я оставлял его именно из-за замера.
   * Задание вернуло #857f74 вместе с доводом: появилась четвёртая ступень, и
   * служебное ушло в неё — значит третьей больше не нужно тянуть две роли
   * сразу, и она может стать тише.
   *
   * Что это стоит, чтобы знать наверняка: строка автора, надписи правой
   * колонки и подписи под картинками набраны 11–13 и этим цветом. Часть людей
   * при слабом экране или ярком свете прочтёт их с трудом. Обратный ход —
   * #6f6a5f (около 5:1) или возврат к #635e55.
   */
  --l-text-3: #857f74;

  /*
   * Тёмная тема эталоном не описана, но обязана существовать: тема следует
   * настройке системы, и человек с тёмной системой не должен получать белую
   * вспышку. Та же лестница, перевёрнутая, — обвязка темнее листа.
   */
  --d-canvas: #141412;
  --d-surface: #1a1917;
  --d-surface-2: #232220;
  --d-surface-3: #2b2926;
  --d-line: #33312c;
  --d-line-strong: #4d4a43;
  --d-line-soft: #2b2925;
  --d-line-hair: #232220;
  --d-text-4: #8a8478;
}

/* skin-specific hues: quiet = sand, dense = sage */
:root[data-skin="dense"] {
  --l-accent: #2c6549;
  --l-accent-quiet: #e3efe8;
  --l-accent-line: #c3dbcd;
  --l-accent-contrast: #ffffff;
  --l-mark: #cfe6d8;
  --d-accent: #8fc4a6;
  --d-accent-quiet: #16211c;
  --d-accent-line: #274236;
  --d-accent-contrast: #0d1912;
  --d-mark: #23372c;
}

/* ---------- 3. theme mapping --------------------------------- */

:root,
:root[data-theme="light"] {
  --canvas: var(--l-canvas);
  --surface: var(--l-surface);
  --surface-2: var(--l-surface-2);
  --surface-3: var(--l-surface-3);
  /* Подложка выбранного в списках. Отдельная от --surface-2: наведение и
     выбор — разные состояния, и одним цветом их не различить. */
  --surface-sel: var(--l-surface-sel, var(--l-surface-2));
  --line: var(--l-line);
  --line-strong: var(--l-line-strong);
  --line-soft: var(--l-line-soft, var(--l-line));
  --line-hair: var(--l-line-hair, var(--l-line));
  --text: var(--l-text);
  --text-2: var(--l-text-2);
  --text-3: var(--l-text-3);
  --text-4: var(--l-text-4, var(--l-text-3));
  --accent: var(--l-accent);
  --accent-quiet: var(--l-accent-quiet);
  --accent-line: var(--l-accent-line);
  --accent-contrast: var(--l-accent-contrast);
  --ok: var(--l-ok);
  --ok-quiet: var(--l-ok-quiet);
  --bad: var(--l-bad);
  --bad-quiet: var(--l-bad-quiet);
  --warn: var(--l-warn);
  --warn-quiet: var(--l-warn-quiet);
  --info: var(--l-accent);
  --info-quiet: var(--l-accent-quiet);
  --info-line: var(--l-accent-line);
  --mark: var(--l-mark);
  --shadow: var(--l-shadow);
  --shadow-pop: var(--l-shadow-pop);
  --scrim-bg: rgba(28, 27, 24, 0.42);
  color-scheme: light;
}

/* ТЕМА НЕ СЛЕДИТ ЗА СИСТЕМОЙ.

   Здесь был @media (prefers-color-scheme: dark), и он делал вид страницы
   свойством чужой настройки: человек, у которого в системе включена тёмная
   тема, получал тёмную базу знаний, ничего о ней не решая. Для рабочего
   инструмента, куда приходят по ссылке из переписки, это означает, что двое
   смотрят на разное и описывают друг другу разное.

   Светлая тема — по умолчанию и всегда. Тёмная остаётся и включается ЯВНО,
   атрибутом data-theme="dark" на теге html. */

:root[data-theme="dark"] {
  --canvas: var(--d-canvas);
  --surface: var(--d-surface);
  --surface-2: var(--d-surface-2);
  --surface-3: var(--d-surface-3);
  --surface-sel: var(--d-surface-sel, var(--d-surface-2));
  --line: var(--d-line);
  --line-strong: var(--d-line-strong);
  --line-soft: var(--d-line-soft, var(--d-line));
  --line-hair: var(--d-line-hair, var(--d-line));
  --text: var(--d-text);
  --text-2: var(--d-text-2);
  --text-3: var(--d-text-3);
  --text-4: var(--d-text-4, var(--d-text-3));
  --accent: var(--d-accent);
  --accent-quiet: var(--d-accent-quiet);
  --accent-line: var(--d-accent-line);
  --accent-contrast: var(--d-accent-contrast);
  --ok: var(--d-ok);
  --ok-quiet: var(--d-ok-quiet);
  --bad: var(--d-bad);
  --bad-quiet: var(--d-bad-quiet);
  --warn: var(--d-warn);
  --warn-quiet: var(--d-warn-quiet);
  --info: var(--d-accent);
  --info-quiet: var(--d-accent-quiet);
  --info-line: var(--d-accent-line);
  --mark: var(--d-mark);
  --shadow: var(--d-shadow);
  --shadow-pop: var(--d-shadow-pop);
  --scrim-bg: rgba(0, 0, 0, 0.62);
  color-scheme: dark;
}

/* ---------- 4. skin metrics ---------------------------------- */

:root,
:root[data-skin="quiet"] {
  --sidebar-w: 264px;
  --sidebar-pad: var(--sp-4);
  --rail-only: 0;

  --measure: 708px;
  --content-pad-x: var(--sp-12);
  --content-pad-y: var(--sp-10);
  --content-gap: var(--sp-5);

  --topbar-h: 56px;
  --toolbar-h: 48px;
  --toolbar-vis: 0.55;         /* chrome pulled back until hover/focus */

  --row-h: 32px;
  --row-gap: 2px;
  --row-pad-x: var(--sp-2);

  --radius-s: 6px;
  --radius: 10px;
  --radius-l: 14px;

  --font-body: var(--font-read);
  --fs-body: 18px;
  --lh-body: 1.7;
  --fs-ui: 14px;
  --fs-small: 12.5px;
  --fs-title: 44px;
  --fs-h1: 32px;
  --fs-h2: 25px;
  --fs-h3: 20px;
  --fs-h4: 17px;
  --heading-weight: 600;
  --block-gap: var(--sp-5);
  --tracking-title: -0.015em;
}

:root[data-skin="dense"] {
  --sidebar-w: 58px;           /* narrow rail */
  --sidebar-pad: var(--sp-2);
  --rail-only: 1;

  --measure: 668px;
  --content-pad-x: var(--sp-8);
  --content-pad-y: var(--sp-6);
  --content-gap: var(--sp-4);

  --topbar-h: 44px;
  --toolbar-h: 36px;
  --toolbar-vis: 1;

  --row-h: 26px;
  --row-gap: 1px;
  --row-pad-x: var(--sp-1);

  --radius-s: 5px;
  --radius: 8px;
  --radius-l: 11px;

  --font-body: var(--font-ui);
  --fs-body: 15px;
  --lh-body: 1.6;
  --fs-ui: 13px;
  --fs-small: 11.5px;
  --fs-title: 30px;
  --fs-h1: 24px;
  --fs-h2: 20px;
  --fs-h3: 17px;
  --fs-h4: 15px;
  --heading-weight: 600;
  --block-gap: var(--sp-3);
  --tracking-title: -0.02em;
}

/*
 * paper: шкала и ритм делового вики-документа.
 *
 * Главное отличие от quiet — СПЛОШНОЙ СИСТЕМНЫЙ SANS вместо серифа. Сериф
 * читается как книга, а это не книга: это рабочая страница, где рядом с
 * абзацем живут таблица, чеклист и статусы, и они все должны быть одного
 * рода.
 *
 * Колонка шире (800 вместо 708), текст мельче (16 вместо 18) и плотнее по
 * начертанию — на строку помещается примерно столько же, но страница
 * перестаёт выглядеть эссе.
 */
:root[data-skin="paper"] {
  --sidebar-w: 264px;
  --sidebar-pad: var(--sp-3);
  --rail-only: 0;

  /*
   * Мера и поля из доработки: колонка чуть уже, поля шире. Заголовок вырос с
   * 29 до 38 — теперь он читается как заголовок статьи, а не как крупный
   * абзац, и раздел при нём отбивается сильнее.
   */
  --measure: 792px;
  --content-pad-x: 56px;
  --content-pad-y: 44px;
  --content-gap: var(--sp-4);

  --topbar-h: 52px;
  --toolbar-h: 44px;
  --toolbar-vis: 1;                /* панель видна сразу: это рабочий стол */

  --row-h: 30px;
  --row-gap: 2px;
  --row-pad-x: var(--sp-2);

  /*
   * Три радиуса и не больше: 6 у того, что нажимают, 7 у блоков, круг у
   * аватаров. Крупнее уводит в маркетинг, разнобой — в неряшливость.
   */
  --radius-s: 6px;             /* кнопки, поля, метки */
  --radius: 7px;               /* блоки: таблица, код, выноска */
  --radius-l: 7px;

  /*
   * ТЕНЬ РОВНО ОДНА на весь продукт, и та еле видна. Тень говорит «этот
   * элемент над остальными»; если так говорят три элемента сразу, не верят
   * ни одному.
   */
  --shadow: 0 1px 2px rgba(28, 27, 24, 0.05);

  /*
   * ЛЕСТНИЦА КЕГЛЕЙ. Своих чисел мимо неё в продукте быть не должно: кегль,
   * вписанный числом, читается как случайный — потому что он случайный.
   */
  --font-body: var(--font-ui);
  --fs-title: 38px;                /* заголовок статьи, 1.1 */
  --fs-h1: 38px;
  --fs-h2: 23px;                   /* раздел, 1.25 */
  --fs-h3: 17px;                   /* подраздел, 1.3 */
  --fs-lede: 19px;                 /* лид под заголовком, 1.6 */
  --fs-body: 16px;                 /* основной текст */
  --lh-body: 1.714;
  --fs-h4: 16px;
  --fs-ui: 13px;                   /* мета, панель, оглавление */
  --fs-small: 11px;                /* шапка колонки, заголовок выноски */
  --heading-weight: 600;
  --block-gap: var(--sp-4);

  /*
   * Один раз, и не выше по файлу.
   *
   * Объявлений было ДВА: -0.022em здесь и -0.01em девятью строками ниже. Побеждал
   * второй, и заголовок всё это время набирался трекингом, которого никто не
   * заказывал, — при 38 кеглях разница в полточки на знак, то есть больше знака
   * на строку. Ни в одном замере это не всплывало: оба значения выглядят
   * осмысленно.
   */
  --tracking-title: -0.022em;
}

/* ---------- 5. components ------------------------------------ */

*,
*::before,
*::after { box-sizing: border-box; }

html,
body {
  margin: 0;
  min-height: 100%;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  -webkit-text-size-adjust: 100%;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }

:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--focus-width) solid var(--accent);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-s);
}
:where(button, input, select, textarea):disabled,
[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* --- shell --- */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}

.sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  min-width: 0;
  padding: var(--sidebar-pad);
  background: color-mix(in srgb, var(--surface) 55%, var(--canvas));
  border-right: 1px solid var(--line);
}

.sidebar-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-1) var(--sp-2);
}

.sidebar-project {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  font-size: var(--fs-ui);
  font-weight: 600;
  color: var(--text);
}
.sidebar-project .muted { font-weight: 400; }

.sidebar-tree {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.sidebar-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  color: var(--text-3);
}

.workspace {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--canvas);
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--topbar-h);
  padding: 0 var(--sp-5);
  background: var(--canvas);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

.content {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--content-gap);
  width: 100%;
  max-width: calc(var(--measure) + var(--content-pad-x) * 2);
  min-width: 0;
  margin: 0 auto;
  padding: var(--content-pad-y) var(--content-pad-x) var(--sp-12);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-2);
  text-wrap: pretty;
}
.content.is-wide { max-width: 100%; }
.content > * { margin: 0; }
.content > * + * { margin-top: var(--block-gap); }

.content h1, .content h2, .content h3, .content h4 {
  font-family: var(--font-body);
  font-weight: var(--heading-weight);
  color: var(--text);
  line-height: 1.2;
  letter-spacing: var(--tracking-title);
}
.content h1 { font-size: var(--fs-h1); }
.content h2 { font-size: var(--fs-h2); }
.content h3 { font-size: var(--fs-h3); }
.content h4 { font-size: var(--fs-h4); }
/* Один кегль на оба состояния: см. `.cm-inline-code` ниже. */
.content code,
.cm-inline-code { font-family: var(--font-mono); font-size: 0.9em; }
/* Подсветка объявляется на оба состояния сразу: своя строка у каждого —
   это два числа для одной вещи, и расходятся они молча. */
.content mark,
.cm-highlight { background: var(--mark); color: var(--text); border-radius: 3px; padding: 0 2px; }

.scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: var(--scrim-bg);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.scrim[hidden] { display: none; }

/* --- tree --- */

.tree {
  display: flex;
  flex-direction: column;
  gap: var(--row-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tree-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--row-h);
  padding: 0 var(--sp-2) 0 calc(var(--sp-2) + var(--row-pad-x));
  border-radius: var(--radius-s);
  color: var(--text-2);
  font-size: var(--fs-ui);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.tree-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.tree-item:active { background: var(--surface-3); }
.tree-item:focus-visible {
  outline: var(--focus-width) solid var(--accent);
  outline-offset: -1px;
  background: var(--surface-2);
}
.tree-item.is-active {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  font-weight: 600;
}
.tree-item[aria-disabled="true"] { color: var(--text-3); }

.tree-title {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.dot {
  flex: none;
  width: 6px;
  height: 6px;
  margin-left: auto;
  border-radius: 50%;
  background: var(--accent);
}

/* --- breadcrumbs --- */

.crumbs {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  font-size: var(--fs-ui);
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
}
.crumbs a { color: var(--text-3); }
.crumbs a:hover { color: var(--text); }
.crumbs .sep { color: var(--line-strong); }
.crumbs .current {
  color: var(--text);
  font-weight: 500;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- editor --- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--toolbar-h);
  padding: var(--sp-1) var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  opacity: var(--toolbar-vis);
  transition: opacity var(--dur) var(--ease);
}
.toolbar:hover,
.toolbar:focus-within { opacity: 1; }

.tool-group {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding-right: var(--sp-2);
  border-right: 1px solid var(--line);
}
.tool-group:last-child { border-right: 0; padding-right: 0; }
.tool-group > * {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 0 var(--sp-2);
  border: 0;
  border-radius: var(--radius-s);
  background: transparent;
  color: var(--text-2);
  font: inherit;
  font-size: var(--fs-ui);
  cursor: pointer;
}
.tool-group > *:hover { background: var(--surface-2); color: var(--text); }
.tool-group > *:active { background: var(--surface-3); }
.tool-group > *[aria-pressed="true"] { background: var(--accent-quiet); color: var(--accent); }

.editor {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
}

.editor-host {
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.editor-host:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 var(--focus-width) var(--accent-quiet);
}

.preview {
  min-width: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-2);
}
.preview > * + * { margin-top: var(--block-gap); }

.editor-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-1);
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-3);
}

.save-state {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  color: var(--text-3);
}
.save-state::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.save-state.is-ok { color: var(--ok); }
.save-state.is-bad { color: var(--bad); }

.title-input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-title);
  font-weight: var(--heading-weight);
  line-height: 1.12;
  letter-spacing: var(--tracking-title);
}
.title-input::placeholder { color: var(--text-3); }
.title-input:hover { border-bottom-color: var(--line); }
.title-input:focus { outline: 0; border-bottom-color: var(--accent); }
.title-input:focus-visible { outline: var(--focus-width) solid var(--accent); outline-offset: 4px; }
.title-input:disabled { color: var(--text-3); border-bottom-color: transparent; }

/* --- popovers --- */

.popover {
  min-width: 260px;
  max-width: min(92vw, 380px);
  padding: var(--sp-1);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-pop);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  z-index: 60;
}

.popover-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--row-h);
  padding: var(--sp-2);
  border-radius: var(--radius-s);
  color: var(--text-2);
  text-decoration: none;
  cursor: pointer;
}
.popover-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.popover-item:active { background: var(--surface-3); }
.popover-item:focus-visible { outline: var(--focus-width) solid var(--accent); outline-offset: -1px; }
.popover-item.is-active {
  background: var(--accent-quiet);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.popover-item[aria-disabled="true"] { color: var(--text-3); }

.popover-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-s);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 12px;
}
.popover-item.is-active .popover-icon { background: var(--surface); color: var(--accent); }

.popover-hint {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--text-3);
}

.selection-bar {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  white-space: nowrap;
  z-index: 60;
}
.selection-bar > * {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 var(--sp-2);
  border: 0;
  border-radius: var(--radius-s);
  background: transparent;
  color: var(--text-2);
  font: inherit;
  font-size: var(--fs-ui);
  cursor: pointer;
}
.selection-bar > *:hover { background: var(--surface-2); color: var(--text); }
.selection-bar > *:active { background: var(--surface-3); }

/* --- callouts --- */

.callout {
  --callout-accent: var(--accent);
  --callout-bg: var(--accent-quiet);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sp-1) var(--sp-3);
  padding: var(--sp-4);
  background: var(--callout-bg);
  border-radius: var(--radius-s);
}
.callout-icon {
  grid-row: 1 / span 2;
  align-self: start;
  font-size: 15px;
  line-height: 1.4;
  color: var(--callout-accent);
}
.callout-title {
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--callout-accent);
}
.callout-body {
  grid-column: 2;
  font-size: calc(var(--fs-body) - 1px);
  line-height: 1.6;
  color: var(--text-2);
}
.callout-body > * + * { margin-top: var(--sp-2); }

.callout-note     { --callout-accent: var(--info); --callout-bg: var(--info-quiet); }
.callout-abstract { --callout-accent: var(--info); --callout-bg: var(--info-quiet); }
.callout-info     { --callout-accent: var(--info); --callout-bg: var(--info-quiet); }
.callout-todo     { --callout-accent: var(--info); --callout-bg: var(--info-quiet); }
.callout-tip      { --callout-accent: var(--ok);   --callout-bg: var(--ok-quiet); }
.callout-success  { --callout-accent: var(--ok);   --callout-bg: var(--ok-quiet); }
.callout-example  { --callout-accent: var(--accent); --callout-bg: var(--accent-quiet); }
.callout-important{ --callout-accent: var(--accent); --callout-bg: var(--accent-quiet); }
.callout-quote    { --callout-accent: var(--line-strong); --callout-bg: var(--surface-2); }
.callout-warning  { --callout-accent: var(--warn); --callout-bg: var(--warn-quiet); }
.callout-caution  { --callout-accent: var(--warn); --callout-bg: var(--warn-quiet); }
.callout-question { --callout-accent: var(--warn); --callout-bg: var(--warn-quiet); }
.callout-danger   { --callout-accent: var(--bad);  --callout-bg: var(--bad-quiet); }
.callout-failure  { --callout-accent: var(--bad);  --callout-bg: var(--bad-quiet); }
.callout-bug      { --callout-accent: var(--bad);  --callout-bg: var(--bad-quiet); }
.callout-quote .callout-title { color: var(--text-3); }

/* --- tables --- */

.table-scroll {
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* Углы рамки обрезают углы решётки: без этого линия ячейки вылезает за
     скругление и рамка выглядит надколотой. */
  overflow-y: hidden;
  scrollbar-width: thin;
}
/*
 * ТАБЛИЦА ПЕРЕНОСИТ СТРОКИ, А НЕ УЕЗЖАЕТ ВБОК.
 *
 * Было `min-width: max-content` — таблица занимала столько, сколько просило её
 * самое длинное предложение, и колонка с описанием задачи уводила её за край
 * страницы. Читать такую таблицу можно только возя её мышью, а сравнивать
 * строки — нельзя вовсе: край экрана режет их в разных местах.
 *
 * Теперь ширина ограничена колонкой текста, а длинные ячейки переносятся.
 * Горизонтальная прокрутка осталась запасным выходом для таблиц, которым не
 * хватает места даже с переносами, — с десятком колонок.
 */
.table-scroll table {
  width: 100%;
  min-width: 0;
  border-collapse: collapse;
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
}

.table-scroll th,
.table-scroll td {
  /*
   * `break-word`, а НЕ `anywhere`, и разница здесь решающая.
   *
   * Оба переносят слово, которому не хватило строки. Но `anywhere` вдобавок
   * участвует в расчёте минимальной ширины: браузер считает, что колонке
   * достаточно одного знака, — и сужает её до предела. Колонка «#» со
   * значением «01» превращалась в две строки, «0» и «1».
   *
   * `break-word` минимальную ширину не трогает: колонка получает столько,
   * сколько просит её самое длинное слово целиком, и рвёт его только тогда,
   * когда места нет даже так.
   */
  overflow-wrap: break-word;

  /*
   * НИЖЕ ТРЁХ ЗНАКОВ КОЛОНКА НЕ СУЖАЕТСЯ.
   *
   * Одного `break-word` не хватило: в редакторе ячейка наследует от CodeMirror
   * `white-space: break-spaces`, и в такой среде правило перестаёт защищать
   * короткое слово — колонке «#» доставалось 13 точек под текст при нужных 16,
   * и «01» разваливалось на «0» и «1».
   *
   * `ch` — ширина нуля в шрифте самой ячейки, поэтому предел держится и при
   * смене кегля, и при смене скина. Три знака: номер, короткий код, «да».
   */
  min-width: calc(3ch + 2 * var(--sp-3));
}
.table-scroll th,
.table-scroll td {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  color: var(--text-2);
}
.table-scroll th {
  position: sticky;
  top: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  /*
   * Заголовок колонки переносится наравне с ячейками.
   *
   * `nowrap` здесь означал: длинное название колонки задаёт ширину всей
   * таблице. Одно слово «Ответственный» — и таблица шире страницы.
   */
  white-space: normal;
}
.table-scroll tr:last-child td { border-bottom: 0; }
.table-scroll th:last-child,
.table-scroll td:last-child { border-right: 0; }

.wikilink {
  color: var(--accent);
  border-bottom: 1px solid var(--accent-line);
  text-decoration: none;
}
.wikilink:hover { background: var(--accent-quiet); border-bottom-color: var(--accent); text-decoration: none; }
.wikilink:focus-visible { outline: var(--focus-width) solid var(--accent); outline-offset: 2px; }
.wikilink[aria-disabled="true"],
.wikilink.is-missing { color: var(--text-3); border-bottom-style: dashed; }

/* --- misc blocks --- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--sp-4);
}
.cards > * {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  color: var(--text-2);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.cards > a:hover { border-color: var(--line-strong); text-decoration: none; }
.cards > a:active { transform: translateY(1px); }

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--warn-quiet);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  color: var(--text-2);
}

.conflict {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.conflict ins,
.conflict .is-added {
  background: var(--ok-quiet);
  color: var(--ok);
  text-decoration: none;
  border-radius: 4px;
  padding: 2px 5px;
}
.conflict del,
.conflict .is-removed {
  background: var(--bad-quiet);
  color: var(--bad);
  text-decoration: none;
  border-radius: 4px;
  padding: 2px 5px;
}

.history {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  color: var(--text-2);
}
.history > * {
  display: flex;
  gap: var(--sp-3);
  padding-left: var(--sp-4);
  border-left: 1px solid var(--line);
  position: relative;
}
.history > *::before {
  content: "";
  position: absolute;
  left: -3px;
  top: 7px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--line-strong);
}
.history > *:first-child::before { background: var(--accent); }

.muted { color: var(--text-3); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-2);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-s);
  background: var(--accent-quiet);
  color: var(--accent);
  font-family: var(--font-ui);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.login-card {
  width: min(100%, 384px);
  margin: var(--sp-12) auto;
  padding: var(--sp-8);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
}
.login-card input {
  width: 100%;
  min-height: 40px;
  padding: 0 var(--sp-3);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  color: var(--text);
  font: inherit;
}
.login-card input:hover { border-color: var(--line-strong); }
.login-card input:focus-visible { outline: var(--focus-width) solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.login-card button {
  min-height: 40px;
  border: 0;
  border-radius: var(--radius-s);
  background: var(--accent);
  color: var(--accent-contrast);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.login-card button:hover { background: color-mix(in srgb, var(--accent) 88%, var(--text)); }
.login-card button:active { background: color-mix(in srgb, var(--accent) 78%, var(--text)); }

/* --- CodeMirror (engine classes: styled, not renamed) --- */

.cm-editor {
  background: transparent;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: calc(var(--fs-body) - 3px);
  line-height: 1.6;
}
.cm-editor.cm-focused { outline: 0; }
.cm-content { padding: var(--sp-4) var(--sp-4) var(--sp-8); caret-color: var(--accent); }
.cm-line { padding: 0 var(--sp-1); }
.cm-line:hover { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }

/*
 * ПОДСВЕТКА ТЕКУЩЕЙ СТРОКИ УБРАНА У СКИНА paper.
 *
 * Серая полоса во всю ширину под заголовком — заметный элемент, которого в
 * эталоне нет вовсе. В чтении её тоже нет, и она была самым бросающимся в
 * глаза различием между правкой и чтением.
 *
 * Место курсора видно по самому курсору и по проступившей разметке — этого
 * достаточно, а полоса спорила с ритмом отбивок.
 */
[data-skin="paper"] .cm-activeLine { background: transparent; }
.cm-cursor { border-left: 2px solid var(--accent); }
.cm-selectionBackground,
.cm-editor .cm-selectionBackground,
.cm-editor.cm-focused .cm-selectionBackground { background: var(--mark); }

.cm-h1, .cm-h2, .cm-h3, .cm-h4 {
  font-family: var(--font-body);
  font-weight: var(--heading-weight);
  color: var(--text);
}
/*
 * ТРЕКИНГ У КАЖДОГО СВОЙ, как и в отрисованном документе.
 *
 * Здесь на все четыре стоял один --tracking-title, то есть трекинг заголовка
 * СТАТЬИ. Раздел в правке набирался -0.022em против -0.014em в чтении: на 23
 * кеглях это пятая часть точки на знак, глазом не видно, приёмкой видно сразу.
 * Первое, что она нашла.
 */
.cm-h1 { font-size: var(--fs-h1); letter-spacing: var(--tracking-title); }
.cm-h2 { font-size: var(--fs-h2); letter-spacing: -0.016em; }
.cm-h3 { font-size: var(--fs-h3); letter-spacing: -0.012em; }
.cm-h4 { font-size: var(--fs-h4); letter-spacing: 0; }
.cm-strong { font-weight: 700; color: var(--text); }
.cm-em { font-style: italic; }
.cm-strike { text-decoration: line-through; color: var(--text-3); }
.cm-inline-code {
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--text);
  font-family: var(--font-mono);
  /* Кегль объявлен вместе со статьёй выше: два числа для одной вещи
     расходятся молча, и приёмка ловила ровно это. */
}
.cm-link { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.cm-quote { color: var(--text-2); padding-left: 22px; }
/*
 * Блок кода в правке — тот же, что в чтении.
 *
 * Моноширинного шрифта здесь не было вовсе: строки внутри тройных
 * кавычек набирались основным шрифтом в 16 против 14 моноширинных в
 * чтении. Блок кода, набранный не моноширинным, перестаёт быть блоком
 * кода — в нём не сходятся столбцы, ради которых его и пишут.
 */
.cm-fenced {
  display: block;
  background: var(--surface-2);
  color: var(--text);
  border-radius: var(--radius-s);
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.65;
}
.cm-table { font-family: var(--font-mono); color: var(--text-2); }
.cm-bullet { color: var(--accent); }

/*
 * Строка списка в правке красится как абзац в чтении.
 *
 * Была темнее — цветом основного текста. Разницу между `--text` и
 * `--text-2` глазом почти не видно, а на экране это два разных списка в
 * двух состояниях одного документа.
 */
.cm-line:has(.cm-bullet) { color: var(--text-2); }

/* ---------- 6. skin layout deltas ---------------------------- */
/* Only what tokens cannot express. */

/*
 * quiet и dense: раздел отбивается чертой, ссылка подчёркнута всегда.
 *
 * Оба правила раньше стояли в base.css, то есть действовали на все скины
 * разом. Это не поведение, а решение о виде: в paper черты между разделами
 * нет вовсе, а ссылка подчёркивается только под указателем.
 */
[data-skin="quiet"] :is(.content, .preview) h2,
[data-skin="dense"] :is(.content, .preview) h2 {
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
[data-skin="quiet"] :is(.content, .preview) a:not(.wikilink),
[data-skin="dense"] :is(.content, .preview) a:not(.wikilink) {
  border-bottom: 1px solid var(--accent-line);
}

/* quiet: chrome recedes until you reach for it */
[data-skin="quiet"] .topbar { background: color-mix(in srgb, var(--canvas) 90%, var(--surface)); }
[data-skin="quiet"] .content { --block-gap: var(--sp-5); }
[data-skin="quiet"] .editor-host { border-color: transparent; background: transparent; }
[data-skin="quiet"] .editor-host:focus-within { border-color: var(--accent); background: var(--surface); }

/* dense: sidebar collapses to an icon rail; popovers carry the UI */
[data-skin="dense"] .sidebar { align-items: center; gap: var(--sp-2); }
[data-skin="dense"] .sidebar-head { justify-content: center; padding: var(--sp-1); }
[data-skin="dense"] .sidebar-project,
[data-skin="dense"] .sidebar-foot .muted,
[data-skin="dense"] .tree-title { display: none; }
[data-skin="dense"] .sidebar-tree { width: 100%; }
[data-skin="dense"] .tree-item { justify-content: center; padding: 0; }
[data-skin="dense"] .tree-item.is-active { box-shadow: inset 0 0 0 1px var(--accent-line); }
[data-skin="dense"] .dot { margin-left: 0; position: absolute; }
[data-skin="dense"] .sidebar-foot { justify-content: center; border-top: 0; }
[data-skin="dense"] .toolbar { border-radius: 0; border-left: 0; border-right: 0; }
[data-skin="dense"] .popover { min-width: 300px; border-color: var(--line-strong); }
[data-skin="dense"] .editor-foot { justify-content: flex-start; gap: var(--sp-4); }
[data-skin="dense"] .cards { gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }

/* --- paper --- */

/* Лист светлее обвязки. Рабочая область — сам документ; шапка и панели вокруг. */
[data-skin="paper"] .workspace { background: var(--surface); }
[data-skin="paper"] .topbar,
[data-skin="paper"] .sidebar { background: var(--canvas); }

/*
 * Колонка по ЛЕВОМУ краю, а не по центру.
 *
 * Документ читают сверху вниз, и левая граница текста при этом обязана стоять
 * на месте. У центрированной колонки она уезжает при каждом изменении ширины
 * окна, и глаз каждый раз ищет начало строки заново.
 */
[data-skin="paper"] .content { margin-left: 0; margin-right: auto; }

/*
 * Ритм заголовков: сверху 40, снизу 8.
 *
 * ЗАГОЛОВОК ПРИНАДЛЕЖИТ СЛЕДУЮЩЕМУ АБЗАЦУ, а не пустоте перед ним. При равных
 * отступах сверху и снизу он висит между разделами, и глаз каждый раз решает,
 * к чему он относится. Разделительных линий между разделами при этом нет:
 * отбивка уже сказала всё, что линия могла бы добавить.
 *
 * Порядок двух строк ниже существенный: вес у них одинаковый, и решает он.
 * Первая даёт заголовку большой отступ сверху, вторая прижимает к нему то,
 * что идёт следом, — и она же, стоя второй, побеждает для подзаголовка сразу
 * под заголовком: h3 под h2 принадлежит ему, а не отделяется от него.
 */
/*
 * РИТМ ДОКУМЕНТА. Порядок правил снизу вверх — от общего к частному, и он же
 * решает при равном весе: то, что прижимает контент к заголовку, стоит ниже
 * всех и потому побеждает.
 */
[data-skin="paper"] .content > * + * { margin-top: 12px; }
[data-skin="paper"] .content > :is(ul:not([class]), ol:not([class]), table, .table-scroll) { margin-top: 18px; }
[data-skin="paper"] .content > :is(.callout, figure) { margin-top: 28px; }
[data-skin="paper"] .content > :is(h1, h2, h3, h4) { margin-top: 40px; }
/* Раздел отбивается сильнее прочих заголовков: при h1 в 38 сорока мало. */
[data-skin="paper"] .content > h2 { margin-top: 52px; }
[data-skin="paper"] .content > :is(h1, h2, h3, h4) + * { margin-top: 8px; }
[data-skin="paper"] .doc-foot { margin-top: 56px; }

/* Ссылка подчёркивается только под указателем — как в эталоне. */
[data-skin="paper"] :is(.content, .preview) a:not(.wikilink) { border-bottom: 0; }

/*
 * Кегль ячейки. Вся остальная геометрия таблицы — поля, лестница линий, шапка,
 * неразрывные служебные колонки — собрана ОДНИМ местом в base.css.
 *
 * Отступление от задания («числа в base.css не появляются») сознательное.
 * Правила таблицы обязаны действовать и на редактор, где разметка своя
 * (`.cm-editor`), а skins.css заменяется целиком — при следующей замене
 * редактор остался бы со старой таблицей, и мы третий раз ловили бы
 * расхождение чтения с правкой. Числа при этом всё равно взяты отсюда:
 * base.css их не выдумывает, а применяет к двум поверхностям сразу.
 */
[data-skin="paper"] :is(.content, .preview, .cm-editor) .table-scroll :is(th, td) {
  font-size: 15px;
}

/* Текст выноски мельче основного — как в эталоне. */
[data-skin="paper"] .callout .callout-body { font-size: 15px; line-height: 1.6; }

/*
 * Точка списка серая и мельче.
 *
 * В quiet она акцентная: там документ — чтение, и маркер задаёт ритм. Здесь
 * рядом со списком живут таблицы и статусы, и цветная точка спорит с ними за
 * внимание, ничего при этом не сообщая.
 */
[data-skin="paper"] :is(.content, .preview) ul:not([class]) > li::before {
  width: 5px;
  height: 5px;
  left: -20px;
  top: 0.7em;
  background: var(--line-strong);
}

/* Чеклист эталона: квадрат поменьше, отбивка от подписи побольше. */
[data-skin="paper"] :is(.content, .preview) input[type="checkbox"] {
  width: 17px;
  height: 17px;
  margin-right: var(--sp-3);
  border-radius: 4px;
}

/*
 * ------- Числа ниже сняты с эталона поштучно -------
 *
 * Всё, что здесь стоит числом, а не токеном, взято из inline-стилей эталона.
 * Токенами это выразить нельзя: у эталона шкала не кратна четырём, и подгонять
 * под неё общую сетку значило бы менять два других скина ради одного.
 */

/* Заголовок статьи: 38/1.1. Было 29/1.14 — при выросшем кегле строки сходятся
   плотнее, иначе двухстрочное название разваливается на две отдельные. */
[data-skin="paper"] .content h1,
[data-skin="paper"] .title-input { line-height: 1.1; }

/* Строка автора и подвал документа. */
[data-skin="paper"] .doc-meta { gap: 10px; }
[data-skin="paper"] .doc-foot { gap: 14px; }

/* Правая колонка: между пунктами оглавления 10, между блоками 24. */
[data-skin="paper"] .rail-block { gap: 10px; }

/* Шапка: поля по 24. */
[data-skin="paper"] .topbar { padding: 0 24px; }

/* Плашка статуса в шапке — того же кегля, что метки в тексте. */
[data-skin="paper"] .badge {
  padding: 2px 7px;
  font-size: 11px;
}

/* Шапка таблицы ниже строк: в ней одна строка и та короткая. */
[data-skin="paper"] :is(.content, .preview, .cm-editor) th { padding: 8px 12px; }

/*
 * Список: точка 5 точек, до текста 12 — значит текст начинается на 17.
 * Между пунктами 6, а в списке задач 8: квадрат чекбокса выше точки, и при
 * равном отступе строки слипаются.
 */
[data-skin="paper"] :is(.content, .preview) ul:not([class]) { padding-left: 17px; }
[data-skin="paper"] :is(.content, .preview) ul:not([class]) > li::before { left: -17px; }
[data-skin="paper"] :is(.content, .preview) li + li { margin-top: 6px; }
[data-skin="paper"] :is(.content, .preview) li:has(input[type="checkbox"]) + li { margin-top: 8px; }

/*
 * Выноска эталона обведена рамкой целиком, а не полосой слева.
 *
 * Рамка светлее собственного цвета выноски: сплошная линия в полную силу
 * спорит с текстом внутри, ради которого плашка и нарисована. Цвет для каждого
 * семейства назван ГОТОВЫМ (`--frame-colour` в base.css), а осветление
 * оставлено запасным: подобрать долю нельзя в принципе — чтобы попасть в
 * #c3d5e2, по красному нужно 21%, по зелёному 18%, по синему 15%. Это не
 * осветление акцента, а свой цвет, выбранный глазами.
 *
 * Сама рамка и её сборка из строк для редактора живут в base.css одним местом
 * на оба состояния. Скину остаются только числа — иначе правка в одном
 * состоянии снова разойдётся с другим.
 */
[data-skin="paper"] :is(.callout, .cm-callout) {
  --callout-pad-x: 16px;
  --callout-pad-y: 14px;
}

[data-skin="paper"] .callout { gap: 4px 12px; }

/*
 * Отбивка сверху у тяжёлых блоков больше обычной: 20 у иллюстрации, 24 у
 * выноски. Так в эталоне. Вес селекторов подобран так, чтобы правило «после
 * заголовка 8» по-прежнему побеждало: заголовок и то, что под ним, — одно
 * целое, и картинка сразу под заголовком не должна от него отрываться.
 */
/* Тяжёлые блоки отбиваются сильнее текста: 28 у выноски и у иллюстрации. Вес
   селекторов подобран так, чтобы «после заголовка 8» по-прежнему побеждало —
   заголовок и то, что под ним, одно целое. */
[data-skin="paper"] .content > :is(figure, .callout) { margin-top: 28px; }

/*
 * ЦВЕТ ТЕКСТА: основной — тёмный, у абзацев — светлее.
 *
 * В эталоне колонка объявлена цветом #1c1b18, и светлее его только абзацы и
 * перечни «на будущее». Пункты чеклиста и ячейки таблицы остаются тёмными: это
 * то, ради чего страницу открывают, а абзац вокруг них — пояснение.
 *
 * У нас было наоборот — светлым был весь документ, — и разница читалась как
 * «текст блёклый».
 */
[data-skin="paper"] :is(.content, .preview) { color: var(--text); }
[data-skin="paper"] :is(.content, .preview) :is(p, ul:not([class]), ol:not([class])) { color: var(--text-2); }
[data-skin="paper"] :is(.content, .preview) li:has(input[type="checkbox"]) { color: var(--text); }

/*
 * Сделанная задача НЕ гаснет и не зачёркивается.
 *
 * В остальных скинах гаснет — список тогда читается по тому, что осталось. Но
 * в эталоне раздел «Что готово» состоит из одних сделанных, и зачёркнутым он
 * выглядит как список отменённого. Галочки достаточно.
 */
/*
 * СДЕЛАННОЕ НЕ ЗАЧЁРКИВАЕТСЯ — ни в отрисованном документе, ни в редакторе.
 *
 * В эталоне отметка «готово» стоит галочкой, а текст остаётся текстом: список
 * читают, чтобы увидеть, ЧТО сделано, а не чтобы перестать это видеть.
 *
 * `.cm-task-done` в этом перечне не был, и оттого правка выглядела иначе, чем
 * чтение: те же три строки в редакторе шли перечёркнутыми. Разница в одном
 * селекторе — ровно то, из-за чего «один дизайн» перестаёт быть одним.
 */
[data-skin="paper"] :is(.content, .preview) li:has(input[type="checkbox"]:checked),
[data-skin="paper"] .cm-task-done {
  color: var(--text);
  text-decoration: none;
}

/* Ячейка таблицы: строки в ней плотнее основного текста. */
[data-skin="paper"] :is(.content, .preview, .cm-editor) .table-scroll td {
  line-height: 1.6;
  color: inherit;
}

/* Код внутри строки: 0.9 от кегля вокруг. */
/* Правка считается тем же текстом, что и чтение: без `.cm-inline-code`
   здесь код в редакторе оставался на 0,88 и был мельче на треть
   пикселя. Незаметное расхождение живёт дольше заметного. */
/* Скин в селекторе обязателен и у редактора: без него правило слабее
   общего в base.css, которое стоит ниже по файлу и потому побеждает.
   Ровно на этом код в правке и оставался мельче на треть пикселя. */
[data-skin="paper"] :is(.content, .preview) code,
[data-skin="paper"] .cm-inline-code { font-size: 0.9em; }

/*
 * Стрелка у ссылки наружу.
 *
 * Она отвечает на единственный вопрос, который ссылка задаёт в рабочем
 * документе: уведёт ли это со страницы. Размер и подъём — из эталона.
 */
/* Контур живёт в base.css рядом с остальными значками — здесь только
   подъём под скин, если он понадобится. */

/*
 * ПЕРЕЧЕНЬ ССЫЛОК ВНУТРИ ВЫНОСКИ — строками с разделителями.
 *
 * Так в эталоне устроен блок «Рабочие материалы»: значок, название ссылкой,
 * под ним источник помельче, разделитель между строками во всю ширину плашки.
 *
 * Отрицательные поля у списка нужны, чтобы разделители доходили до краёв: без
 * них линии обрываются, не дойдя до рамки, и плашка выглядит недоделанной.
 * Никакой своей разметки при этом не нужно — это обычный список Markdown,
 * у которого подпись вынесена в отдельный абзац пустой строкой.
 */
/*
 * ЧТО ИМЕННО СЧИТАЕТСЯ ПЕРЕЧНЕМ — и почему условие такое длинное.
 *
 * `.callout-body:has(> ul > li > p > a)` — список, у которого В КАЖДОМ пункте
 * ссылка вынесена в свой абзац. В Markdown это значит, что у пункта есть
 * подпись, отделённая пустой строкой, то есть перед нами перечень материалов,
 * а не просто список внутри заметки.
 *
 * Условие обязано стоять на КАЖДОМ правиле ниже, а не только на первых двух.
 * Пока его не было, обычный список внутри любой выноски получал разделители,
 * значок и отрицательные поля: у заметки с тремя пунктами появлялись линии
 * поперёк плашки, которым там взяться неоткуда.
 */
[data-skin="paper"] .callout:has(.callout-body > ul > li > p > a) {
  padding: 9px 14px 0;
}

/*
 * Надпись «Рабочие материалы» на кегль мельче остальных выносок.
 *
 * В эталоне так: у выноски-вопроса заголовок 12, у этой плашки 11. Разница не
 * случайна — это не выноска, а шапка перечня, и она обязана быть тише того,
 * что перечисляет.
 */
[data-skin="paper"] .callout:has(.callout-body > ul > li > p > a) .callout-title {
  font-size: 11px;
}

/*
 * Текст занимает обе колонки сетки, а не одну правую: иначе строки перечня
 * начинаются не от края плашки, а от колонки значка, и разделители между ними
 * выглядят обрубленными слева. Значок при этом остаётся рядом с заголовком.
 */
[data-skin="paper"] .callout:has(.callout-body > ul > li > p > a) .callout-body {
  grid-column: 1 / -1;
}

[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul {
  list-style: none;
  margin: 9px -14px 0;
  padding: 0;
}

[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul > li {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 2px 12px;
  align-items: center;
  margin: 0;
  padding: 12px 14px;
  border-top: 1px solid color-mix(in srgb, var(--line-colour) 22%, var(--bg-colour));
  font-size: 15px;
}

/* Ссылка внутри плашки говорит цветом плашки, а не общим цветом ссылок. */
[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul > li a {
  color: var(--line-colour);
}

[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul > li::before {
  content: "▤";
  grid-column: 1;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  width: 24px;
  height: 24px;
  border: 1px solid color-mix(in srgb, var(--line-colour) 22%, var(--bg-colour));
  border-radius: 5px;
  background: var(--surface);
  color: var(--line-colour);
  font-size: 12px;
  /* Точку списка здесь заменяет значок — обычная точка была бы второй. */
  position: static;
  top: auto;
  left: auto;
}

[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul > li > * {
  grid-column: 2;
  margin: 0;
}

/* Второй абзац пункта — источник: откуда это и что это вообще такое. */
[data-skin="paper"] .callout-body:has(> ul > li > p > a) > ul > li > p + p {
  font-size: 12px;
  line-height: 1.5;
  color: color-mix(in srgb, var(--line-colour) 40%, var(--text-3));
}

/* ---------- 7. responsive: drawer under 860px ---------------- */

@media (max-width: 860px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 50;
    width: min(300px, 86vw);
    max-width: 86vw;
    padding: var(--sp-4);
    background: var(--surface);
    border-right: 1px solid var(--line-strong);
    box-shadow: var(--shadow-pop);
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }
  .app.is-drawer-open .sidebar,
  .app[data-drawer="open"] .sidebar,
  .sidebar:focus-within {
    transform: none;
    visibility: visible;
  }
  .app.is-drawer-open .scrim,
  .app[data-drawer="open"] .scrim { opacity: 1; visibility: visible; }

  /* the rail expands to a full list once it is a drawer */
  [data-skin="dense"] .sidebar { align-items: stretch; }
  [data-skin="dense"] .sidebar-project,
  [data-skin="dense"] .tree-title { display: block; }
  [data-skin="dense"] .tree-item { justify-content: flex-start; padding: 0 var(--sp-2); }

  :root {
    --content-pad-x: var(--sp-4);
    --content-pad-y: var(--sp-5);
    --fs-title: 30px;
    --fs-h1: 25px;
    --fs-h2: 21px;
  }
  :root[data-skin="quiet"] { --fs-body: 17px; }

  /*
   * paper приходится повторять здесь отдельно, и это не небрежность.
   *
   * Селектор `:root[data-skin="paper"]` весит больше, чем `:root`, и внутри
   * медиазапроса продолжал побеждать: на телефоне у колонки оставались поля
   * по 48 точек с каждой стороны, то есть четверть экрана уходила в пустоту.
   * Медиазапрос сам по себе веса не добавляет — это частая ловушка.
   */
  :root[data-skin="paper"] {
    --content-pad-x: var(--sp-4);
    --content-pad-y: var(--sp-5);
    --fs-title: 26px;
    --fs-h1: 26px;
    --fs-h2: 21px;
    --fs-h3: 18px;
  }

  .topbar { padding: 0 var(--sp-3); gap: var(--sp-2); }
  .toolbar { position: sticky; bottom: 0; }
  .tree-item,
  .popover-item { min-height: 44px; }              /* touch targets */
  .selection-bar > *,
  .tool-group > * { min-height: 40px; }
}

@media (max-width: 520px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
  .callout { padding: var(--sp-3); }
}

/* high-contrast / forced colors safety */
@media (forced-colors: active) {
  .tree-item.is-active,
  .popover-item.is-active { forced-color-adjust: none; outline: 1px solid CanvasText; }
  :where(a, button, input, [tabindex]):focus-visible { outline: 2px solid Highlight; }
}
