/* «Кухонная библиотека» — печатный лист. Тема перенесена из .streamlit/config.toml:
   бумажный фон, зелёный акцент, кегль 17px — аудитории (домашние повара,
   телефон/ноутбук) легче читать. Классы .cite-*, .rec-*, .tl-*, .trust,
   .more-sep, .kb-head перенесены из app.py как есть — их же отдаёт
   ragbook/answer_view.py, recipe_view.py и timeline_view.py.

   ЦВЕТА — ТОЛЬКО ТОКЕНАМИ. Ни одного hex вне :root и блока палитры книг:
   иначе тёмная тема и рестайл упираются в захардкоженные значения, которые
   нечем перекрыть. Токен назван по РОЛИ («поднятая бумага»), а не по цвету
   («кремовый»): в тёмной теме роль сохранится, а цвет — нет. */

:root {
  /* ---------------------------------------- бумага: поверхности по высоте */
  --paper:        #FAF8F2;  /* фон страницы */
  --paper-raised: #FFFFFF;  /* карточка ответа — самый белый лист */
  --paper-cream:  #FFFDF6;  /* мелкие поверхности: поле ввода, попап, рецепт */
  --paper-quiet:  #FBF8F0;  /* тихая врезка и ховер */
  --paper-inset:  #F5F0E2;  /* заметная врезка: раскладка, «успеть заранее» */
  --paper-aside:  #F7F3E8;  /* совет на полях внутри рецепта */
  --paper-lane:   #F2ECDD;  /* дорожка полосы времени (и линия её строк) */
  --paper-warn:   #FBF3E2;  /* плашка сбоя сервиса */
  --paper-pick:   #EDF3EE;  /* выбранный переключатель */
  --paper-nav:    #E3EDE3;  /* ховер строки навигации */
  --paper-gap:    #FAFDF8;  /* окно ожидания в «Плане готовки» */

  /* ------------------------------------------------------------- текст */
  --text:       #2C2A26;   /* основной */
  --text-book:  #33291C;   /* книжный набор: выписки, рецепты, план */
  --text-soft:  #4A4034;   /* второй план */
  --muted:      #8A8272;   /* подписи */
  --muted-soft: #A79E8B;   /* самые тихие подписи и швы */
  --ink-pill:   #5A5343;   /* текст кнопок-пилюль */
  --ink-aside:  #6B6355;   /* совет на полях */
  --ink-dash:   #7A7263;   /* пунктирная кнопка */
  --on-color:   #FFFFFF;   /* текст на цветной подложке */
  --dead:       #999999;   /* сноска в никуда */

  /* ------------------------------------------------------------- линии */
  --line:      #E0D8C6;    /* основная */
  --line-card: #E9E4D8;    /* кайма карточки ответа */
  --line-soft: #EDE6D6;    /* внутренние разделители и таблицы */
  --line-pill: #E4DDCC;    /* кайма пилюль и карточек рецепта */
  --line-dash: #DCD3BE;    /* пунктир и врезки */
  --line-firm: #C9BFA6;    /* линия под курсором */
  --line-warn: #EAD9B0;    /* кайма плашки сбоя */

  /* --------------------------------------------------- смысловые цвета */
  --accent:      #37725B;  /* зелёный акцент */
  --accent-deep: #2E6B4F;  /* нажатие */
  --trust:       #2E7D57;  /* цитаты сверены дословно */
  --trust-warn:  #8C6D1F;  /* сверено частично */
  --passive:     #7FA891;  /* идёт само */
  --attend:      #C9A227;  /* следить */
  --hand:        #8C3B33;  /* руками */
  --guide:       #8A7A3C;  /* время из справочника, не из книги */
  --guide-line:  #B9A45E;
  --stamp:       #7A4E9E;  /* штемпельная краска: «сверено дословно» */
  --edit:        #386095;  /* правка из приёмки: синие чернила корректора */
  --edit-wash:   #EDF2F8;  /* подложка следа правки */

  /* ------------------------------------------------------------- тени */
  --shadow-card:  0 4px 14px -12px rgba(60, 45, 10, .35);
  --shadow-pop:   0 14px 44px rgba(40, 30, 10, .35);
  --shadow-sheet: 0 -10px 34px rgba(40, 30, 10, .3);
  --ring:         rgba(44, 42, 38, .3);
  --scrim:        rgba(44, 42, 38, .38);
  --hairline:     rgba(0, 0, 0, .10);

  --serif: Georgia, "Times New Roman", serif;
  --sans: "Segoe UI", system-ui, sans-serif;
  /* Машинопись — только для метаданных: шифр источника, штамп, шапка бланка.
     Текст книги остаётся серифом всегда. */
  --mono: Consolas, "Cascadia Mono", ui-monospace, monospace;

  color-scheme: light;

  /* Цвет книги по умолчанию — для компонентов без класса .bk-* */
  --book: var(--hand);
}

/* Палитра книг. Индекс = позиция в PALETTE (ragbook/answer_view.py), класс
   ставит вьюха (`book_class`). Инлайн-стилем цвет книги задавать нельзя:
   инлайн выигрывает у любого правила темы. */
.bk-0 { --book: #8C3B33; }   /* бордо */
.bk-1 { --book: #3E6B4F; }   /* зелень */
.bk-2 { --book: #8A5A10; }   /* мёд */
.bk-3 { --book: #55447E; }   /* слива */
.bk-4 { --book: #386095; }   /* синий */
.bk-5 { --book: #6B4A2F; }   /* кофе */
.bk-6 { --book: #4A4A45; }   /* графит */
.bk-7 { --book: #8F7500; }   /* горчица */

/* ------------------------------------------------------- тёмная тема
   «Кухня вечером», а не инверсия: тёплый почти-чёрный фон, кремовый текст,
   акценты подняты по светлоте (на тёмном тот же зелёный читается глуше).
   Список значений продублирован намеренно: системная тема и ручной выбор —
   разные селекторы, а объединить их в один медиазапрос CSS не даёт.
   Правишь один блок — правь второй. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper:        #17140F;
    --paper-raised: #1E1A14;
    --paper-cream:  #221E17;
    --paper-quiet:  #1C1913;
    --paper-inset:  #262117;
    --paper-aside:  #241F18;
    --paper-lane:   #2E2A22;
    --paper-pick:   #1F2E26;
    --paper-nav:    #202A22;
    --paper-warn:   #2C2415;
    --paper-gap:    #161D18;

    --text:       #E8E1D2;
    --text-book:  #EDE6D8;
    --text-soft:  #C9C0AE;
    --muted:      #9A9384;
    --muted-soft: #7C7566;
    --ink-pill:   #C4BBA6;
    --ink-aside:  #ADA492;
    --ink-dash:   #A79E8B;
    --on-color:   #17140F;   /* тёмные чернила на светлых акцентах и номерках */
    --dead:       #6B675E;

    --line:      #3A342A;
    --line-card: #2F2A22;
    --line-soft: #2A251E;
    --line-pill: #3A342A;
    --line-dash: #453E32;
    --line-firm: #57503F;
    --line-warn: #4A3D20;

    --accent:      #7FB79C;
    --accent-deep: #96C9B0;
    --trust:       #7FB79C;
    --trust-warn:  #C7A94E;
    --passive:     #8FC0A6;
    --attend:      #D9B646;
    --hand:        #C4685C;
    --guide:       #B3A05F;
    --guide-line:  #6E6238;
    --stamp:       #A98AD1;
    --edit:        #7FA3CC;
    --edit-wash:   #1C2530;

    --shadow-card:  0 4px 14px -12px rgba(0, 0, 0, .8);
    --shadow-pop:   0 14px 44px rgba(0, 0, 0, .65);
    --shadow-sheet: 0 -10px 34px rgba(0, 0, 0, .6);
    --ring:         rgba(237, 230, 216, .45);
    --scrim:        rgba(8, 7, 5, .62);
    --hairline:     rgba(255, 255, 255, .12);
  }
  :root:not([data-theme="light"]) .bk-0 { --book: #C4685C; }
  :root:not([data-theme="light"]) .bk-1 { --book: #6E9E7E; }
  :root:not([data-theme="light"]) .bk-2 { --book: #C08E36; }
  :root:not([data-theme="light"]) .bk-3 { --book: #8C7BBD; }
  :root:not([data-theme="light"]) .bk-4 { --book: #6C9BD0; }
  :root:not([data-theme="light"]) .bk-5 { --book: #A67C55; }
  :root:not([data-theme="light"]) .bk-6 { --book: #8A8A82; }
  :root:not([data-theme="light"]) .bk-7 { --book: #C4A62E; }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --paper:        #17140F;
  --paper-raised: #1E1A14;
  --paper-cream:  #221E17;
  --paper-quiet:  #1C1913;
  --paper-inset:  #262117;
  --paper-aside:  #241F18;
  --paper-lane:   #2E2A22;
  --paper-pick:   #1F2E26;
  --paper-nav:    #202A22;
  --paper-warn:   #2C2415;
  --paper-gap:    #161D18;

  --text:       #E8E1D2;
  --text-book:  #EDE6D8;
  --text-soft:  #C9C0AE;
  --muted:      #9A9384;
  --muted-soft: #7C7566;
  --ink-pill:   #C4BBA6;
  --ink-aside:  #ADA492;
  --ink-dash:   #A79E8B;
  --on-color:   #17140F;
  --dead:       #6B675E;

  --line:      #3A342A;
  --line-card: #2F2A22;
  --line-soft: #2A251E;
  --line-pill: #3A342A;
  --line-dash: #453E32;
  --line-firm: #57503F;
  --line-warn: #4A3D20;

  --accent:      #7FB79C;
  --accent-deep: #96C9B0;
  --trust:       #7FB79C;
  --trust-warn:  #C7A94E;
  --passive:     #8FC0A6;
  --attend:      #D9B646;
  --hand:        #C4685C;
  --guide:       #B3A05F;
  --guide-line:  #6E6238;
  --stamp:       #A98AD1;
  --edit:        #7FA3CC;
  --edit-wash:   #1C2530;

  --shadow-card:  0 4px 14px -12px rgba(0, 0, 0, .8);
  --shadow-pop:   0 14px 44px rgba(0, 0, 0, .65);
  --shadow-sheet: 0 -10px 34px rgba(0, 0, 0, .6);
  --ring:         rgba(237, 230, 216, .45);
  --scrim:        rgba(8, 7, 5, .62);
  --hairline:     rgba(255, 255, 255, .12);
}
:root[data-theme="dark"] .bk-0 { --book: #C4685C; }
:root[data-theme="dark"] .bk-1 { --book: #6E9E7E; }
:root[data-theme="dark"] .bk-2 { --book: #C08E36; }
:root[data-theme="dark"] .bk-3 { --book: #8C7BBD; }
:root[data-theme="dark"] .bk-4 { --book: #6C9BD0; }
:root[data-theme="dark"] .bk-5 { --book: #A67C55; }
:root[data-theme="dark"] .bk-6 { --book: #8A8A82; }
:root[data-theme="dark"] .bk-7 { --book: #C4A62E; }

/* Переключатель темы в шапке: 🌙 / ☀️. Значение пишет kb.js в localStorage,
   а читает его инлайн-скрипт в <head> — до первой отрисовки, иначе тёмный
   экран моргнёт светлым. */
.kb-theme { margin-left: auto; border: 1px solid var(--line-pill);
  background: var(--paper-cream); border-radius: 50%; width: 2.1rem;
  height: 2.1rem; line-height: 1; font-size: .95rem; cursor: pointer;
  align-self: center; }
.kb-theme:hover { border-color: var(--accent); }

* { box-sizing: border-box; }
html { font-size: 17px; }
body {
  margin: 0; background: var(--paper); color: var(--text);
  font-family: var(--sans); line-height: 1.5;
  display: flex; min-height: 100vh;
}

/* ------------------------------------------------------------- каркас */

main {
  flex: 1 1 auto; min-width: 0; max-width: 46rem; margin: 0 auto;
  padding: 1.2rem 1rem 9rem;
}
body.sheet-open { overflow: hidden; }   /* фон не уезжает под шторкой */
hr { border: none; border-top: 1px solid var(--line); margin: .9rem 0; }
h4 { margin: .4rem 0 .3rem; font-size: .95rem; }

/* печатная шапка */
.kb-head { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  border-bottom: 3px double var(--line); padding-bottom: .55rem; margin-bottom: .5rem; }
.kb-head .t { font-family: var(--serif); font-size: 1.45rem; }

/* ------------------------------------------------ строка чипов навигации */

/* Липкая: «полка сужена» должно быть видно и на середине длинного ответа. */
.kb-chips { position: sticky; top: 0; z-index: 60; display: flex; gap: .35rem;
  overflow-x: auto; scrollbar-width: none; background: var(--paper);
  border-bottom: 1px solid var(--line-soft); padding: .45rem 0; margin-bottom: .6rem; }
.kb-chips::-webkit-scrollbar { display: none; }
.kb-chips form { display: contents; }
.kb-nav { flex: 0 0 auto; border: 1px solid var(--line-pill); background: var(--paper-cream);
  border-radius: 16px; padding: .3rem .85rem; min-height: 2rem; cursor: pointer;
  font-family: var(--sans); font-size: .85rem; color: var(--ink-pill);
  white-space: nowrap; }
.kb-nav:hover { border-color: var(--line-firm); color: var(--accent); }
/* Чип полки зелёный только когда полка СУЖЕНА: цвет здесь — сигнал фильтра,
   а не украшение. Полная полка — состояние по умолчанию, оно молчит. */
.kb-nav.on { border-color: var(--accent); color: var(--accent);
  background: var(--paper-pick); font-weight: 600; }

/* ----------------------------------------------------------- шторки */

.kb-scrim { position: fixed; inset: 0; z-index: 400; background: var(--scrim); }
.kb-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 500;
  background: var(--paper-cream); border-radius: 18px 18px 0 0;
  padding: .5rem 1rem 1.4rem; box-shadow: var(--shadow-sheet);
  max-height: 72vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  font-size: .9rem; }
.kb-scrim[hidden], .kb-sheet[hidden] { display: none; }
.kb-grab { display: block; width: 2.4rem; height: 4px; border-radius: 2px;
  background: var(--line-dash); margin: .25rem auto .7rem; cursor: grab; }
.kb-sheet h5 { font-family: var(--serif); font-weight: 600; font-size: 1.1rem;
  margin: 0 0 .5rem; }
.kb-sheet .kb-cap { margin: .5rem 0; }
.sheet-go { margin-top: .3rem; width: 100%; }

@media (min-width: 901px) {
  /* Десктоп — та же шторка центрированным попапом: один каркас, не два макета. */
  .kb-sheet { left: 50%; right: auto; transform: translateX(-50%);
    bottom: auto; top: 8vh; width: min(94vw, 30rem); border-radius: 14px;
    box-shadow: var(--shadow-pop); }
  .kb-grab { cursor: default; }
}

/* ------------------------------------------------------- лента-диалог */

.qa { margin: 1rem 0; }

/* вопрос — рубрика с двойной линейкой, а не пузырь чата: ширина строки на
   телефоне дороже диалоговости, а диалог передаёт чередование «рубрика → лист» */
.kb-ask { border-bottom: 3px double var(--line); margin: 1.6rem 0 .7rem;
  padding-bottom: .5rem; }
.kb-eyebrow { margin: 0; font-family: var(--sans); font-size: .68rem;
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted-soft); }
.kb-q { margin: .2rem 0 0; font-family: var(--serif); font-weight: 600;
  font-size: 1.28rem; line-height: 1.25; white-space: pre-wrap; }

/* ответ — лист с книжным набором */
.kb-card {
  background: var(--paper-raised); border: 1px solid var(--line-card);
  border-radius: 4px 18px 18px 18px;
  padding: .85rem 1rem .7rem; margin-top: .6rem;
  box-shadow: var(--shadow-card); }
.kb-card p, .kb-card li {
  font-family: var(--serif); font-size: 1.04rem; line-height: 1.68; }
.kb-card h1, .kb-card h2, .kb-card h3, .kb-card h4 {
  font-family: var(--serif); font-weight: 600; font-size: 1.12rem; }
.kb-card table { border-collapse: collapse; margin: .4rem 0; }
.kb-card table td, .kb-card table th {
  border-bottom: 1px solid var(--line-soft); padding: .18rem .55rem .18rem 0;
  font-family: var(--serif); font-size: .95rem; text-align: left; }

/* служебные строки: тонкие подписи, а не плашки */
.kb-cap { color: var(--muted); font-size: .8rem; margin: .15rem 0;
  font-family: var(--sans) !important; }
.kb-card .kb-cap { font-size: .8rem; line-height: 1.4; }
.kb-warn { background: var(--paper-warn); border: 1px solid var(--line-warn);
  border-radius: 10px; padding: .6rem .9rem; }
.kb-warn p { margin: .2rem 0; }

/* статус стрима и «печатающийся» черновик */
.kb-status { color: var(--muted); font-size: .85rem; }

/* Сценка ожидания. Ответ собирается 30–40 секунд, и всё это время видна одна
   строка: часы ⏳ сообщали только «ждите», хотя идёт работа. Сценок две
   (`render.WAIT_SCENES`), выбираются наугад — чтобы значок не примелькался
   тому, кто спрашивает по десятку раз за вечер.

   Значок — СОСЕД строки статуса, а не её содержимое: `kb.js` обновляет этап
   через `textContent`, и вложенный SVG стёрся бы на первом событии stage.
   Цвет — чернила самой строки (`currentColor`): это часть подписи «ищу», а не
   новый сигнал, и заводить ради него смысловой цвет нельзя. */
.kb-wait { display: flex; align-items: center; gap: .7rem; }
.kb-wait .kb-status { margin: 0; }
.ld { flex: none; overflow: visible; }

/* опара дышит: пузыри всплывают и лопаются на поверхности */
.ld-ferm circle { transform-box: fill-box; transform-origin: 50% 50%; }
.ld-ferm .b1 { animation: fm-bub 2.6s ease-in infinite; }
.ld-ferm .b2 { animation: fm-bub 2.6s ease-in infinite .7s; }
.ld-ferm .b3 { animation: fm-bub 2.6s ease-in infinite 1.4s; }
.ld-ferm .b4 { animation: fm-bub 2.6s ease-in infinite 2s; }
.ld-ferm .surf { animation: fm-surf 2.6s ease-in-out infinite; }
@keyframes fm-bub {
  0%   { opacity: 0; transform: translateY(0) scale(.5); }
  25%  { opacity: .85; }
  80%  { opacity: .85; transform: translateY(-9px) scale(1); }
  100% { opacity: 0; transform: translateY(-12px) scale(1.5); }
}
@keyframes fm-surf {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-1.5px); }
}

/* листают книгу: страницы перекладываются справа налево */
.ld-book { perspective: 120px; }
.ld-book .page, .ld-book .page2 { transform-origin: 26px 8px;
  animation: bp-flip 2.4s ease-in-out infinite; }
.ld-book .page2 { animation-delay: .8s; }
@keyframes bp-flip {
  0%, 10%   { transform: rotateY(0deg); opacity: .85; }
  55%       { transform: rotateY(-100deg); opacity: .55; }
  70%, 100% { transform: rotateY(-180deg); opacity: 0; }
}

/* «Уменьшить движение» — системная настройка, а не пожелание: сценка замирает
   целиком, строка этапа продолжает рассказывать, что происходит. */
@media (prefers-reduced-motion: reduce) {
  .ld * { animation: none !important; }
}
.kb-typing { font-family: var(--serif); font-size: 1.02rem; line-height: 1.6;
  white-space: pre-wrap; color: var(--text-soft); }

/* Номерок-сноска: цель касания, а не значок. Цвет — книги (класс .bk-*). */
.cite-n { display: inline-block; min-width: 1.2rem; min-height: 1.2rem;
  margin: 0 .1rem; padding: .1rem .34rem; border: none; border-radius: .7rem;
  text-align: center; background: var(--book); color: var(--on-color);
  font-family: var(--sans); font-size: .72rem; font-weight: 700; line-height: 1.1;
  vertical-align: .12em; cursor: pointer; user-select: none; }
.cite-n[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--ring); }
sup.cite-dead { color: var(--dead); font-size: .7rem; }

/* Выписка — блок ПОД своим абзацем, а не попап поверх текста: раскрытие
   толкает текст вниз, и видно, к какой фразе относится цитата. */
.cite-inline { border-left: 3px solid var(--book); border-radius: 0 10px 10px 0;
  background: var(--paper-quiet); padding: .55rem .8rem .5rem; margin: .1rem 0 .8rem; }
.cite-inline[hidden] { display: none; }
/* Шифр источника — машинописью и капителью, как на каталожной карточке.
   Метаданные, и только они: текст книги под шифром остаётся серифом. */
.cite-h { display: block; color: var(--book); font-family: var(--mono);
  font-size: .72rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; }
.cite-crumbs { display: block; color: var(--muted); margin-top: .1rem;
  font-family: var(--sans); font-size: .74rem; }
.cite-b { display: block; margin-top: .35rem; font-family: var(--serif);
  font-size: .95rem; line-height: 1.55; color: var(--text-book); }
.cite-x { margin-top: .4rem; border: none; background: transparent; cursor: pointer;
  padding: .2rem 0; color: var(--muted); font-family: var(--sans); font-size: .74rem; }
.cite-x:hover { color: var(--accent); }

/* Строка доверия к цитатам. Полная сверка — штамп, частичная — строка:
   разница в подаче ровно такая же, как разница в смысле. */
.trust { color: var(--trust); font-size: .83rem !important; margin: .15rem 0 0;
  font-family: var(--sans) !important; }
.trust.warn { color: var(--trust-warn); }
.stamp { display: inline-block; margin: .7rem 0 .1rem; padding: .22rem .6rem;
  border: 2px solid var(--stamp); border-radius: 4px; color: var(--stamp);
  transform: rotate(-3deg); opacity: .85;
  font-family: var(--mono) !important; font-size: .7rem !important;
  letter-spacing: .14em; text-transform: uppercase; }

/* шов «Ещё из книг» между ответом и дочитанным дополнением */
.more-sep { display: flex; align-items: center; gap: .6rem; margin: 1rem 0 .3rem;
  color: var(--muted-soft); font-family: var(--sans) !important;
  font-size: .72rem !important; letter-spacing: .08em; text-transform: uppercase; }
.more-sep::before, .more-sep::after { content: ""; flex: 1; height: 1px;
  background: var(--line-soft); }

/* ---------------------------------------------- хвост карточки */

/* Одна линейка целей касания: «＋ Ещё», 👍, 👎, «📷 стр.» — все ≥40 px. */
.kb-tail { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .4rem;
  margin-top: .7rem; }
/* обёртка прозрачна для раскладки: кнопки — прямые элементы линейки, но
   `hx-target="closest .kb-more-row"` продолжает находить свою цель */
.kb-more-row { display: contents; }
.kb-tbtn { display: inline-flex; align-items: center; justify-content: center;
  min-height: 2.35rem; padding: 0 .85rem; border: 1px solid var(--line-pill);
  border-radius: 1.2rem; background: var(--paper-cream); color: var(--ink-dash);
  font-family: var(--sans); font-size: .82rem; line-height: 1.2; cursor: pointer; }
.kb-tbtn:hover { border-color: var(--accent); color: var(--accent);
  background: var(--paper-quiet); }
.kb-fb { display: flex; gap: .4rem; }
.kb-fb-done { align-items: center; min-height: 2.35rem; color: var(--muted);
  font-family: var(--sans); font-size: .78rem; }
/* стрим дочитывания встаёт на место кнопки — своей строкой, а не в ряд */
.kb-tail .kb-stream { flex: 1 1 100%; }

/* кнопка-приглашение вне хвоста — пунктир: это не главное действие */
.kb-dash {
  border: 1px dashed var(--line-dash); background: transparent; box-shadow: none;
  color: var(--ink-dash); border-radius: 12px; padding: .35rem .8rem; cursor: pointer;
  font-family: var(--sans); font-size: .82rem; line-height: 1.5; }
.kb-dash:hover { border-color: var(--accent); color: var(--accent);
  background: var(--paper-quiet); }

/* «Почему не нашлось?» — тихая строка-раскрывашка */
.kb-why { margin-top: .3rem; }
.kb-why > summary { color: var(--muted); font-size: .8rem; cursor: pointer;
  list-style: none; font-family: var(--sans); }
.kb-why > summary::-webkit-details-marker { display: none; }
.kb-why > summary:hover { color: var(--accent); }
.kb-why-body { color: var(--text-soft); font-size: .88rem; padding: .4rem .2rem;
  font-family: var(--sans); }

/* ------------------------------------------------- карточка рецепта */

.rec-card { border: 1px solid var(--line-pill); border-left: 4px solid var(--book);
  border-radius: 10px; background: var(--paper-cream); padding: .7rem .95rem .8rem;
  margin: .5rem 0 .2rem; }
.rec-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: .8rem; flex-wrap: wrap; margin-bottom: .35rem; }
.rec-title { font-family: var(--serif); font-size: 1.06rem;
  font-weight: 600; color: var(--text-book); }
.rec-src { color: var(--muted); font-family: var(--mono);
  font-size: .7rem; letter-spacing: .07em; text-transform: uppercase;
  white-space: nowrap; }
.rec-crumbs { color: var(--muted-soft); font-family: var(--sans);
  font-size: .74rem; margin-bottom: .45rem; }
.rec-body { font-family: var(--serif); font-size: 1rem;
  line-height: 1.62; color: var(--text-book); }
.rec-body p { margin: 0 0 .5rem; font-size: 1rem; }
.rec-lay { display: block; margin-top: .5rem; padding: .45rem .7rem;
  background: var(--paper-inset); border-radius: 8px; font-family: var(--serif);
  font-size: .93rem; color: var(--text-soft); }
.rec-lay b { color: var(--text-book); }
.rec-base { margin-top: .55rem; padding: .5rem .7rem; border-left: 3px solid var(--line);
  background: var(--paper-quiet); font-family: var(--serif); font-size: .93rem;
  line-height: 1.55; color: var(--text-soft); }
.rec-base .h { display: block; color: var(--muted);
  font-family: var(--sans); font-size: .74rem; margin-bottom: .25rem; }
/* врезка книги внутри рецепта — совет на полях, а не шаг приготовления */
.rec-aside { margin: .45rem 0; padding: .4rem .7rem; border-left: 3px solid var(--line-dash);
  background: var(--paper-aside); color: var(--ink-aside); font-family: var(--sans);
  font-size: .82rem; line-height: 1.5; }
/* таблица ингредиентов (Монтанари): узкая, без шапки-заголовка */
.rec-tbl { border-collapse: collapse; margin: .4rem 0 .5rem; font-size: .9rem; }
.rec-tbl td { border-bottom: 1px solid var(--line-soft); padding: .18rem .55rem .18rem 0;
  vertical-align: top; }
.rec-tbl tr:first-child td { color: var(--muted); font-weight: 600;
  font-family: var(--sans); font-size: .78rem; }
.rec-note { color: var(--muted); font-size: .78rem !important;
  font-family: var(--sans) !important; margin: .2rem 0 .4rem; }
/* свёрнутые рецепты: строка-ссылка, раскрывается нажатием */
details.rec-more { border-top: 1px dotted var(--line-pill); padding: .32rem 0; }
details.rec-more > summary { cursor: pointer; list-style: none;
  font-family: var(--serif); font-size: .97rem; color: var(--text-book); }
details.rec-more > summary::-webkit-details-marker { display: none; }
details.rec-more > summary:hover { color: var(--hand); }
details.rec-more > summary .rec-src { margin-left: .5rem; }
details.rec-more[open] > summary { font-weight: 600; margin-bottom: .3rem; }

/* переключатели порций и способа приготовления */
.kb-portions, .kb-variants { display: flex; gap: .2rem; flex-wrap: wrap;
  margin: .4rem 0 .2rem; }
.kb-radio { border: 1px solid var(--line-pill); border-radius: 16px; padding: .12rem .7rem;
  font-size: .82rem; font-family: var(--sans); color: var(--ink-pill); cursor: pointer;
  background: var(--paper-cream); }
.kb-radio:hover { border-color: var(--line-firm); color: var(--accent); }
.kb-radio input { display: none; }
.kb-radio:has(input:checked) { border-color: var(--accent); color: var(--accent);
  background: var(--paper-pick); }

/* вкладки «Рецепт из книги / План готовки» */
.kb-tabs { display: flex; gap: .2rem; border-bottom: 1px solid var(--line);
  margin-top: .5rem; }
.kb-tab { border: none; background: transparent; cursor: pointer;
  font-family: var(--sans); font-size: .85rem; color: var(--muted);
  padding: .3rem .7rem; border-bottom: 2px solid transparent; }
.kb-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.hidden { display: none; }

/* ------------------------------------------------- «План готовки»
   Крупные шаги, а не строка-таблица (прототип PLAN-REDESIGN-MOCKUP.html,
   26.07.2026). Дорожки-шкалы у строки больше нет: на 390 px она занимала
   четверть ширины и при этом не читалась — двенадцать шагов давали полоски
   в несколько пикселей. Масштаб времени несут отметки слева, блок «сначала
   поставьте» и плашки свободных окон. */

.tl { font-family: var(--sans); font-size: .95rem; color: var(--text-book); }
.tl-sum { padding: .5rem .1rem .1rem; color: var(--muted); font-size: .82rem; }
.tl-sum b { font-size: 1.15rem; color: var(--text-book); font-weight: 600; }
.tl-ahead { margin: .5rem 0 .6rem; padding: .45rem .7rem; border-radius: 8px;
  background: var(--paper-inset); border-left: 3px solid var(--attend); }
.tl-ahead .h { display: block; font-size: .74rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); margin-bottom: .2rem; }
.tl-ahead-row { overflow: hidden; }   /* длительность в строке уходит вправо */

/* ------------------------------------------------- час подачи (Р3)
   Сервер отдаёт режим «Без часа», пересчёт делает kb.js по data-min. Строка
   .tl-fine — обязательная часть блока, а не мелкий шрифт: часы выглядят
   точнее, чем план есть на самом деле. */

.tl-serve { margin: .55rem 0 0; padding: .7rem .8rem; border-radius: 8px;
  background: var(--paper-inset); border: 1px solid var(--line-dash); }
.tl-serve-l { font-size: .82rem; color: var(--muted); }
.tl-time { font-family: var(--sans); font-size: .95rem; font-weight: 600;
  color: var(--text-book); background: var(--paper-cream);
  border: 1px solid var(--line); border-radius: 6px; padding: .2rem .4rem;
  margin-left: .35rem; min-height: 2rem; }
.tl-start { margin: .45rem 0 0; font-size: .88rem; color: var(--text-soft); }
.tl-start b { font-size: 1.35rem; color: var(--hand);
  font-variant-numeric: tabular-nums; }
.tl-fine { margin: .3rem 0 0; font-size: .72rem; color: var(--muted-soft); }
/* Чипы уезжают горизонтально: четыре пресета в 390 px не помещаются, а
   переносить их в две строки — отдавать блоку пол-экрана. */
.tl-chips { display: flex; gap: .3rem; margin: .5rem 0 0; overflow-x: auto;
  scrollbar-width: none; }
.tl-chips::-webkit-scrollbar { display: none; }
.tl-chip { flex: 0 0 auto; font-family: var(--sans); font-size: .78rem;
  padding: .3rem .7rem; min-height: 2.2rem; border: 1px solid var(--line-pill);
  border-radius: 14px; background: var(--paper-cream); color: var(--ink-pill);
  cursor: pointer; white-space: nowrap; }
.tl-chip[aria-pressed="true"] { border-color: var(--accent); color: var(--accent);
  background: var(--paper-pick); }

/* Рубрика над куском ленты: «сначала поставьте» / «пока идёт» / «по порядку».
   Машинопись капителью — тот же жест, что шифр источника в карточке. */
.tl-eye { display: block; margin: 1rem 0 .3rem; font-family: var(--mono);
  font-size: .62rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted-soft); }

/* «Сначала поставьте»: длинная варка с нуля, из-за которой весь остальной план
   и укладывается параллельно. */
.tl-hero { padding: .7rem .8rem .75rem; background: var(--paper-cream);
  border: 1px solid var(--line-pill); border-left: 4px solid var(--passive);
  border-radius: 6px; overflow: hidden; }
.tl-hero .h { font-size: 1.02rem; font-weight: 600; color: var(--text-book); }
.tl-hero .q { display: block; margin-top: .3rem; font-family: var(--serif);
  font-size: .92rem; line-height: 1.45; color: var(--text-soft); }
.tl-hero .m { display: block; margin-top: .4rem; font-size: .8rem; color: var(--accent); }

/* --------------------------------------------------------------- шаг */

/* Поток шагов и окон. Оформления у контейнера нет — он существует, чтобы
   отделить строки ленты от блока «сначала поставьте» и подвала-легенды: по
   нему же тесты отличают строку с пометкой происхождения от образца той же
   пометки в легенде (`_rows` в tests/test_timeline.py). */
.tl-rows { display: block; }

details.tl-step { border-bottom: 1px solid var(--line-soft); }
details.tl-step > summary { display: flex; gap: .55rem; align-items: flex-start;
  min-height: 2.9rem; padding: .5rem 0; cursor: pointer; list-style: none; }
details.tl-step > summary::-webkit-details-marker { display: none; }
/* Признак того, что под шагом лежит фраза книги: без него строка не выглядит
   нажимаемой, и «один клик до источника» остаётся секретом. */
details.tl-step > summary::after { content: "▾"; align-self: flex-start;
  padding-top: .55rem; font-size: .7rem; color: var(--muted-soft); }
details.tl-step[open] > summary::after { content: "▴"; }
details.tl-step[open] > summary { background: var(--paper-quiet); }
.tl-at { flex: 0 0 2.6rem; padding-top: .1rem; font-family: var(--mono);
  font-size: .74rem; color: var(--muted-soft); font-variant-numeric: tabular-nums; }
/* Рельс вместо шкалы: цвет = род работы, длина = высота строки. */
.tl-rail { flex: 0 0 3px; align-self: stretch; border-radius: 2px;
  background: var(--paper-lane); }
.tl-passive > summary .tl-rail { background: var(--passive); }   /* идёт само */
.tl-attended > summary .tl-rail { background: var(--attend); }   /* следить */
.tl-active > summary .tl-rail { background: var(--hand); }       /* руками */
/* overflow-wrap здесь НЕ ставится: длительность плавает вправо, на первой
   строке остаётся узкий просвет, и break-word рвёт по нему первое же слово
   («Спассе/ровать»). Слово должно целиком уходить на вторую строку. */
.tl-what { flex: 1 1 auto; min-width: 0; line-height: 1.35; color: var(--text); }
.tl-sub { display: block; margin-top: .1rem; font-size: .74rem;
  color: var(--muted-soft); line-height: 1.3; }
.tl-sub-book { color: var(--accent); }

/* Длительность: место в строке отдельно от цвета происхождения — модификаторы
   служат и образцами в легенде, где плавать вправо им незачем. */
.tl-dur { float: right; margin-left: .5rem; font-size: .84rem; white-space: nowrap; }
.tl-book  { color: var(--accent); }
.tl-guide { color: var(--guide); border-bottom: 1px dotted var(--guide-line);
  cursor: help; }
.tl-adapt { color: var(--hand); cursor: help; }
.tl-none  { color: var(--muted-soft); font-style: italic; }
.tl-ref { font-style: normal; color: var(--muted); font-size: .78rem;
  margin-left: .3rem; }
.tl-temp { margin-left: .35rem; color: var(--hand); font-size: .82rem; }

/* фраза книги под шагом */
.tl-src { padding: 0 .2rem .7rem 3.7rem; font-family: var(--serif);
  font-size: .92rem; line-height: 1.5; color: var(--text-soft);
  overflow-wrap: break-word; }
.tl-src .p { display: block; margin-top: .25rem; font-family: var(--mono);
  font-size: .64rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted-soft); }

/* свободное окно — плашкой: ради него лента и существует */
.tl-win { margin: .6rem 0; padding: .7rem .8rem; border-radius: 6px;
  background: var(--paper-gap); border: 1px dashed var(--passive); }
.tl-win .t { font-size: 1.05rem; font-weight: 600; color: var(--accent); }
.tl-win .s { display: block; margin-top: .1rem; font-size: .8rem;
  color: var(--text-soft); }

.tl-from { padding: .4rem .1rem 0; color: var(--muted); font-size: .8rem; }

/* легенда одной сноской: свёрнута, но развернуть её можно всегда */
details.tl-foot { margin-top: 1rem; border-top: 1px dotted var(--line-pill); }
details.tl-foot > summary { padding: .7rem .1rem; font-size: .8rem;
  color: var(--muted); cursor: pointer; list-style: none; }
details.tl-foot > summary::-webkit-details-marker { display: none; }
details.tl-foot > summary::after { content: " ▾"; }
details.tl-foot[open] > summary::after { content: " ▴"; }
.tl-foot .body { padding: 0 .1rem .9rem; font-size: .8rem; line-height: 1.55;
  color: var(--muted); }
.tl-foot .body span { margin-right: .8rem; white-space: nowrap; }
.tl-foot .body p { margin: .5rem 0 0; }

.tl-empty { margin: .35rem 0 .2rem; padding: .4rem .7rem; border-radius: 8px;
  background: var(--paper-quiet); border: 1px dashed var(--line-pill); color: var(--muted);
  font-family: var(--sans); font-size: .8rem; }

/* ------------------------------------------------- содержимое шторок */
/* Классы .sb-* и .toc-* остались от сайдбара: их отдаёт web/toc.py, и переезд
   в шторки их не касается. Размеры целей касания подняты — палец, не курсор. */

.sb-block > summary { cursor: pointer; font-weight: 600; padding: .35rem 0;
  list-style: none; }
.sb-block > summary::-webkit-details-marker { display: none; }
.sb-block > summary::before { content: "▸ "; color: var(--muted); }
.sb-block[open] > summary::before { content: "▾ "; }
.kb-check { display: flex; align-items: center; gap: .15rem; padding: .4rem 0;
  cursor: pointer; border-bottom: 1px solid var(--line-soft); }
.kb-check:last-of-type { border-bottom: none; }
.kb-check input { accent-color: var(--accent); margin-right: .3rem;
  width: 1.05rem; height: 1.05rem; }

/* строки «Содержания» и указателя: плотное оглавление, а не столбик кнопок */
.sb-item { display: block; width: 100%; text-align: left; border: none;
  background: transparent; cursor: pointer; font-family: var(--sans);
  font-size: .85rem; line-height: 1.35; color: var(--text);
  padding: .35rem .45rem; border-radius: 8px; }
.sb-item:hover { background: var(--paper-nav); }
.sb-all { color: var(--accent); }
/* Строка «Содержания» о двух целях: название кладут в вопрос, номер полосы
   открывает саму страницу книги. Номер набран цифрами и справа — как в
   печатном оглавлении, где после названия идёт страница. */
.sb-line { display: flex; align-items: center; gap: .2rem; }
.sb-line > .sb-item { flex: 1 1 auto; min-width: 0; }
/* Номер полосы — ссылка на /read (работает и без JS), поэтому здесь снимается
   подчёркивание и цвет ссылки: выглядеть она должна как номер в оглавлении. */
.sb-page { flex: 0 0 auto; min-width: 2.6rem; padding: .3rem .4rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-soft); border-radius: 8px; background: transparent;
  color: var(--muted); font-family: var(--sans); font-size: .74rem;
  font-variant-numeric: tabular-nums; cursor: pointer; text-decoration: none; }
.sb-page:hover { color: var(--accent); border-color: var(--accent); }
.toc-node > summary { cursor: pointer; list-style: none; font-size: .85rem;
  padding: .35rem .45rem; border-radius: 8px;
  display: flex; align-items: center; gap: .2rem; }
.toc-node > summary > .toc-t { flex: 1 1 auto; min-width: 0; }
.toc-node > summary::-webkit-details-marker { display: none; }
.toc-node > summary::before { content: "▸ "; color: var(--muted); }
.toc-node[open] > summary::before { content: "▾ "; }
.toc-node > summary:hover { background: var(--paper-nav); }
.toc-kids { padding-left: .7rem; }
.idx-pick { display: flex; gap: .4rem; margin-bottom: .4rem; }
.idx-pick select { flex: 1 1 0; min-width: 0; padding: .35rem;
  border: 1px solid var(--line); border-radius: 8px; background: var(--paper-cream);
  font-family: var(--sans); font-size: .85rem; color: var(--text); }

/* --------------------------------------------------- конец ленты */

/* «Новый разговор» — в конце ленты: его жмут, дочитав ответ. На пустой ленте
   прячется (нечего начинать заново). */
.feed-end { display: flex; justify-content: center; margin: 1.4rem 0 .2rem; }
#feed:empty + .feed-end { display: none; }

/* ------------------------------------------- поле ввода и чипсы-примеры */

/* Панель ввода прижата к нижнему краю ВИДИМОЙ области: на телефоне layout- и
   visual-вьюпорты расходятся (адресная строка, клавиатура), и просто
   `position: fixed` уезжает за край экрана — доводит по visualViewport kb.js.
   env(safe-area-inset-bottom) — для экранов с домашней полосой. */
#askbar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 100;
  background: linear-gradient(to top, var(--paper) 75%, transparent);
  padding: 1.2rem 0 calc(.9rem + env(safe-area-inset-bottom, 0px)); }
#ask-form { display: flex; gap: .5rem; align-items: flex-end;
  width: min(94vw, 44rem); margin: 0 auto; }
/* Пилюля: одна строка по умолчанию, растёт под текст (kb.js), потолок — 7rem. */
#ask-form textarea { flex: 1 1 auto; resize: none; border: 1px solid var(--line);
  border-radius: 1.4rem; padding: .6rem 1rem; font-family: var(--sans);
  font-size: .95rem; line-height: 1.4; max-height: 7rem;
  background: var(--paper-cream); color: var(--text); }
#ask-form textarea:focus { outline: 2px solid var(--accent); border-color: transparent; }
/* Круглая «↑» 44×44: цель касания вместо широкой кнопки «Спросить 🔍»,
   которая отъедала четверть ширины строки. Подпись — в aria-label. */
.kb-send { flex: 0 0 2.6rem; width: 2.6rem; height: 2.6rem; border: none;
  border-radius: 50%; background: var(--accent); color: var(--on-color);
  font-size: 1.15rem; line-height: 1; cursor: pointer; }
.kb-send:hover { background: var(--accent-deep); }
.kb-send:disabled { opacity: .45; }

/* Пустая лента — бланк требования: примеры не «чипсы», а вписанные от руки
   строки заказа. Форма честная — тап по строке действительно подаёт запрос
   в книгохранилище. */
#welcome { margin: .6rem 0 1rem; padding: .7rem .9rem 1rem; text-align: left;
  background: var(--paper-cream); border: 1px solid var(--line-pill);
  border-radius: 4px; }
.blank-h { margin: 0 0 .2rem; font-family: var(--mono); font-size: .66rem;
  letter-spacing: .2em; text-transform: uppercase; color: var(--muted); }
.kb-chip { display: block; width: 100%; text-align: left; cursor: pointer;
  margin: 0; padding: .55rem .2rem .3rem; background: transparent;
  border: none; border-bottom: 2px dotted var(--line-dash); border-radius: 0;
  font-family: var(--serif); font-style: italic; font-size: .97rem;
  line-height: 1.4; color: var(--ink-pill); }
.kb-chip:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* лента учитывает, что поле ввода фиксировано */
@media (min-width: 901px) {
  main { padding-bottom: 10rem; }
}

/* ------------------------------------------------------------ телефон */

@media (max-width: 900px) {
  /* 16 px полей — ровно столько, сколько нужно, чтобы строка не липла к краю:
     на 360-пиксельном экране каждый пиксель ширины — это слово в строке. */
  main { padding: .8rem 16px 9rem; }
  .kb-head .t { font-size: 1.3rem; }
  /* Лист ответа теряет рамку и поля: читаем страницу, а не карточку в чате.
     На десктопе (ширина есть) карточка остаётся листом с тенью. */
  .kb-card { background: transparent; border: none; border-radius: 0;
    box-shadow: none; padding: .3rem 0 .2rem; margin-top: .2rem; }
  .kb-card p, .kb-card li { font-size: 1.06rem; }
}

/* --------------------------------------------- режим готовки (/cook) */
/* Пульт у плиты: один шаг крупно, таймер, кнопка в пол-ладони. Экран всегда
   тёмный (шаблон ставит data-theme="dark"), поэтому цвета берутся из тех же
   токенов — и семантика шагов совпадает с цветом рельса «Плана готовки».
   Кнопки входа во вкладке плана нет с 26.07.2026 — экран открывается прямой
   ссылкой, поэтому класса `.ck-go` здесь больше нет. */

.ck-body { display: block; min-height: 100vh; padding: 0 0 8.5rem;
  background: var(--paper); }
.ck-top { display: flex; align-items: center; justify-content: space-between;
  gap: .8rem; padding: .8rem 1rem .4rem; color: var(--muted);
  font-family: var(--sans); font-size: .82rem; }
.ck-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ck-x { flex: 0 0 2.4rem; height: 2.4rem; border: none; background: transparent;
  color: var(--muted); font-size: 1.15rem; cursor: pointer; }
.ck-empty { padding: 2rem 1rem; color: var(--muted); font-family: var(--sans); }

/* полоса шагов: цвета те же, что у .tl-rail — узнаваемость между вкладкой и режимом */
.ck-prog { display: flex; gap: 3px; margin-bottom: 1.1rem; }
.ck-prog i { flex: 1; height: 5px; border-radius: 2px; background: var(--paper-lane); }
.ck-prog i.done { opacity: .45; }
.ck-prog i.ck-passive { background: var(--passive); }
.ck-prog i.ck-attended { background: var(--attend); }
.ck-prog i.ck-active { background: var(--hand); }

.ck-ahead { margin: 0 0 1rem; padding: .5rem .8rem; border-radius: 10px;
  border-left: 3px solid var(--attend); background: var(--paper-inset);
  color: var(--text-soft); font-family: var(--sans); font-size: .82rem; }
.ck-main { padding: 1.4rem 1rem 0; }
.ck-eyebrow { margin: 0; font-family: var(--sans); font-size: .72rem;
  letter-spacing: .2em; text-transform: uppercase; color: var(--attend); }
.ck-title { margin: .35rem 0 .2rem; font-family: var(--sans); font-size: 1.55rem;
  line-height: 1.2; font-weight: 700; color: var(--text); }
.ck-sub { margin: 0; font-family: var(--sans); font-size: .9rem; color: var(--muted); }
/* Фраза книги дословно — тот же жест, что `.tl-src` во вкладке плана. Длинный
   абзац прокручивается внутри себя: таймер не должен уезжать за экран из-за
   того, что книга в этом месте многословна. */
.ck-src { margin: .5rem 0 0; max-height: 8rem; overflow-y: auto;
  font-family: var(--serif); font-size: .9rem; line-height: 1.5;
  color: var(--text-soft); }

.ck-timer { margin: 2rem 0 0; text-align: center; }
.ck-clock { display: block; font-family: var(--sans); font-size: 2.9rem;
  font-weight: 700; font-variant-numeric: tabular-nums; color: var(--passive); }
.ck-clock.over { color: var(--attend); }
.ck-clock-l { display: block; margin-top: .2rem; font-family: var(--sans);
  font-size: .8rem; color: var(--muted); }
.ck-mean { margin: 1.4rem 0 0; padding: .6rem .8rem; border-radius: 10px;
  border: 1px dashed var(--line-dash); color: var(--text-soft);
  font-family: var(--sans); font-size: .85rem; }
.ck-mean b { color: var(--attend); }

.ck-act { position: fixed; left: 0; right: 0; bottom: 0; padding: 0 1rem 1rem;
  background: linear-gradient(to top, var(--paper) 70%, transparent); }
.ck-next { width: 100%; min-height: 3.4rem; border: none; border-radius: 14px;
  background: var(--accent); color: var(--on-color); font-family: var(--sans);
  font-size: 1.1rem; font-weight: 600; cursor: pointer; }
.ck-sec { display: flex; align-items: center; justify-content: space-between;
  margin-top: .6rem; font-family: var(--sans); font-size: .8rem; color: var(--muted); }
.ck-back { border: none; background: transparent; color: var(--muted);
  font-family: var(--sans); font-size: .85rem; padding: .5rem .2rem; cursor: pointer; }
.ck-back:disabled { opacity: .35; }
.ck-lock::before { content: "🔆 "; }

@media (min-width: 901px) {
  .ck-top, .ck-main { max-width: 34rem; margin-left: auto; margin-right: auto; }
  .ck-act { left: 50%; transform: translateX(-50%); width: min(94vw, 34rem); }
}

/* Слой иллюстраций: кнопка «📷 N стр.» в линейке хвоста. Свёрнут намеренно —
   плотность ленты не должна меняться от того, что к ответу нашлись кадры;
   фото раскрывает тот, кому они нужны. */
.kb-photos { font-family: var(--sans); font-size: .78rem; }
.kb-photos[open] { flex: 1 1 100%; }   /* раскрытая полоса — своей строкой */
.kb-photos summary { display: inline-flex; align-items: center;
  min-height: 2.35rem; padding: 0 .85rem; border: 1px solid var(--line-pill);
  border-radius: 1.2rem; background: var(--paper-cream); color: var(--ink-dash);
  font-size: .82rem; cursor: pointer; list-style: none; }
.kb-photos summary::-webkit-details-marker { display: none; }
.kb-photos summary:hover { border-color: var(--accent); color: var(--accent); }
.kb-photo-row { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .45rem; }
.kb-photo { display: block; text-decoration: none; color: var(--muted);
            text-align: center; }
.kb-photo img { display: block; max-height: 132px; width: auto; border-radius: 3px;
                border: 1px solid var(--hairline); background: var(--paper-raised); }
.kb-photo span { display: block; margin-top: .18rem; font-size: .7rem; }

/* Снимок во весь экран. Выше шторок (z 500) — иначе он открывался бы под
   ними. Кадр показывается целиком (contain): страница книги читается только
   целиком, обрезка по ширине превратила бы её в кусок текста. */
.kb-lightbox { position: fixed; inset: 0; z-index: 900; display: flex;
  align-items: center; justify-content: center; padding: .8rem;
  background: rgba(0, 0, 0, .92); }
.kb-lightbox[hidden] { display: none; }   /* иначе flex перебивает hidden */
.kb-lightbox img { max-width: 100%; max-height: 100%; object-fit: contain;
  border-radius: 4px; }
.kb-lb-close { position: absolute; right: .7rem;
  top: calc(.7rem + env(safe-area-inset-top, 0px));
  width: 2.8rem; height: 2.8rem; border: none; border-radius: 50%;
  background: rgba(255, 255, 255, .18); color: #fff; font-size: 1.25rem;
  line-height: 1; cursor: pointer; }
/* Подпись и стрелки — одна полоса под кадром. Сама полоса кликов не ловит
   (тап мимо кнопок закрывает снимок, как и раньше), а кнопки — ловят. */
.kb-lb-bar { position: absolute; left: 0; right: 0;
  bottom: calc(.7rem + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; justify-content: center; gap: .75rem;
  pointer-events: none; }
.kb-lb-cap { font-family: var(--sans); font-size: .78rem;
  color: rgba(255, 255, 255, .78); text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
  min-width: 9rem; text-align: center; }
.kb-lb-nav { pointer-events: auto; width: 2.8rem; height: 2.8rem;
  border: none; border-radius: 50%; background: rgba(255, 255, 255, .18);
  color: #fff; font-size: 1.4rem; line-height: 1; cursor: pointer; }
.kb-lb-nav[hidden] { display: none; }
.kb-lb-nav:disabled { opacity: .28; cursor: default; }
body.lb-open { overflow: hidden; }   /* лента не прокручивается под снимком */

/* --------------------------------------------------- вход и регистрация

   Отдельный каркас: у этих страниц нет ни ленты, ни шторок, ни липкой
   навигации, и общий `main` с его нижним отступом под поле ввода (9rem)
   оставил бы форму висеть в верхней трети экрана. Ширина заметно уже ленты —
   форма из четырёх полей на 46rem читается как таблица, а не как форма.

   Вид — читательский формуляр: машинописная шапка отдела, поля-строки бланка
   (подпись машинописью, ответ от руки серифом) и кнопка-штамп. Это продолжение
   «печатного листа» ленты, а не отдельный экран логина: человек попадает в
   фонд, и первая же страница говорит об этом тем же языком, что и ответы. */
/* `safe center` обязателен, а не украшение: у формы записи пять полей, и на
   телефоне она выше экрана. Обычный `center` в переполнении уводит НАЧАЛО
   формы выше верхней границы — шапка оказывается срезана, и прокрутка туда
   не достаёт. `safe` в этом случае прижимает к началу. Строка ниже — запасная
   для браузеров без `safe`: там центрирования не будет, но и обрезки тоже. */
.gate-body { align-items: flex-start; align-items: safe center; }
.gate { max-width: 24rem; width: 100%; padding: 2rem 1rem 3rem; }
/* Машинопись — как везде в системе: шифр источника, штамп, шапка бланка. */
.gate-top { margin: 0 0 .35rem; font-family: var(--mono); font-size: .68rem;
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted-soft); }
.gate-card { position: relative; display: flex; flex-direction: column;
  margin-top: 1.5rem; padding: 1.3rem 1.2rem 1.4rem;
  border: 1px solid var(--line-card); border-radius: 3px;
  background: var(--paper-raised); box-shadow: var(--shadow-card); }
/* Штемпель — единственное украшение страницы, и оно же объясняет порядок: за
   дверью фонд, а не сервис с открытой регистрацией. Краска ТИХАЯ: токен
   `--stamp` в системе значит «цитаты сверены дословно», и занимать смысловой
   цвет декорацией нельзя. */
.gate-stamp { position: absolute; top: .9rem; right: .9rem;
  transform: rotate(-8deg); border: 2px solid var(--muted-soft);
  border-radius: 4px; padding: .12rem .4rem; opacity: .7;
  font-family: var(--mono); font-size: .58rem; line-height: 1.3;
  letter-spacing: .14em; text-transform: uppercase; text-align: center;
  color: var(--muted-soft); }
/* Заголовок стоит один: порядок («только по билету», «только по коду»)
   говорит штемпель, и повторять его подзаголовком значит объяснять дважды.
   Правое поле — под штемпель: без него длинный заголовок («Запись читателя»)
   уходит под оттиск, и обе надписи становятся нечитаемы. */
.gate-h { margin: 0 0 1.3rem; padding-right: 5rem; font-family: var(--serif);
  font-size: 1.45rem; font-weight: 600; }
.gate-f { display: flex; flex-direction: column; margin-bottom: 1.2rem; }
.gate-l { font-family: var(--mono); font-size: .7rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted); }
/* Строка бланка, на которой сейчас пишут, подсвечивается целиком: на
   подчёркнутом поле одна смена цвета линии слишком тиха. */
.gate-f:focus-within .gate-l { color: var(--accent); }
/* «— по желанию» у необязательного поля: тише самой подписи, но в той же
   машинописи — это часть строки бланка, а не примечание под ней. */
.gate-opt { letter-spacing: .08em; color: var(--muted-soft); }
.gate-i { width: 100%; min-height: 2.9rem; padding: .5rem .1rem .35rem;
  border: none; border-bottom: 1px solid var(--line-firm); border-radius: 0;
  background: transparent; color: var(--text);
  font-family: var(--serif); font-size: 1.1rem; }
.gate-i:focus { outline: none; border-bottom-width: 2px;
  border-bottom-color: var(--accent); padding-bottom: calc(.35rem - 1px); }
/* Автозаполнение браузер красит поле СВОИМ фоном — на строке бланка без
   заливки это читается как вставленная чужая плашка. Возвращаем бумагу. */
.gate-i:-webkit-autofill { -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 3rem var(--paper-raised) inset;
  caret-color: var(--text); }
.gate-go { min-height: 3.1rem; margin-top: .3rem; border: none;
  border-radius: 2px; background: var(--accent); color: var(--on-color);
  font-family: var(--sans); font-size: .92rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; cursor: pointer; }
.gate-go:hover { background: var(--accent-deep); }
/* Ошибка входа — плашкой того же вида, что и сбой сервиса: человек уже знает
   этот цвет как «сообщение системы», а не как часть книги. */
.gate-err { margin: 0 0 1rem; padding: .55rem .7rem; border-radius: 2px;
  border-left: 3px solid var(--line-warn); background: var(--paper-warn);
  font-family: var(--sans); font-size: .85rem; color: var(--text-soft); }
.gate-hint { margin: .35rem 0 0; font-family: var(--sans);
  font-size: .75rem; color: var(--muted); }
.gate-note { margin: 1.4rem 0 0; font-family: var(--mono); font-size: .72rem;
  line-height: 1.6; color: var(--muted-soft); }
.gate-a { color: var(--accent); }

/* Кто вошёл — СРАЗУ ЗА названием, а не у правого края: имя читают вместе с
   названием («это моя полка»), а не ищут в противоположном углу. Свободное
   место забирает кнопка темы (`margin-left: auto` ниже) — иначе два элемента
   с `auto` поделили бы его пополам и увели имя в середину строки. */
.kb-who { display: flex; align-items: center; gap: .2rem; }
.kb-who ~ .kb-theme { margin-left: auto; }
.kb-who-n { font-family: var(--sans); font-size: .8rem; color: var(--muted);
  max-width: 9rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
/* Выход — значок двери с уходящей стрелкой, без подписи: слово «Выйти»
   занимало место рядом с именем, хотя жмут его раз в месяц. Размер кнопки
   держится тапом (2.4rem ≈ 41 px), а не размером рисунка; имя для скринридера
   и подсказка живут в разметке (`aria-label`, `title`). */
.kb-out { display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; padding: 0; border: none; border-radius: 50%;
  background: transparent; color: var(--muted); cursor: pointer; }
.kb-out:hover { color: var(--accent); background: var(--paper-quiet); }
.kb-out:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ------------------------------------------------------- приёмка рецептов

   Свой каркас, как у входа и режима готовки: у экрана приёмки нет ни ленты, ни
   шторок, ни поля ввода, зато нужна ШИРОКАЯ колонка — три панели (снимки
   страниц, оцифрованный текст, план) читаются только рядом, иначе сверять
   нечего. На узком экране панели складываются в столбец: приёмка с телефона —
   не основной случай, но и запрещать его нечем. */
   Экран сделан как ЛИСТ ПРИЁМКИ ТИРАЖА, и это не метафора ради красоты: работа
   здесь ровно корректорская — сверить оттиск с набором и поставить печать.
   Отсюда три решения, которых не было в первой версии (она читалась как
   отладочная таблица). Первое: реестр идёт РАЗДЕЛАМИ КНИГИ, номера полос стоят
   на полях слева, названия набраны книжным шрифтом — глаз ведёт по названиям,
   а не по служебным колонкам. Второе: над реестром КАРТА ПРИЁМКИ — по клетке на
   рецепт: сколько пройдено и где остались непроверенные места, видно одним
   взглядом, чего список из шестидесяти строк не показывает никогда. Третье:
   вердикт — ОТТИСК ШТЕМПЕЛЯ (краска `--stamp` в проекте уже заведена под
   «сверено дословно»), а не строка статуса. */
/* display: block ОБЯЗАТЕЛЕН. Глобальный `body` — флекс-строка (главная держит
   так ленту и шторки), и без переопределения шапка с содержимым вставали
   колонками рядом: на телефоне экран делился пополам, левая половина пустовала.
   Каркас приёмки простой — шапка сверху, лист под ней. */
.rv-body { display: block; margin: 0; background: var(--paper);
  color: var(--text); }
.rv-top { display: flex; align-items: baseline; gap: .7rem;
  padding: .5rem 1.2rem; border-bottom: 1px solid var(--line);
  background: var(--paper-raised); }
.rv-home { flex: 0 0 auto; font-family: var(--sans); font-size: .82rem;
  color: var(--accent); text-decoration: none; white-space: nowrap; }
.rv-home:hover { text-decoration: underline; }
.rv-title { font-family: var(--sans); font-size: .7rem; color: var(--muted-soft);
  text-transform: uppercase; letter-spacing: .12em; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.rv-main { max-width: 84rem; margin: 0 auto; padding: 1.4rem 1.2rem 4rem; }
.rv-empty, .rv-none { font-family: var(--sans); font-size: .85rem;
  color: var(--muted); }
.rv-none code { font-family: var(--mono); font-size: .78rem; }

/* Книги — вкладками: приёмка идёт книга за книгой. */
.rv-tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1.4rem; }
.rv-tab { padding: .28rem .75rem; border: 1px solid var(--line-pill);
  border-radius: 999px; background: var(--paper-cream);
  font-family: var(--sans); font-size: .8rem; color: var(--ink-pill);
  text-decoration: none; }
.rv-tab:hover { border-color: var(--line-firm); color: var(--accent); }
.rv-tab.on { background: var(--paper-pick); border-color: var(--accent);
  color: var(--accent-deep); }

/* Шапка книги: титул, как на авантитуле, и счёт приёмки под ним. */
.rv-book { max-width: 46rem; margin: 0 0 1.6rem; }
.rv-eyebrow { margin: 0; font-family: var(--sans); font-size: .68rem;
  text-transform: uppercase; letter-spacing: .16em; color: var(--muted-soft); }
.rv-book h1 { margin: .35rem 0 .2rem; font-family: var(--serif);
  font-weight: 600; font-size: 1.85rem; line-height: 1.2;
  color: var(--text-book); }
.rv-author { margin: 0; font-family: var(--sans); font-size: .82rem;
  color: var(--muted); }
.rv-stat { display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 1rem 0 .8rem; }
.rv-num { display: flex; align-items: baseline; gap: .35rem;
  font-family: var(--sans); font-size: .78rem; color: var(--muted); }
.rv-num b { font-family: var(--serif); font-size: 1.5rem; font-weight: 600;
  line-height: 1; color: var(--text-soft); }
.rv-num.rv-ok b { color: var(--trust); }
.rv-num.rv-bad b { color: var(--hand); }

/* Карта приёмки: клетка на рецепт, в порядке книги. */
.rv-map { display: flex; flex-wrap: wrap; gap: 3px; }
.rv-cell { width: .85rem; height: .85rem; border-radius: 2px;
  background: var(--paper-inset); border: 1px solid var(--line-pill); }
.rv-cell:hover { outline: 2px solid var(--line-firm); outline-offset: 1px; }
.rv-cell.rv-ok { background: var(--trust); border-color: var(--trust); }
.rv-cell.rv-bad { background: var(--hand); border-color: var(--hand); }
.rv-cell.rv-stale-mark { background: var(--paper-warn);
  border-color: var(--trust-warn); }

/* Реестр: раздел книги — заголовок, рецепт — строка с полем для номера полос. */
.rv-list { display: flex; flex-direction: column; gap: 1.6rem; }
.rv-sec h2 { display: flex; align-items: baseline; gap: .6rem;
  margin: 0 0 .1rem; padding-bottom: .3rem;
  border-bottom: 1px solid var(--line); font-family: var(--sans);
  font-size: .74rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .1em; color: var(--muted); }
.rv-count { margin-left: auto; font-family: var(--mono); font-size: .72rem;
  color: var(--muted-soft); letter-spacing: 0; }
.rv-row { display: grid; grid-template-columns: 5.5rem 1fr auto 9rem;
  gap: .9rem; align-items: baseline; padding: .5rem .4rem;
  border-bottom: 1px solid var(--line-soft); text-decoration: none;
  color: var(--text); }
.rv-row:last-child { border-bottom: none; }
.rv-row:hover { background: var(--paper-quiet); }
.rv-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rv-pages { font-family: var(--mono); font-size: .74rem; color: var(--muted-soft);
  text-align: right; }
.rv-name { font-family: var(--serif); font-size: 1.02rem; line-height: 1.35;
  color: var(--text-book); }
.rv-note { display: block; font-family: var(--sans); font-size: .74rem;
  color: var(--muted); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.rv-has-plan { font-size: .8rem; color: var(--passive); }
/* Лента есть, но порога показа не проходит: читателю её не видно, и значок
   обязан отличаться от значка показанного плана — иначе приёмка говорит о
   рецепте не то, что видит читатель. */
.rv-weak-plan { opacity: .45; }
.rv-no-plan { display: inline-block; width: .8rem; }
.rv-state { font-family: var(--sans); font-size: .74rem; color: var(--muted-soft);
  text-align: right; }
.rv-state.rv-ok { color: var(--trust); }
.rv-state.rv-bad { color: var(--hand); }
.rv-state.rv-stale-mark { color: var(--trust-warn); }

/* Карточка приёмки */
.rv-head { max-width: 46rem; margin-bottom: 1.1rem; }
.rv-head h1 { margin: .3rem 0 .25rem; font-family: var(--serif);
  font-weight: 600; font-size: 1.6rem; line-height: 1.2;
  color: var(--text-book); }
.rv-back, .rv-next { font-family: var(--sans); font-size: .8rem;
  color: var(--accent); text-decoration: none; }
.rv-back:hover, .rv-next:hover { text-decoration: underline; }
.rv-sub { margin: 0; font-family: var(--sans); font-size: .8rem;
  color: var(--muted); }
.rv-pg { display: inline-block; margin-right: .6rem; padding: .05rem .4rem;
  border: 1px solid var(--line-pill); border-radius: 3px;
  background: var(--paper-cream); font-family: var(--mono); font-size: .72rem;
  color: var(--text-soft); }
.rv-next { display: inline-block; margin-top: .6rem; }

.rv-verdict { margin: 0 0 1.4rem; }
.rv-form { position: relative; max-width: 46rem; padding: .9rem 1rem;
  border: 1px solid var(--line-card); border-radius: 6px;
  background: var(--paper-cream); box-shadow: var(--shadow-card); }
.rv-form textarea { width: 100%; box-sizing: border-box; padding: .5rem .6rem;
  border: 1px solid var(--line-pill); border-radius: 4px;
  background: var(--paper-raised); font-family: var(--sans);
  font-size: .85rem; color: var(--text); resize: vertical; }
.rv-form textarea:focus-visible { outline: 2px solid var(--accent);
  outline-offset: -1px; }
.rv-acts { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
.rv-btn { padding: .42rem .95rem; border: 1px solid var(--line-pill);
  border-radius: 999px; background: var(--paper-raised);
  font-family: var(--sans); font-size: .85rem; color: var(--ink-pill);
  cursor: pointer; }
.rv-btn:hover { border-color: var(--line-firm); color: var(--accent); }
.rv-btn-ok.on { background: var(--trust); border-color: var(--trust);
  color: var(--on-color); }
.rv-btn-bad.on { background: var(--hand); border-color: var(--hand);
  color: var(--on-color); }
.rv-btn-off { color: var(--muted-soft); }

/* Оттиск приёмки. Наклон и разреженная прописная — от руки поставленный
   штемпель, а не элемент интерфейса: печать видна раньше, чем прочитан текст. */
.rv-stamp { position: absolute; right: 1rem; top: -.5rem;
  display: flex; align-items: baseline; gap: .5rem;
  padding: .3rem .7rem; border: 2px solid var(--stamp); border-radius: 3px;
  background: var(--paper-raised); color: var(--stamp);
  font-family: var(--sans); transform: rotate(-2deg); }
.rv-stamp .t { font-size: .82rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .12em; }
.rv-stamp .d, .rv-stamp .w { font-family: var(--mono); font-size: .68rem;
  opacity: .8; }
.rv-stamp-bad { border-color: var(--hand); color: var(--hand); }
.rv-stamp-stale { border-style: dashed; opacity: .55; }
.rv-stamp .s { font-size: .68rem; }

.rv-stale, .rv-conf { margin: 0 0 .5rem; font-family: var(--sans);
  font-size: .78rem; color: var(--muted); }
/* Устаревший вердикт — предупреждением, а не тихой подписью: одобрение по
   прежней редакции текста легко принять за проверку нынешнего. */
.rv-stale { padding: .4rem .6rem; border-left: 3px solid var(--trust-warn);
  background: var(--paper-warn); color: var(--text-soft); }

/* Три панели. Средняя шире: оцифрованный текст читают целиком, а снимок и
   ленту — просматривают. */
.rv-panes { display: grid; grid-template-columns: 15rem minmax(0, 1.5fr) minmax(0, 1fr);
  gap: 1.2rem; align-items: start; }
.rv-pane { min-width: 0; padding: .9rem 1rem 1rem;
  border: 1px solid var(--line-card); border-radius: 6px;
  background: var(--paper-raised); }
.rv-pane h2 { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  margin: 0 0 .7rem; padding-bottom: .4rem;
  border-bottom: 1px solid var(--line-soft); font-family: var(--sans);
  font-size: .74rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .1em; color: var(--muted); }
.rv-hint { font-size: .68rem; font-weight: 400; text-transform: none;
  letter-spacing: 0; color: var(--muted-soft); }
.rv-pane .kb-rec { max-height: 62rem; overflow: auto; }
.rv-pane .kb-rec p { font-family: var(--serif); font-size: 1rem;
  line-height: 1.62; color: var(--text-book); }

/* Полосы книги — колонкой: рецепт идёт подряд, и листать их сверху вниз
   естественнее, чем собирать взглядом плитку. */
.rv-shots { display: flex; flex-direction: column; gap: .6rem;
  max-height: 62rem; overflow: auto; }
.rv-shot { display: block; text-decoration: none; color: var(--muted-soft);
  font-family: var(--mono); font-size: .7rem; }
.rv-shot img { display: block; width: 100%; height: auto; border-radius: 3px;
  border: 1px solid var(--line-soft); box-shadow: var(--shadow-card); }
.rv-shot span { display: block; margin-top: .2rem; }
.rv-shot:hover img { border-color: var(--line-firm); }

@media (max-width: 66rem) {
  .rv-panes { grid-template-columns: 1fr; }
  .rv-shots { flex-direction: row; flex-wrap: wrap; max-height: none; }
  .rv-shot { width: 8.5rem; }
  .rv-pane .kb-rec { max-height: none; }
}
/* ---------------------------------------------------------------- телефон

   Приёмку ведут и с телефона: книга в руках, экран рядом. Поэтому здесь не
   «сжатая версия десктопа», а другая раскладка строки: состояние переезжает
   ПОД название (в узкой колонке правый столбец съедал бы половину ширины),
   номер полос садится на одну строку с состоянием, а карта приёмки мельчает,
   чтобы книга помещалась в пять-шесть рядов и оставалась картой. */
@media (max-width: 44rem) {
  .rv-main { padding: .9rem .8rem 3rem; }
  .rv-tabs { gap: .3rem; margin-bottom: 1rem; }
  .rv-tab { padding: .24rem .6rem; font-size: .78rem; }
  .rv-book { margin-bottom: 1.2rem; }
  .rv-book h1 { font-size: 1.35rem; }
  .rv-stat { gap: 1.1rem; margin: .8rem 0 .7rem; }
  .rv-num b { font-size: 1.25rem; }
  .rv-cell { width: .7rem; height: .7rem; }
  .rv-map { gap: 2px; }

  .rv-list { gap: 1.2rem; }
  .rv-sec h2 { font-size: .7rem; }
  .rv-row { grid-template-columns: 1fr auto; gap: .15rem .5rem;
    padding: .55rem .1rem; }
  .rv-name { grid-column: 1; grid-row: 1; font-size: .98rem; }
  .rv-has-plan, .rv-no-plan { grid-column: 2; grid-row: 1; }
  .rv-pages { grid-column: 1; grid-row: 2; text-align: left; }
  .rv-state { grid-column: 2; grid-row: 2; font-size: .72rem; }

  .rv-head h1 { font-size: 1.3rem; }
  .rv-form { padding: .8rem; }
  .rv-acts { gap: .4rem; }
  .rv-btn { flex: 1 1 auto; padding: .5rem .6rem; text-align: center; }
  .rv-stamp { position: static; display: inline-flex; margin-bottom: .6rem;
    transform: none; }
  .rv-shot { width: 100%; }
  .rv-shots { flex-direction: column; }
}

/* -------------------------------------------------- правки из приёмки (rvx-)

   Экран собирает правки — применяет конвейер (REVIEW-EDIT-PROPOSAL.md).
   Весь след неприменённой правки — СИНИЕ ЧЕРНИЛА КОРРЕКТОРА (`--edit`):
   зелёный занят «сверено», бордовый — «на правку», третий слой смысла
   получает третий цвет. */

.rvx-edit-btn { margin-left: auto; padding: .1rem .6rem;
  border: 1px dashed var(--line-firm); border-radius: 999px;
  font-size: .68rem; font-weight: 400; letter-spacing: 0; text-transform: none;
  color: var(--text-soft); text-decoration: none; white-space: nowrap; }
.rvx-edit-btn:hover { border-style: solid; border-color: var(--edit);
  color: var(--edit); }

.rvx-badge { display: inline-flex; align-items: center; gap: .3rem;
  padding: .06rem .55rem; border: 1px solid var(--edit); border-radius: 999px;
  background: var(--edit-wash); color: var(--edit);
  font-family: var(--sans); font-size: .7rem; white-space: nowrap; }
.rvx-badge::before { content: "✎"; }
.rvx-badge-ok { border-color: var(--trust); color: var(--trust);
  background: var(--paper-pick); }
.rvx-badge-bad { border-color: var(--hand); color: var(--hand);
  background: var(--paper-warn); }

.rvx-strip { display: flex; align-items: baseline; flex-wrap: wrap;
  gap: .3rem .7rem; margin: 0 0 .6rem; font-family: var(--sans);
  font-size: .72rem; }
.rvx-note { color: var(--muted-soft); }
.rvx-switch { color: var(--edit); }
.rvx-inline { display: inline; margin-left: auto; }
.rvx-drop { border: none; background: none; padding: 0; cursor: pointer;
  font-family: var(--sans); font-size: .72rem; color: var(--muted-soft);
  text-decoration: underline; }
.rvx-drop:hover { color: var(--hand); }

.rvx-chip { display: inline-block; margin: .2rem 0 .6rem; padding: .2rem .7rem;
  border: 1px solid var(--edit); border-radius: 999px;
  background: var(--edit-wash); color: var(--edit); text-decoration: none;
  font-family: var(--sans); font-size: .76rem; }
.rvx-chip:hover { text-decoration: underline; }

/* Задание агенту: «вижу, что криво» свободным текстом. */
.rvx-task, .rvx-task-form { max-width: 46rem; margin: -.6rem 0 1.2rem;
  font-family: var(--sans); font-size: .8rem; }
.rvx-task { display: flex; align-items: baseline; flex-wrap: wrap;
  gap: .3rem .7rem; padding: .5rem .8rem;
  border: 1px solid var(--line-card); border-radius: 6px;
  background: var(--paper-cream); }
.rvx-task-text { color: var(--text-soft); }
.rvx-task-form summary { cursor: pointer; color: var(--muted);
  font-size: .76rem; }
.rvx-task-form summary:hover { color: var(--edit); }
.rvx-task-form form { display: flex; flex-direction: column; gap: .4rem;
  margin-top: .4rem; }
.rvx-task-form textarea { padding: .5rem .6rem;
  border: 1px solid var(--line-pill); border-radius: 4px;
  background: var(--paper-raised); font-family: var(--sans); font-size: .82rem;
  color: var(--text); resize: vertical; }
.rvx-send { align-self: flex-start; padding: .42rem .95rem;
  border: 1px solid var(--accent); border-radius: 999px;
  background: var(--accent); color: var(--on-color);
  font-family: var(--sans); font-size: .85rem; font-weight: 600;
  cursor: pointer; }
.rvx-send:hover { background: var(--accent-deep);
  border-color: var(--accent-deep); }
.rvx-cancel { align-self: center; font-family: var(--sans); font-size: .8rem;
  color: var(--muted); }

/* Страница правки текста: источник слева, редактор справа. Редактор —
   моноширинный сырой markdown: правится то, что читает система, и маркеры
   с таблицами видны как есть; книжный сериф остаётся в панели чтения. */
.rvx-cols { display: grid; grid-template-columns: 17rem minmax(0, 1fr);
  gap: 1.2rem; align-items: start; }
.rvx-rules { margin: 0 0 .7rem; padding: .45rem .7rem;
  border: 1px solid var(--line-warn); border-radius: 6px;
  background: var(--paper-warn); font-family: var(--sans); font-size: .74rem;
  color: var(--text-soft); }
.rvx-rules b { color: var(--trust-warn); }
.rvx-form { display: flex; flex-direction: column; gap: .5rem; }
.rvx-md { width: 100%; box-sizing: border-box; padding: .7rem .8rem;
  border: 1px solid var(--line-firm); border-radius: 6px;
  background: var(--paper-raised); color: var(--text-book);
  font-family: var(--mono); font-size: .8rem; line-height: 1.55;
  resize: vertical; }
.rvx-md:focus-visible { outline: 2px solid var(--edit); outline-offset: -1px; }
.rvx-note-in { padding: .4rem .6rem; border: 1px solid var(--line-pill);
  border-radius: 4px; background: var(--paper-raised);
  font-family: var(--sans); font-size: .8rem; color: var(--text); }
.rvx-acts { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.rvx-error { margin: 0 0 .6rem; padding: .45rem .7rem;
  border-left: 3px solid var(--hand); background: var(--paper-warn);
  font-family: var(--sans); font-size: .8rem; color: var(--text-soft); }
.rvx-warn { margin: 0 0 .4rem; padding: .35rem .7rem;
  border-left: 3px solid var(--attend); background: var(--paper-warn);
  font-family: var(--sans); font-size: .76rem; color: var(--text-soft); }

/* Редактор плана: операции строками с полями, а не JSON. */
.rvx-ops { display: flex; flex-direction: column; gap: .5rem; }
.rvx-op { margin: 0; padding: .55rem .75rem; border: 1px solid var(--line-pill);
  border-radius: 7px; background: var(--paper-raised); }
.rvx-op-head { display: flex; align-items: center; gap: .5rem; }
.rvx-op-no { flex: 0 0 auto; width: 1.3rem; height: 1.3rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--paper-inset);
  font-family: var(--mono); font-size: .7rem; color: var(--muted); }
.rvx-op-verb { flex: 1 1 auto; min-width: 0; padding: .3rem .5rem;
  border: 1px solid var(--line-soft); border-radius: 4px;
  background: var(--paper-cream); font-family: var(--serif);
  font-size: .95rem; color: var(--text-book); }
.rvx-op-tools { display: flex; gap: .25rem; }
.rvx-ico { width: 1.6rem; height: 1.6rem; border: 1px solid var(--line-soft);
  border-radius: 5px; background: none; color: var(--muted);
  font-size: .75rem; line-height: 1; cursor: pointer; }
.rvx-ico:hover { border-color: var(--line-firm); color: var(--text); }
.rvx-op-fields { display: flex; flex-wrap: wrap; gap: .35rem .7rem;
  margin-top: .45rem; }
.rvx-op-fields label { display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--sans); font-size: .66rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted-soft); }
.rvx-op-fields input, .rvx-op-fields select { width: 6.5rem; padding: .2rem .4rem;
  border: 1px solid var(--line-soft); border-radius: 4px;
  background: var(--paper-cream); font-family: var(--sans); font-size: .78rem;
  color: var(--text); font-variant-numeric: tabular-nums; }
.rvx-op-text { width: 100%; box-sizing: border-box; margin-top: .4rem;
  padding: .3rem .5rem; border: 1px dashed var(--line-dash);
  border-radius: 4px; background: none; font-family: var(--serif);
  font-size: .82rem; color: var(--text-soft); }
.rvx-addop { padding: .45rem; border: 1px dashed var(--line-firm);
  border-radius: 7px; background: none; color: var(--muted);
  font-family: var(--sans); font-size: .8rem; cursor: pointer; }
.rvx-addop:hover { color: var(--edit); border-color: var(--edit); }
.rvx-plan-meta { display: flex; gap: 1rem; flex-wrap: wrap;
  align-items: flex-start; font-family: var(--sans); font-size: .72rem;
  color: var(--muted); }
.rvx-plan-meta select { padding: .2rem .4rem; border: 1px solid var(--line-soft);
  border-radius: 4px; background: var(--paper-cream); font-size: .78rem; }
.rvx-issues { flex: 1 1 16rem; display: flex; flex-direction: column;
  gap: .25rem; }
.rvx-issues textarea { padding: .3rem .5rem; border: 1px solid var(--line-soft);
  border-radius: 4px; background: var(--paper-cream);
  font-family: var(--sans); font-size: .78rem; resize: vertical; }
.rvx-preview-btn { padding: .42rem .95rem; border: 1px solid var(--line-firm);
  border-radius: 999px; background: var(--paper-raised);
  font-family: var(--sans); font-size: .85rem; color: var(--ink-pill);
  cursor: pointer; }
.rvx-preview-btn:hover { border-color: var(--edit); color: var(--edit); }
.rvx-preview-box { max-width: 46rem; margin-top: 1rem; }
.rvx-preview-cap { margin: 0 0 .5rem; font-family: var(--sans);
  font-size: .72rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .1em; color: var(--muted); }

/* Очередь правок. Статус не хранится — вычислен сравнением с корпусом. */
.rvx-stat { display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 1rem 0 .8rem; }
.rvx-num { display: flex; align-items: baseline; gap: .35rem;
  font-family: var(--sans); font-size: .8rem; color: var(--muted); }
.rvx-num b { font-family: var(--serif); font-size: 1.5rem; font-weight: 600; }
.rvx-num.rvx-st-q b { color: var(--edit); }
.rvx-num.rvx-st-a b { color: var(--trust); }
.rvx-num.rvx-st-c b { color: var(--hand); }
.rvx-rows { display: flex; flex-direction: column; }
.rvx-row { display: grid; grid-template-columns: 5.5rem 1fr auto;
  gap: .2rem .9rem; padding: .6rem .2rem; align-items: baseline;
  border-bottom: 1px solid var(--line-soft); }
.rvx-row:last-child { border-bottom: none; }
.rvx-name { min-width: 0; font-family: var(--serif); font-size: 1rem; }
.rvx-name a { color: var(--text-book); text-decoration: none; }
.rvx-name a:hover { color: var(--accent); text-decoration: underline; }
.rvx-layer { display: inline-block; margin-right: .5rem; padding: .04rem .4rem;
  border: 1px solid var(--line-pill); border-radius: 4px;
  font-family: var(--sans); font-size: .64rem; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted); vertical-align: .1rem; }
.rvx-meta { display: block; font-family: var(--sans); font-size: .72rem;
  color: var(--muted); }
.rvx-state { display: flex; align-items: baseline; gap: .7rem;
  font-family: var(--sans); font-size: .76rem; white-space: nowrap; }
.rvx-state.rvx-st-q { color: var(--edit); }
.rvx-state.rvx-st-a { color: var(--trust); }
.rvx-state.rvx-st-c { color: var(--hand); }
.rvx-diff { grid-column: 2 / 4; margin-top: .2rem; padding-left: .8rem;
  border-left: 2px solid var(--line-soft); font-family: var(--mono);
  font-size: .72rem; overflow-x: auto; }
.rvx-del { color: var(--hand); }
.rvx-add { color: var(--edit); }
.rvx-more { color: var(--muted-soft); font-family: var(--sans); }

@media (max-width: 66rem) {
  .rvx-cols { grid-template-columns: 1fr; }
}
@media (max-width: 44rem) {
  .rvx-row { grid-template-columns: 1fr auto; }
  .rvx-row .rv-pages { display: none; }
  .rvx-diff { grid-column: 1 / 3; }
  .rvx-op-fields input, .rvx-op-fields select { width: 5.2rem; }
}

