/* ============================================================
   tkan.css — оформление «Ткань» со скролл-сценой. 2026-09-18.
   Основа снята с dayos.com живьём, с 2026-09-25 это своя система:
   все значения — токенами из tokens.css, здесь чисел нет, кроме
   формул раскладки и значений компонентов (foundation.md §3, §16).

   Цвет фона, текста и линий задаёт скрипт: --bg, --fg, --mute, --ln
   переливаются по прокрутке. Значения по умолчанию — в tokens.css:
   страница обязана быть читаемой и без единого скрипта.
   ============================================================ */

/* --- Шрифты: самохостинг, ничего по ссылке ------------------- */
@font-face { font-family:"RCond"; font-style:normal; font-weight:900; font-display:swap;
  src:url("fonts/robotocond-900-cyrillic.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; }
@font-face { font-family:"RCond"; font-style:normal; font-weight:900; font-display:swap;
  src:url("fonts/robotocond-900-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Geist"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/geist-400-cyrillic.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; }
@font-face { font-family:"Geist"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/geist-400-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Geist"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/geist-500-cyrillic.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; }
@font-face { font-family:"Geist"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/geist-500-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"GeistMono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/geistmono-400-cyrillic.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116; }
@font-face { font-family:"GeistMono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/geistmono-400-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }

* { box-sizing: border-box; }

/* Полоса прокрутки убрана: она стояла чёрной рейкой справа и мешала.
   Прокрутка при этом работает, клавиатура тоже. */
html {
  background: var(--bg);
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar { width: 0; height: 0; display: none; }

body {
  margin: 0;
  font-family: var(--text);
  font-size: var(--fs-6);
  line-height: var(--lh-body);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Холст сцены прибит к окну, содержимое едет поверх. */
#scene { position: fixed; inset: 0; z-index: var(--z-scene); width: 100%; height: 100%; pointer-events: none; }
main { position: relative; z-index: var(--z-content); }

a { color: inherit; }
a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, textarea:focus-visible {
  outline: var(--st-accent) solid var(--yellow); outline-offset: var(--focus-offset);
}

/* --- Шапка ---------------------------------------------------- */
/* Шапка на широком экране больше не прячется (Ян 2026-09-25), поэтому
   раздел, к которому ведёт ссылка с якорем, встаёт ниже неё, а не под
   ней. Отступ тот же, что у якорей «Оплаты» (inner.css, .pay__choose).
   На телефоне хватает верхнего поля главы — проверено кадром work#raschet. */
@media (min-width: 900px) {
  [id] { scroll-margin-top: clamp(72px, 12vh, 140px); }
}

.head {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-head);
  /* Три колонки, а не flex со space-between: при разной ширине названия
     и кнопки меню съезжало от центра окна. Средняя колонка — auto,
     крайние — равные, поэтому меню стоит ровно посередине. */
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--sp-16);
  /* Сверху к отступу прибавляется безопасная зона: шапка прибита к
     верхней кромке окна, а на айфоне под ней проходит полоса статуса. */
  padding: calc(var(--head-pad) + var(--safe-t)) var(--side-r) var(--head-pad) var(--side-l);
  transition: transform var(--dur-move) var(--ease-standard);
}
.head > .logo { justify-self: start; }
.head > .nav { justify-self: center; }
.head > .pill, .head > .burger { justify-self: end; }
/* На узком экране колонок две: название слева, кнопка меню справа. */
@media (max-width: 899px) {
  .head { grid-template-columns: 1fr auto auto; }
  .head > .pill { justify-self: end; }
}
/* На телефоне кнопка остаётся в шапке — Ян 2026-09-22: кнопка с первого
   экрана снята («у нас же есть кнопка сверху, зачем ещё одна»), значит
   верхняя обязана быть видна на любой ширине. Место освобождает слово
   «Меню»: остаётся значок, имя кнопке даёт aria-label в parts.js.
   До 09-22 кнопка здесь пряталась: «Получить план» со словом «Меню»
   в 390px не помещались. */
@media (max-width: 560px) {
  .head { grid-template-columns: 1fr auto auto; gap: var(--sp-12); }
  .head > .pill { padding: var(--sp-10) var(--sp-16); font-size: var(--fs-4); }
  .burger__text { display: none; }
}
.head.is-hidden { transform: translateY(-140%); }
/* Подложка под шапкой. Прежняя гасла уже на 42% высоты — ровно там, где
   стоят буквы, поэтому заголовки просвечивали сквозь название и «Меню»
   (видно было на 768). Теперь она плотная на всю высоту шапки и мягко
   сходит на нет ниже её края.

   На самом верху страницы подложки нет: там под шапкой первый экран,
   и нити должны доходить до верхней кромки. Она появляется, как только
   страницу тронули. */
.head::before {
  content: ""; position: absolute; inset: 0 0 -40px; z-index: -1; pointer-events: none;
  background: linear-gradient(to bottom, var(--bg) 0, var(--bg) calc(100% - 40px), transparent);
  opacity: 0; transition: opacity var(--dur-base) linear;
}
.head.is-solid::before { opacity: 1; }
.logo {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-display); font-size: var(--fs-10); text-decoration: none;
  /* Палец попадает не по буквам, а по цели: на телефоне высота названия
     была 26px при норме 44. */
  display: inline-flex; align-items: center; min-height: var(--tap);
}
.logo span { background: var(--yellow); color: var(--on-accent); padding: 0 .18em; }
.nav {
  display: flex; gap: var(--sp-f7);
  background: var(--fill-subtle);
  border-radius: var(--r-pill); padding: var(--sp-f1) var(--sp-f5);
  font-size: var(--fs-3); font-weight: 500;
}
.nav a { text-decoration: none; }
.nav a:hover { opacity: var(--o-link-hover); }

/* --- Ссылка при наведении: жёлтая плашка, текст чёрный -------------
   Одно правило на ссылки в тексте, в реквизитах и в подвале. Жёлтым
   текстом ссылку не красим: на белом и сером он даёт около 1,3:1 —
   так было у реквизитов и подвала до аудита ДС 2026-09-25. Плашка —
   тот же язык «чёрное на жёлтом», что у цены и пометок. Кнопки и
   ступени пути ведут себя по-своему и сюда не входят. */
main a:not(.button):not(.route__stop):hover,
.site-foot a:hover {
  /* Плашка — полоса высотой в строку по центру: у ссылок подвала блок
     растянут до 44px ради пальца, и сплошная заливка давала высокий
     прямоугольник. Поле по бокам — padding и равный ему отрицательный
     margin: раскладка при наведении не сдвигается. */
  color: var(--on-accent);
  background: linear-gradient(var(--yellow), var(--yellow)) 0 50% / 100% 1.35em no-repeat;
  padding-inline: .2em; margin-inline: -.2em;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
  text-decoration-color: transparent;
}

/* --- Перейти к содержимому -----------------------------------------
   Первая остановка клавиатуры: без неё до текста страницы нужно пройти
   всю шапку. Видна только в фокусе с клавиатуры, создаёт parts.js
   (аудит ДС 2026-09-25). */
.skip {
  /* Встаёт ровно на место логотипа и той же высоты — закрывает его
     целиком, а не торчит внахлёст. */
  position: fixed; left: var(--side-l); top: calc(var(--head-pad) + var(--safe-t)); z-index: var(--z-skip);
  display: inline-flex; align-items: center; min-height: calc(var(--tap) + var(--sp-8));
  background: var(--yellow); color: var(--on-accent); text-decoration: none;
  font-family: var(--mono); font-size: var(--fs-3);
  padding: var(--sp-10) var(--sp-16); border-radius: var(--r-pill);
  transform: translateY(-200%);
}
.skip:focus-visible { transform: none; outline-color: var(--on-accent); }
main:focus { outline: none; }
/* Текущий раздел: полный контраст плюс жёлтая черта под словом.
   Одним жёлтым его метить нельзя — на светлой главе жёлтый по серому
   почти не виден, и метка пропадала ровно там, где чаще всего стоит
   человек. Видно стало 2026-09-21, когда в шапку добавился пункт
   «Главная»: на самой главной он и оказывался нечитаемым. */
.nav a[aria-current="page"] {
  color: var(--fg);
  box-shadow: inset 0 calc(-1 * var(--st-base)) 0 var(--yellow);
}

/* --- Нити проходят под текстом, а не сквозь буквы ---------------
   Холст сцены прибит к окну, текст едет поверх — любая строка рано
   или поздно проезжает через полосу нитей. Ореол цветом главы гасит
   нить только возле самих букв: между абзацами, по краям и за текстом
   поле видно, как было. Тот же приём, что подложка у графика и у
   сообщения формы. Цвет — токен --bg, ореол идёт за сменой фона.

   ⚠️ Сцену ради этого не трогаем. Ян 2026-09-24 принял ореол и отклонил
   правки сцены (жёлтый на главной, сведение нитей к кнопке на телефоне):
   «человек крутит… когда на одной прокрутке это перекрылось, страшного
   в этом ничего нету». Перекрытие в одном кадре прокрутки — не дефект. */
.ch { text-shadow: 0 0 1px var(--bg), 0 0 3px var(--bg), 0 0 6px var(--bg); }
/* У кнопок и плашек свой фон: ореол цветом главы лёг бы вокруг их букв
   грязным пятном. */
.ch :is(.pill, .button, .todo, .todo-note, .pack__price, .field__err, a:hover),
.ch .route__no::after { text-shadow: none; }

/* --- Кнопка-таблетка ------------------------------------------ */
.pill, .button {
  display: inline-block; border: 0; cursor: pointer;
  border-radius: var(--r-pill); padding: var(--sp-f2) var(--sp-f6);
  font-family: var(--text); font-size: var(--fs-5); font-weight: 500;
  text-decoration: none; white-space: nowrap;
  background: var(--action-bg); color: var(--action-fg);
  transition: background-color var(--dur-recolor) var(--ease-standard), color var(--dur-recolor) var(--ease-standard), opacity var(--dur-hover);
}
.pill:hover, .button:hover { opacity: var(--o-button-hover); }
/* Неактивна: форма «Вопросов» гасит кнопку на время отправки (form.js).
   До 2026-09-25 здесь рисовал браузер по умолчанию. */
.button:disabled { opacity: var(--o-dim); cursor: progress; }
/* Кнопка и подпись рядом стоят в обычном абзаце. Строчный поток обтекал
   кнопку: на телефоне хвост подписи уезжал под неё отдельной строкой.
   Флекс с переносом ставит подпись целиком рядом или целиком ниже. */
main p:has(> .button) {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-f3); max-width: var(--measure-wide);
}
main p:has(> .button) > .small { flex: 1 1 22ch; }
/* Кнопка у правого поля колонки: цель для нитей уезжает вправо, и путь
   до неё виден целиком. Только на широком экране — на узком колонка
   и так во всю ширину. */
@media (min-width: 900px) {
  main p.act-right:has(> .button) { justify-content: flex-end; }
}
/* Дорожка дошла: кнопка принимает точку в себя. Короткий импульс, без
   свечения — оно на нашем списке запрещённых приёмов. */
.button.is-arrived { transform: scale(1.045); }
/* Нажатие: кнопка на миг сжимается — отклик пальцу и мыши. Стоит после
   is-arrived, чтобы нажатие было видно и на кнопке, в которую пришла нить. */
.pill:active, .button:active { transform: scale(var(--press-scale)); transition: transform var(--dur-hover) var(--ease-standard); }
.button { transition: background-color var(--dur-recolor) var(--ease-standard), color var(--dur-recolor) var(--ease-standard), opacity var(--dur-hover), transform var(--dur-move) var(--ease-overshoot); }

/* --- Меню на узком экране --------------------------------------
   Строка ссылок в шапке не помещается уже на планшете, а страниц
   шесть. Кнопка открывает меню во весь экран: крупные имена
   разделов, ничего больше. */
.burger {
  display: none; align-items: center; gap: var(--sp-10); min-height: var(--tap);
  background: none; border: 0; padding: var(--sp-8) 0; margin: 0;
  color: var(--fg); font: inherit; font-weight: 500; cursor: pointer;
  font-size: var(--fs-5);
}
.burger__lines { display: block; width: 22px; height: 12px; position: relative; }
.burger__lines::before, .burger__lines::after {
  content: ""; position: absolute; left: 0; right: 0; height: 2px;
  background: var(--fg); transition: transform var(--dur-base) var(--ease-standard), top var(--dur-base);
}
.burger__lines::before { top: 0; }
.burger__lines::after  { top: 10px; }
.burger[aria-expanded="true"] .burger__lines::before { top: 5px; transform: rotate(45deg); }
.burger[aria-expanded="true"] .burger__lines::after  { top: 5px; transform: rotate(-45deg); }
.burger:focus-visible { outline: var(--st-accent) solid var(--yellow); outline-offset: var(--focus-offset); }

/* Меню прибито к окну, поэтому его высота — ровно высота экрана, и
   лишнему содержимому деваться некуда. Центрирование через
   justify-content резало его с обеих сторон разом: на айфоне пять
   разделов с кнопкой в экран не влезали, верхний пункт уходил за
   кромку под чёлку, и доскроллить туда было нельзя — flex обрезает
   переполнение с той стороны, куда центрует. Ян 2026-09-21.

   Теперь центрирование держат автоматические поля: пока места хватает,
   они разводят содержимое к середине; как только перестаёт — поля
   схлопываются в ноль, содержимое встаёт от верхнего отступа и
   прокручивается. Обрезать нечего. */
.menu {
  position: fixed; inset: 0; z-index: var(--z-menu);
  background: var(--bg);
  display: flex; flex-direction: column; justify-content: flex-start;
  gap: var(--menu-gap);
  padding: calc(var(--menu-top) + var(--safe-t)) var(--side-r)
 calc(var(--menu-bottom) + var(--safe-b)) var(--side-l);
  overflow-y: auto; overscroll-behavior: contain;
  transform: translateY(-100%);
  transition: transform var(--dur-move) var(--ease-standard);
}
.menu__nav { margin-top: auto; }
.menu__cta { margin-bottom: auto; }
.menu.is-open { transform: none; }
.menu[hidden] { display: none; }
.menu__nav { display: flex; flex-direction: column; gap: var(--menu-list-gap); }
.menu__nav a {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-tight); line-height: var(--lh-snug);
  /* Кегль ограничен и по ширине, и по высоте окна: пять разделов с
     кнопкой обязаны помещаться в невысокий экран телефона целиком. */
  font-size: var(--fs-menu);
  color: var(--fg); text-decoration: none;
  /* Палец попадает по цели, а не по буквам: при 9vw на узком экране строка
     высотой 33px при норме 44 — тот же приём, что у названия в шапке. */
  display: inline-flex; align-items: center; min-height: var(--tap);
}
.menu__nav a[aria-current="page"] { color: var(--yellow); }
.menu__nav a:focus-visible { outline: var(--st-accent) solid var(--yellow); outline-offset: var(--focus-offset); }
.menu__cta { align-self: flex-start; margin-top: var(--menu-cta); }
/* Пока меню открыто, кнопка в шапке дублирует ту, что в меню. */
html[data-menu="open"] .head .pill { display: none; }

@media (max-width: 899px) {
  .nav { display: none; }
  .burger { display: inline-flex; }
}
@media (min-width: 900px) {
  .menu { display: none; }
}

/* --- Главы и сетка --------------------------------------------- */
.ch { position: relative; }
.hero, .screen { padding: var(--pad-y) 0; }
.grid {
  /* width: 100% обязателен. Первый экран — колонка флексбокса, а у
     флекс-элемента с margin: 0 auto отменяется растяжение по поперечной
     оси: сетка сжималась по содержимому. На 768 это давало первый экран
     уже остальной страницы и сдвинутый от левого поля на 30px —
     колонки первого экрана не сходились с колонками ниже. */
  max-width: var(--max); width: 100%; margin: 0 auto; padding: 0 var(--side-r) 0 var(--side-l);
  display: grid; grid-template-columns: repeat(12, 1fr);
  column-gap: var(--col-gap);
  /* Ряды сетки обязаны дышать: без этого абзац после списка в четыре
     колонки прилипал к самой длинной колонке и читался как наложение. */
  row-gap: var(--sp-f7);
}
.grid > * { grid-column: 1 / -1; }
@media (min-width: 900px) {
  .g-title { grid-column: 1 / 7; }
  .g-body  { grid-column: 7 / 13; }
  .g-wide  { grid-column: 1 / 11; }
  .g-full  { grid-column: 1 / -1; }
  .g-half  { grid-column: 1 / 7; }
  .g-right { grid-column: 7 / 13; }
}

/* --- Первый экран ---------------------------------------------- */
.hero {
  min-height: 100vh; min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  position: relative; padding-top: calc(var(--hero-top) + var(--safe-t));
}
.hero__title {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-tight); line-height: var(--lh-tight); margin: 0;
  /* Кегль ограничен и по ширине, и по высоте окна: на широком, но
     невысоком экране пять строк заголовка не влезали. */
  font-size: var(--fs-hero); max-width: 13ch;
}
.hero__body { margin-top: var(--sp-f10); }
.hero__cue {
  position: absolute; right: var(--side-r); bottom: calc(clamp(26px,5vh,56px) + var(--safe-b));
  display: flex; align-items: center; gap: var(--sp-12);
  font-family: var(--mono); font-size: var(--fs-1);
  letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--mute);
}
.hero__cue-line { display: block; width: clamp(28px,3.4vw,60px); height: 1px; background: var(--ln); }

/* --- Шапка экрана ----------------------------------------------- */
.screen__head { display: flex; align-items: center; gap: var(--sp-f5); margin-bottom: var(--sp-f7); }
.screen__index { font-family: var(--mono); font-size: var(--fs-2); letter-spacing: var(--ls-caps); color: var(--mute); }
.screen__rule { flex: 1; height: 1px; background: var(--ln); display: block; }
.screen__title {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-tight); line-height: var(--lh-tight); margin: 0;
  font-size: var(--fs-14); max-width: 16ch;
}

/* --- Текст ------------------------------------------------------- */
/* Подзаголовки без класса — на юридических страницах это h2, в остальных
   местах h3. Раньше h2 оставался системным шрифтом и выпадал из системы. */
h3, main h2:not([class]) {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-display); font-size: var(--fs-11); line-height: var(--lh-heading); margin: 0 0 var(--sp-f4);
}
main h2:not([class]) { margin-top: var(--sp-f11); }
/* Длина строки. Часть абзацев в боевой разметке идёт без .measure и на
   широком экране растягивалась до 90–99 знаков — глаз теряет строку.

   Считаем в знаках, а не в ch: нуль в Geist шире средней буквы, и 66ch
   давали на деле 88 знаков. Замер: знаков ≈ ширина / (0.5 × кегль),
   поэтому 52ch ≈ 70 знаков — верх рекомендованного диапазона. */
p { margin: 0 0 1em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }
.lead { font-size: var(--fs-8); line-height: var(--lh-lead); }
.lead strong, .lead b { font-weight: 500; }
.measure { max-width: var(--measure); }   /* тот же расчёт, что у p */
.small { font-size: var(--fs-4); }
.muted { color: var(--mute); }
.claim {
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-display); line-height: var(--lh-heading); font-size: var(--fs-12); margin: 0 0 .6em;
}
strong { font-weight: 500; }

/* --- Список с индексами ------------------------------------------ */
.index-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-f9); }
.index-list > li { border-top: var(--st-base) solid var(--ln); padding-top: var(--sp-f3); font-size: var(--fs-5); line-height: var(--lh-body); color: var(--mute); }
.index-list__what {
  display: block; margin-bottom: .45em; color: var(--fg);
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-display); font-size: var(--fs-9); line-height: var(--lh-heading);
}
@media (min-width: 760px) { .index-list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .index-list--4 { grid-template-columns: repeat(4, 1fr); } }

/* --- Схема потоков ------------------------------------------------ */
.streams { margin: 0; display: grid; gap: var(--sp-f7); align-items: center; }
@media (min-width: 900px) { .streams { grid-template-columns: 1fr auto 1fr; } }
.streams__from { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-10); }
.streams__from li, .streams__to {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-6) var(--sp-14);
  border-top: var(--st-hair) solid var(--ln); padding-top: var(--sp-8);
}
/* Правая часть схемы — не строка, а короткий список: чем именно
   управляют с пульта. Поэтому у неё своя раскладка, а не общий с
   источниками строчный поток. */
.streams__to { border-top: var(--st-base) solid var(--yellow); display: grid; gap: var(--sp-10); }
.streams__parts {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-14);
  font-size: var(--fs-5);
}
/* Точка между пунктами — разделитель, а не украшение: без неё
   «деньгами продуктом» читается одной фразой. У последнего её нет. */
.streams__parts li + li::before { content: "· "; color: var(--mute); }
.streams__note {
  font-family: var(--mono); font-size: var(--fs-1);
  letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--mute);
}
.streams__who { font-family: var(--mono); font-size: var(--fs-1); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--mute); }
.streams__what { font-family: var(--display); font-weight: 900; text-transform: uppercase; letter-spacing: var(--ls-display); font-size: var(--fs-7); }
.streams__arrow { justify-self: center; width: 46px; height: 2px; background: var(--fg); position: relative; }
.streams__arrow::after { content:""; position: absolute; right: 0; top: -4px; border: 5px solid transparent; border-left-color: var(--fg); }
@media (max-width: 899px) { .streams__arrow { transform: rotate(90deg); margin: var(--sp-6) 0; } }
.streams figcaption, .chart figcaption { font-family: var(--mono); font-size: var(--fs-1); letter-spacing: var(--ls-mono-wide); color: var(--mute); margin-top: var(--sp-10); grid-column: 1 / -1; }

/* --- Лестница ступеней — снята вместе с блоком --------------------
   Единственным её местом была глава «Как идёт работа» на главной,
   убранная 2026-09-21 по правке Яна: «на главной как идёт работа нужно
   убрать, у нас для этого есть специальная страница». Классы .steps*
   не использовались больше нигде, поэтому уехали вслед за разметкой —
   мёртвые правила в общем файле стилей потом принимают за живые.
   Понадобится вернуть — коммит 7ecb836 и запись PROGRESS.md 09-21. */

/* --- График -------------------------------------------------------- */
/* Под графиком — плотный фон главы. Без него нити сцены шли прямо
   сквозь линии графика и путались с ними: две системы линий на одном
   месте, и ни одна не читается. Ян 2026-09-21: «очень путаются линии
   с графиком, их надо как-то разделить». Цвет берётся из переменной,
   поэтому подложка идёт за главой и на ней не видна как плашка —
   видно только, что поле под графиком чистое. */
.chart {
  margin: 0; position: relative; z-index: var(--z-content);
  background: var(--bg);
  padding: var(--sp-f5) var(--sp-f5) var(--sp-f3);
  /* Края растворяются, чтобы прямоугольник не читался как вырез
     в поле — тот же приём, что у имён потоков. */
  -webkit-mask-image: radial-gradient(120% 130% at 50% 50%, #000 72%, transparent 100%);
  mask-image: radial-gradient(120% 130% at 50% 50%, #000 72%, transparent 100%);
}
/* overflow видимым: подпись «деньги на счёте» выходит за viewBox и срезалась */
.chart svg { width: 100%; height: auto; display: block; overflow: visible; }
.chart__axis  { stroke: var(--ln); stroke-width: 1; }
/* Сетка — то, чего не хватало прежней схеме: по ней видно, что линии
   стоят на шкале, а не нарисованы от руки. Тоньше и бледнее осей,
   иначе она спорит с самими линиями. */
.chart__grid line { stroke: var(--ln); stroke-width: 1; stroke-dasharray: 2 4; }
.chart__work  { fill: none; stroke: var(--fg); stroke-width: 2.5; stroke-linejoin: round; }
.chart__money { fill: none; stroke: var(--yellow); stroke-width: 2.5; stroke-linejoin: round; }
/* Точки замеров на линии денег: у графика из счёта они есть всегда —
   это месяцы, по которым он построен. */
.chart__dots circle { fill: var(--yellow); }
.chart__label { fill: var(--mute); font-family: var(--mono); font-size: 8px; letter-spacing: var(--ls-mono); }
.chart__label--axis { text-anchor: middle; }
.chart__label--tick { text-anchor: end; }

/* --- Чужой пример --------------------------------------------------- */
.case { margin: 0; border-left: var(--st-accent) solid var(--yellow); padding-left: var(--sp-f5); }
.case blockquote { margin: 0 0 .6em; font-size: var(--fs-9); line-height: var(--lh-quote); font-weight: 500; }
.case figcaption { font-size: var(--fs-3); color: var(--mute); }

/* --- Самопроверка ---------------------------------------------------- */
.check { display: grid; gap: 0; }
.check__item { border-top: var(--st-base) solid var(--ln); }
.check__item:last-child { border-bottom: var(--st-base) solid var(--ln); }
.check__head {
  cursor: pointer; list-style: none; padding: var(--sp-f4) 0;
  font-family: var(--display); font-weight: 900; text-transform: uppercase;
  letter-spacing: var(--ls-display); font-size: var(--fs-10); line-height: var(--lh-heading);
  display: flex; align-items: baseline; gap: var(--sp-14);
}
.check__head::-webkit-details-marker { display: none; }
.check__head::after { content: "+"; margin-left: auto; font-family: var(--mono); font-size: .8em; color: var(--mute); }
.check__item[open] .check__head::after { content: "–"; }
.check__body { padding: 0 0 var(--sp-f5); max-width: var(--measure-answer); color: var(--mute); font-size: var(--fs-5); }
.check__left { color: var(--fg); border-left: var(--st-accent) solid var(--yellow); padding-left: var(--sp-14); }

/* --- Четыре потока: имена встают на полосы нитей ---------------------- */
/* Блок держится на экране, пока идёт прокрутка: только так имя потока
   может стоять ровно на своей нити — холст прибит к окну, а текст едет. */
.pin { height: 240vh; position: relative; }
.pin__in { position: sticky; top: 0; height: 100vh; height: 100svh; }

.flows { position: absolute; inset: 0; display: block; gap: 0; }

/* Имя потока обязано стоять ровно на своей нити. Описания разной длины,
   поэтому блок целиком центрировать нельзя: сдвиг считается от центра
   самого имени. Значения заданы числами по трём ширинам, а не формулой:
   clamp внутри calc внутри translateY Chrome парсит, но не применяет —
   transform молча становится единичным, имена уезжают вниз на 35px. */
.flows > li {
  position: absolute; right: 0; width: min(46vw, 560px);
  border-top: 0; padding: var(--sp-12) var(--sp-f4) var(--sp-12) var(--sp-f8);
  /* Подложка нужна, чтобы имя читалось поверх нитей, но сплошная
     вырезала в поле чёткий прямоугольник — на чёрной главе это было
     видно как дыра в жёлтых нитях. Теперь она сходит на нет к обоим
     краям: имя на плотном, поле не разрезано. */
  background: linear-gradient(to right,
    transparent 0, var(--bg) 7%, var(--bg) 88%, transparent 100%);
  opacity: var(--o-dim);
  transform: translateY(-33px);
}
.flows > li::before {
  content: ""; position: absolute; right: 100%; top: 33px;
  width: clamp(24px,3vw,56px); height: 2px;
  /* Доля жёлтого приходит из скрипта числом, смешивание считает CSS —
     поэтому цвет всегда берётся от текущего --fg, каким бы ни был фон. */
  background: color-mix(in srgb, var(--yellow) var(--litpct, 0%), var(--fg));
}
.flows .index-list__what {
  font-size: 40px;
  color: color-mix(in srgb, var(--yellow) var(--litpct, 0%), var(--fg));
}


.flows > li:nth-child(1) { top: 20%; }
.flows > li:nth-child(2) { top: 40%; }
.flows > li:nth-child(3) { top: 60%; }
.flows > li:nth-child(4) { top: 80%; }

@media (max-width: 1499px) {
  .flows .index-list__what { font-size: 32px; }
  .flows > li { transform: translateY(-29px); }
  .flows > li::before { top: 29px; }
}
@media (max-width: 1199px) {
  .flows .index-list__what { font-size: 26px; }
  .flows > li { transform: translateY(-26px); }
  .flows > li::before { top: 26px; }
}

/* Закрепление отменяется в двух случаях: на телефоне (текст идёт во всю
   ширину, нити разведены иначе) и когда движение выключено — иначе блок
   держал бы 240vh пустой прокрутки, на которой ничего не происходит. */
@media (max-width: 899px) {
  .pin { height: auto; }
  .pin__in { position: static; height: auto; }
  .flows { position: static; display: grid; gap: var(--sp-f9); }
  .flows > li { position: static; width: auto; transform: none; opacity: 1;
    border-top: var(--st-base) solid var(--ln); padding: var(--sp-f3) 0 0; background: none; }
  .flows > li::before { display: none; }
  .flows .index-list__what { color: var(--fg) !important; }
}
html[data-motion="off"] .pin { height: auto; }
html[data-motion="off"] .pin__in { position: static; height: auto; }
html[data-motion="off"] .flows { position: static; display: grid; gap: var(--sp-f9); }
html[data-motion="off"] .flows > li { position: static; width: auto; transform: none; opacity: 1;
  border-top: var(--st-base) solid var(--ln); padding: var(--sp-f3) 0 0; background: none; }
html[data-motion="off"] .flows > li::before { display: none; }
html[data-motion="off"] .flows .index-list__what { color: var(--fg) !important; }
@media (min-width: 900px) {
  html[data-motion="off"] .flows { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1100px) {
  html[data-motion="off"] .flows { grid-template-columns: repeat(4, 1fr); }
}

/* --- Форма ------------------------------------------------------------- */
.form { display: grid; gap: var(--sp-f6); max-width: var(--measure-form); }
.field { display: grid; gap: var(--sp-12); }
.field label { font-family: var(--mono); font-size: var(--fs-1); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--mute); }
.field__hint { text-transform: none; letter-spacing: 0; }
/* Белая подложка с размытыми краями под строкой, где печатают, — Ян
   2026-09-25. Нити сцены идут под формой, и точка садилась прямо на
   набранный текст (прогон 20 персон, кадр 07). Цвета не от главы, а
   постоянные: белая подложка на любом фоне. Край тает в фон главы, поэтому
   зазор под подписью --sp-12: иначе свечение ложится на подпись. Всё —
   токенами системы, новых не заведено (Figma: компонент Field). */
.field input, .field textarea {
  width: 100%; background: var(--c-white); border: 0; border-bottom: var(--st-base) solid var(--ln-on-light);
  color: var(--c-black); font: inherit; padding: var(--sp-6) var(--sp-8) var(--sp-10); border-radius: 0;
  box-shadow: 0 0 var(--sp-12) var(--sp-4) var(--c-white);
}
.field input::placeholder, .field textarea::placeholder { color: var(--c-grey-ink); }
.field textarea { min-height: 96px; resize: vertical; }
/* Фокус — чёрная черта: жёлтая на белом почти не видна (1,3 : 1). */
.field input:focus-visible, .field textarea:focus-visible { outline: none; border-bottom-color: var(--c-black); }
/* Незаполненное поле. Жёлтый — единственный акцент оформления, поэтому
   ошибка говорит им же, а не красным: красного в системе нет вовсе.
   Цветом одним дело не ограничивается — под полем стоит текст, что сделать,
   и скрипт вешает aria-invalid с aria-describedby. */
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-bottom-color: var(--yellow); }
.field__err {
  font-family: var(--mono); font-size: var(--fs-2); line-height: var(--lh-lead);
  background: var(--yellow); color: var(--on-accent); padding: var(--sp-6) var(--sp-12); border-radius: var(--r-pill);
  justify-self: start; max-width: 100%;
}
.field__err[hidden] { display: none; }
/* Ловушка для роботов (разметка форм, аудит 2026-09-22): за экраном, вне
   табуляции, без клика. display:none не годится — умный робот такие поля
   пропускает. Отрицательный left полосу прокрутки не создаёт. */
.form__trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }
.form__reply { font-family: var(--mono); font-size: var(--fs-3); background: var(--yellow); color: var(--on-accent); padding: var(--sp-10) var(--sp-16); border-radius: var(--r-pill); justify-self: start; }

/* Заявка ушла. Форма отдаёт своё место одному сообщению: поля, кнопка,
   строка под ней и абзац про данные скрываются. Высоту формы держит
   inline-стиль, который ставит скрипт замером до скрытия — страница не
   прыгает, и главам не приходится пересчитывать закреплённые блоки.
   Плашка остаётся только у ошибок: ошибка — это записка сбоку, а
   отправленная заявка — новое состояние всего блока. */
.form.is-sent { place-content: center; justify-items: center; text-align: center; }
.form.is-sent > :not(.form__sent) { display: none; }
.form__sent {
  font-family: var(--mono); font-size: var(--fs-10); line-height: var(--lh-lead);
  color: var(--fg); max-width: 20em; text-wrap: balance;
  animation: sent-in var(--dur-appear) var(--ease-standard) both;
  /* Нити сцены идут по центру узкого экрана — ровно туда, куда встаёт это
     сообщение. Растушёванная подложка цветом главы уводит пучок ПОД текст,
     а не сквозь буквы: рисунок в текст не лезет (правило Яна 2026-09-19).
     Цвет берётся токеном, поэтому подложка меняется вместе с главой. */
  padding: var(--sp-f8) var(--sp-f8);
  background: radial-gradient(ellipse at center, var(--bg) 55%, transparent 100%);
}
/* Единственный акцент страницы — жёлтый. Здесь он тонкой чертой над
   сообщением, как линейка у заголовков экранов, а не плашкой в полблока. */
.form__sent::before {
  content: ""; display: block; width: 56px; height: 2px;
  background: var(--yellow); margin: 0 auto var(--sp-f5);
}
.form__sent:focus-visible { outline: var(--st-base) solid var(--yellow); outline-offset: 12px; }
@keyframes sent-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
html[data-motion="off"] .form__sent { animation: none; }

/* --- Кнопка в Telegram вместо формы -----------------------------------
   2026-09-24, решение Яна: форм на сайте нет, всё общение — в Telegram
   через бота. Блок: предупреждение (только на «Ценах»), кнопка в бота с
   подписью, строка «нет Telegram — почта», строка про данные. Справа QR —
   только на широком экране с мышью: у кого Telegram лишь на телефоне,
   наводит камеру. На телефоне кода нет, кнопка и так открывает приложение.
   Кнопка — обычная .button, поэтому нити сцены приходят в неё сами
   (motion.js, ctaList). Код стоит справа от кнопки: нити подходят слева
   и на ней кончаются, в код они не заходят. */
.tg { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--sp-f10); }
.tg__main { flex: 1 1 30ch; max-width: var(--measure-wide); display: grid; gap: var(--sp-f4); }
.tg__main > p { margin: 0; }
/* Предупреждение — чертой слева, как у цитаты: это пояснение к кнопке,
   а не плашка-пометка (жёлтые плашки у нас значат «черновик»). */
.tg__note {
  font-family: var(--mono); font-size: var(--fs-3); line-height: var(--lh-body);
  border-left: var(--st-accent) solid var(--yellow); padding-left: var(--sp-f3);
}
.tg__qr { display: none; margin: 0; }
/* Белое поле вокруг кода нарисовано в самом SVG — на чёрной главе код
   читается плиткой, на белой его край держит тонкая линия. */
.tg__qr img {
  display: block; width: clamp(128px,9vw,156px); height: auto; aspect-ratio: 1;
  border-radius: var(--r-soft); outline: var(--st-hair) solid var(--ln); outline-offset: -1px;
}
.tg__qr figcaption {
  font-family: var(--mono); font-size: var(--fs-1); letter-spacing: var(--ls-mono-wide);
  line-height: var(--lh-lead); color: var(--mute); max-width: 17ch; margin-top: var(--sp-10);
}
@media (min-width: 900px) and (hover: hover) and (pointer: fine) {
  .tg__qr { display: block; flex: 0 0 auto; }
}

/* --- Плейсхолдеры и пометки -------------------------------------------- */
.todo { background: var(--yellow); color: var(--on-accent); padding: 0 .3em; font-family: var(--mono); font-size: .92em; }
.todo-note {
  font-family: var(--mono); font-size: var(--fs-2); letter-spacing: var(--ls-mono);
  background: var(--yellow); color: var(--on-accent); padding: var(--sp-10) var(--sp-16); border-radius: var(--r-soft); display: inline-block;
}

/* --- Отступы ------------------------------------------------------------ */
.mt-4 { margin-top: var(--sp-f4); }
.mt-5 { margin-top: var(--sp-f6); }
.mt-6 { margin-top: var(--sp-f9); }
.mt-7 { margin-top: var(--sp-f11); }

/* --- Служебная плашка прототипа (в бой не идёт) ------------------------- */
.probe {
  position: fixed; left: 12px; bottom: 12px; z-index: 9;
  font-family: var(--mono); font-size: 11px; line-height: var(--lh-body);
  background: rgba(0,0,0,.8); color: #d9dbde; padding: var(--sp-6) var(--sp-10); border-radius: 8px;
  pointer-events: none; white-space: pre;
}

/* --- Узкий экран --------------------------------------------------------- */
@media (max-width: 760px) {
  .nav { display: none; }
  .hero__title { max-width: 11ch; }
  .hero__cue { display: none; }
}

/* --- Движение выключено -------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .head, .pill, .button { transition: none !important; }
  .form__sent { animation: none !important; }
}
