/* =========================================================================
   WACIS — кабинет

   Палитра та же, что на сайте: шесть фирменных цветов и ничего сверх.
   Оттенки получены только прозрачностью и смешиванием, поэтому кабинет
   нельзя случайно увести в чужой цвет.

   Кабинет — рабочий инструмент, а не витрина: плотнее сетка, меньше
   воздуха, состояние читается плашкой, а не абзацем текста.
   ========================================================================= */
/* =========================================================================
   ШРИФТ

   Golos Text, переменный по насыщенности. Лежит у нас в
   /fonts/golos-text/ — см. пояснение рядом с файлами.

   Почему не системный. Системный набор даёт на маке SF Pro, на Windows
   Segoe UI, на линуксе что придётся: у платформы нет своего лица, и два
   человека видят разные кабинеты. Для инструмента это допустимо, для
   платформы, которую продают, — нет.

   Почему именно этот. Он сделан для русского интерфейса: широкая
   кириллица, спокойный рисунок, цифры не спорят с буквами. В кабинете,
   где всюду суммы и остатки, это важнее характера.

   swap, а не block: пока шрифт едет, текст показывается системным. Так
   человек читает страницу сразу, а не смотрит на пустое место ради
   красоты первого кадра.
   ========================================================================= */
@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;      /* переменный: промежуточные веса берутся отсюда же */
  font-display: swap;
  src: url("/fonts/golos-text/golos-text-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/golos-text/golos-text-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;
}

:root {
  /* Фирменные цвета — те же шесть. Ничего нового не придумано. */
  --navy:  #00004f;
  --paper: #f2f2f2;
  --ink:   #1a1a1a;
  --wine:  #450b1a;
  --plum:  #831381;
  --teal:  #006655;
  --white: #fff;

  /*
   * ═══════════════════════════════════════════════════════════════════
   *  ОДИН АКЦЕНТ, А НЕ ЧЕТЫРЕ
   * ═══════════════════════════════════════════════════════════════════
   *
   * Раньше акцентом работали все четыре цвета сразу: plum красил ссылки,
   * главную кнопку, кольцо фокуса и предупреждения; navy — шапку и
   * выбранный пункт меню; teal — успех и половину плашек; wine — ошибки.
   * Глазу не за что зацепиться, когда важно всё.
   *
   * Теперь акцент один — navy, он же в знаке. Им отмечено то, на что
   * человек нажимает или что выбрано. Остальные цвета говорят только о
   * состоянии: teal «хорошо», wine «плохо», plum «внимание».
   *
   * Цвет состояния никогда не красит кнопку и не служит украшением.
   */
  --accent:      var(--navy);
  --accent-soft: color-mix(in srgb, var(--navy) 8%, var(--white));
  --accent-line: color-mix(in srgb, var(--navy) 22%, var(--white));

  /*
   * Полотно чуть холоднее бумаги и уведено в сторону акцента на 1.5% —
   * ровно столько, чтобы белая карточка на нём читалась как отдельный
   * предмет, а не как то же самое. Нейтраль без подмеса рядом с navy
   * выглядит грязноватой.
   */
  --bg:      color-mix(in srgb, var(--navy) 3%, #fafafa);
  --surface: var(--white);
  --panel:   color-mix(in srgb, var(--navy) 5%, var(--bg));

  --fg:      var(--ink);
  /*
   * Приглушённый текст — 78% чернил, а не 62%.
   *
   * На 62% выходил #6c6c6d: контраст с фоном 4.7 — впритык к
   * минимуму, при котором текст ещё считается читаемым. Формально
   * проходило, на экране выглядело выцветшим, и подписи под полями
   * читались хуже, чем должны.
   *
   * 78% дают #4a4a4a и контраст 7.9 — читается спокойно и всё ещё
   * заметно светлее основного текста, то есть роль «второстепенного»
   * сохраняется. Этим цветом набраны подсказки под полями, подписи в
   * карточках и пояснения в списках — то, что читают внимательно, а
   * не проглядывают.
   */
  --fg-mute: color-mix(in srgb, var(--ink) 78%, var(--bg));
  --hair:    color-mix(in srgb, var(--navy) 11%, var(--bg));
  --hair-2:  color-mix(in srgb, var(--navy) 20%, var(--bg));

  --ok:   var(--teal);
  --warn: var(--plum);
  --bad:  var(--wine);

  /*
   * Системный набор остаётся запасным: он показывает текст, пока едет
   * наш шрифт, и выручает, если файл почему-то не отдался.
   */
  --font: "Golos Text", -apple-system, BlinkMacSystemFont, "Segoe UI",
          "Helvetica Neue", "Liberation Sans", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  /*
   * Скругление ступенями, а не одно на всё. Вложенное скругляется
   * слабее внешнего — иначе внутренний угол зрительно «выпирает» из
   * внешнего, и коробка выглядит склеенной, а не выточенной.
   */
  --r:    12px;   /* карточки, панели */
  --r-in:  8px;   /* поля, кнопки, строки внутри карточки */
  --r-xs:  6px;   /* мелочь: плашки-квадраты, чипы */

  /*
   * Тени подкрашены в navy, а не чёрные. Чёрная тень на цветной
   * подложке даёт грязный серый ореол; тень цвета фона читается как
   * настоящий свет. Две ступени: лежит и приподнято.
   */
  --sh-1: 0 1px 2px color-mix(in srgb, var(--navy) 8%, transparent),
          0 1px 1px color-mix(in srgb, var(--navy) 4%, transparent);
  --sh-2: 0 4px 16px color-mix(in srgb, var(--navy) 10%, transparent),
          0 1px 3px color-mix(in srgb, var(--navy) 6%, transparent);

  /* Затухание, а не равномерность: движение так читается живым. */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --dur:  .16s;

  /*
   * Слои названы по смыслу. Числа вроде 999 берутся от растерянности,
   * и потом никто не знает, что выше чего.
   */
  --z-sticky: 30;
  --z-band:   50;
  --z-modal:  70;
}

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  /*
   * Цифры одной ширины по всему кабинету. Здесь всюду деньги, остатки и
   * счётчики; в пропорциональном начертании столбец сумм «пляшет», и
   * взгляд не может сравнить два числа, не читая их целиком.
   */
  font-variant-numeric: tabular-nums;
}

/*
 * Шкала заголовков постоянная, а не резиновая.
 *
 * Здесь стоял clamp(24px, 3vw, 30px). В кабинете это вредно: человек
 * смотрит на постоянном экране, а заголовок дышал при каждом изменении
 * ширины окна и в узкой колонке становился мельче подзаголовка соседа.
 * Резиновая типографика — приём витрины, где страницу листают, а не
 * работают в ней.
 */
h1, h2, h3 { margin: 0; line-height: 1.2; letter-spacing: -.021em; font-weight: 660; }
h1 { font-size: 27px; letter-spacing: -.028em; text-wrap: balance; }
h2 { font-size: 18px; }
h3 { font-size: 15.5px; }
p  { margin: 0; }
a  { color: var(--accent); text-underline-offset: .18em; }
a:hover { text-decoration-thickness: 2px; }

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/*
 * Движение отключается целиком, если человек попросил об этом в системе.
 * Не «покороче», а без него: просьба обычно означает не «мне не нравится»,
 * а «от этого укачивает».
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------- ШАПКА */
.top {
  background: var(--navy);
  color: var(--paper);
  /*
   * Тонкая светлая черта по низу вместо рамки в цвет: она читается как
   * край предмета, а не как ещё одна линия интерфейса.
   */
  box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--paper) 12%, transparent);
}
.top__in {
  width: min(100% - 40px, 1180px);
  margin-inline: auto;
  height: 56px;
  display: flex; align-items: center; gap: 20px;
}
.logo { display: flex; align-items: center; gap: 9px; text-decoration: none; color: inherit; }
/* Знак не квадратный: пропорция 7:1. Задаём высоту, ширину считает
   браузер по viewBox — жёсткая ширина сплющила бы начертание. */
.logo svg { width: auto; height: 18px; display: block; }
.logo sup {
  font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--teal) 45%, var(--paper)); margin-left: 4px;
}
.top__right { margin-left: auto; display: flex; align-items: center; gap: 14px; font-size: 14px; }
.top__right a { color: inherit; }
.top__who { color: color-mix(in srgb, var(--paper) 62%, var(--navy)); }
.top form { display: inline; }

/* ------------------------------------------------------------ КАРКАС */
.shell {
  width: min(100% - 40px, 1180px);
  margin: 26px auto 72px;
  display: grid;
  grid-template-columns: 216px minmax(0, 1fr);
  gap: 26px;
  align-items: start;
}
@media (max-width: 800px) { .shell { grid-template-columns: 1fr; gap: 18px; } }

/* ---------------------------------------------------------- НАВИГАЦИЯ */
/*
 * Меню — отдельная поверхность, а не текст на общем фоне.
 *
 * Продуктовый интерфейс хочет второго слоя нейтрали под навигацией:
 * так глаз с одного взгляда делит экран на «где я хожу» и «с чем
 * работаю». Раньше пункты висели прямо на полотне, и граница между
 * ними и содержимым держалась только на отступе.
 */
.side {
  display: grid; gap: 1px;
  background: var(--panel);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 8px;
  position: sticky; top: 18px;
}
/*
 * Заголовок группы — обычным словом, а не капслоком с разрядкой.
 *
 * Мелкие прописные с широкой разрядкой над каждой группой — привычка,
 * от которой интерфейс стареет: их шесть штук на экране, все кричат, и
 * ни один не важен. Группу достаточно отделить воздухом и чертой.
 */
.side__gr {
  font-size: 12px; font-weight: 600; letter-spacing: 0; text-transform: none;
  color: var(--fg-mute); padding: 14px 10px 5px;
}
.side__gr:first-child { padding-top: 4px; }
.side a {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: var(--r-in);
  text-decoration: none; color: var(--fg); font-size: 14.5px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.side a:hover { background: color-mix(in srgb, var(--navy) 7%, transparent); }
.side a[aria-current] {
  background: var(--accent); color: var(--paper); font-weight: 600;
  box-shadow: var(--sh-1);
}
/*
 * Ссылка наружу помечена стрелкой.
 *
 * Уход из панели должен быть виден заранее: человек нажимает пункт
 * меню, ожидая остаться на месте, а открывается другая вкладка с
 * другим сайтом. Стрелка — предупреждение, а не украшение, поэтому
 * стоит у самого края и приглушена: заметить можно, отвлечься нельзя.
 */
.side a[data-ext]::after {
  content: "↗"; margin-left: auto;
  font-size: 12px; color: var(--fg-mute); line-height: 1;
}
.side a[data-ext][aria-current]::after,
.side a[data-ext]:hover::after { color: inherit; }

/* Раздел, за которым пока ничего нет. Помечаем, а не прячем: человек
   должен видеть, что сервис умеет и чего ещё ждать. */
.side a[data-soon] { color: var(--fg-mute); }
.side a[data-soon]::after {
  content: "скоро"; margin-left: auto;
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-mute); border: 1px solid var(--hair-2);
  padding: 1px 5px; border-radius: 20px;
}
@media (max-width: 800px) {
  .side { grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; gap: 4px; padding-bottom: 4px; }
  .side__gr { display: none; }
  .side a[data-soon]::after { display: none; }
}

/* ------------------------------------------------------------- КАРТЫ */
.card {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 22px;
  box-shadow: var(--sh-1);
}
.card + .card { margin-top: 18px; }
.card__h { display: flex; align-items: baseline; gap: 12px; margin-bottom: 4px; }
.card__sub { color: var(--fg-mute); font-size: 14px; margin-top: 6px; }

.grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

/*
 * Отступ между картами ставится сверху у второй и следующих. Внутри
 * сетки это лишнее — расстояние там задаёт gap, — и хуже того: карта,
 * стоящая в сетке второй, получает эти восемнадцать пикселей и
 * съезжает вниз относительно соседки. Со стороны это выглядит как
 * плавающие карточки, и виноватой кажется сетка.
 *
 * Раньше это лечили в каждом месте руками, дописывая style="margin:0"
 * к карточке. Где дописать забывали — там и плавало.
 *
 * Правило перечисляет ВСЕ сетки-контейнеры. Когда оно было написано
 * только про .grid, добавленный позже .cols остался без снятия
 * отступа — и правая карточка на /balance висела на восемнадцать
 * пикселей ниже левой. Новый контейнер для карточек дописывать сюда.
 */
.grid > .card, .grid > .card + .card,
.cols > .card, .cols > .card + .card { margin-top: 0; }

/*
 * Расстояние между блоками верхнего уровня.
 *
 * .card + .card знает только про две карточки подряд. Стоит между
 * ними появиться сетке — а на /balance так и есть, — и соседство
 * рвётся: карточка «История операций» прилипала к блоку .cols без
 * зазора. Поэтому соседство описано между всеми видами блоков, а не
 * между карточками.
 */
.cols + .card, .card + .cols, .cols + .cols,
.grid + .card, .card + .grid, .grid + .grid,
.cols + .grid, .grid + .cols { margin-top: 18px; }

/*
 * Две колонки разной ширины: слева узкая с итогом, справа широкая с
 * действием. На узком экране — одна колонка.
 *
 * Отдельным классом, а не стилем в разметке: inline
 * grid-template-columns перекрывает и auto-fit, и медиазапрос, так
 * что на телефоне колонки остаются двумя и сжимаются до ста тридцати
 * пикселей, а суммы вылезают за край карточки.
 */
/*
 * stretch, а не start: со start каждая карточка обрывалась на высоте
 * своего содержимого, и две колонки заканчивались на разных уровнях —
 * то самое «кривые блоки». Теперь обе тянутся до низа строки.
 */
.cols { display: grid; gap: 18px; grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); align-items: stretch; }
@media (max-width: 720px) { .cols { grid-template-columns: 1fr; } }

/* Плитка со значением */
.stat { display: grid; gap: 4px; }
/*
 * Подпись значения — обычным словом. Прописные с разрядкой над каждым
 * числом превращают четыре плитки в четыре одинаковых крика; важнее
 * само число, а подпись должна дать себя прочитать и отойти.
 */
.stat__k { font-size: 13px; letter-spacing: 0; text-transform: none; color: var(--fg-mute); font-weight: 500; }
.stat__v { font-size: 27px; font-weight: 660; letter-spacing: -.03em; }
.stat__n { font-size: 13px; color: var(--fg-mute); }

/* ------------------------------------------------------- ПОЛОСА ШАГОВ */
/*
 * Пройденные шаги — ссылки, будущие — нет. Видимая, но не работающая
 * ссылка учит не доверять ссылкам, а прыгнуть вперёд всё равно нельзя:
 * человек оказался бы на оплате с пустым расписанием.
 */
.steps {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-bottom: 18px;
}
.steps__i {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px 8px 10px; border-radius: 999px;
  font-size: 14px; text-decoration: none; color: var(--fg-mute);
  background: var(--panel); border: 1px solid var(--hair);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.steps__n {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; border-radius: 999px;
  font-size: 12px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--hair-2); color: var(--fg-mute);
}
a.steps__i:hover { background: color-mix(in srgb, var(--navy) 7%, var(--panel)); color: var(--fg); }
.steps__i--done { color: var(--fg); }
.steps__i--done .steps__n { background: var(--ok); border-color: var(--ok); color: var(--white); }
.steps__i--now  { background: var(--accent); border-color: var(--accent); color: var(--paper); font-weight: 600; }
.steps__i--now .steps__n { background: color-mix(in srgb, var(--paper) 22%, var(--accent));
                           border-color: transparent; color: var(--paper); }
.steps__i--wait { opacity: .62; }

/* Пошаговая инструкция: номера — часть смысла, а не украшение. */
.howto { margin: 14px 0 0; padding-left: 22px; display: grid; gap: 9px; font-size: 14.5px; }
.howto li { line-height: 1.5; }
.howto b { font-weight: 620; }

/* --------------------------------------------------- ГОТОВОЕ РАСПИСАНИЕ */
/*
 * Кнопки выбора — крупные и с подписью о последствии («24 поста в день»).
 * Последствие важнее названия: «Каждый час» звучит безобидно, пока не
 * увидишь, во что это выходит.
 */
.presets { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.presets__b {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 12px 16px; text-align: left; min-width: 150px;
}
.presets__n { font-size: 12.5px; font-weight: 400; color: var(--fg-mute); }
.presets__b:hover .presets__n { color: inherit; }

/* Строка дня: подпись слева, поле справа — так семь строк читаются
   столбцом, а не лесенкой. */
.field--day {
  grid-template-columns: 130px minmax(0, 1fr);
  align-items: center; gap: 12px;
}
.field--day label { margin: 0; }

/*
 * Числа месяца — сетка отметок, а не строки полей.
 *
 * Тридцать одна строка «число / время» пугала и не объясняла, почему их
 * три. Календарной сеткой человек отмечает нужные числа так же, как
 * делал бы в календаре, и время указывает один раз.
 */
.days31 {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr));
  gap: 6px; margin-top: 4px;
}
.days31__d { position: relative; }
.days31__d input {
  position: absolute; opacity: 0; width: 0; height: 0;
}
.days31__d span {
  display: grid; place-items: center;
  height: 38px; border-radius: var(--r-in);
  border: 1px solid var(--hair-2); background: var(--surface);
  font-size: 14px; cursor: pointer; user-select: none;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.days31__d span:hover { border-color: var(--accent-line); }
.days31__d input:checked + span {
  background: var(--accent); border-color: var(--accent); color: var(--paper); font-weight: 600;
}
/* Клавиатуре тоже надо видеть, где она стоит: поле спрятано, значит
   рамку рисуем на подписи. */
.days31__d input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Числа месяца нужны редко — прячем под раскрытие, чтобы не пугать
   формой из тридцати одной строки того, кому хватит дней недели. */
.dates { margin-top: 6px; }
.dates summary { cursor: pointer; font-size: 14px; color: var(--accent); }
@media (max-width: 560px) {
  .field--day { grid-template-columns: 1fr; gap: 5px; }
}

/* ------------------------------------------------------ ПРИМЕР ПОСТА */
/*
 * Пример показывается до оплаты и решает, заплатит человек или нет.
 * Поэтому он оформлен как текст, который читают, а не как поле формы:
 * шире строка, крупнее кегль, воздух вокруг.
 */
.sample {
  margin-top: 16px; padding: 18px 20px;
  background: var(--panel); border: 1px solid var(--hair);
  border-radius: var(--r);
}
.sample__h {
  font-size: 12.5px; color: var(--fg-mute); margin-bottom: 8px;
}
.sample__t { font-size: 15.5px; line-height: 1.62; max-width: 68ch; }

/* ------------------------------------------------------------ ПЛАШКИ */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
  padding: 3px 9px; border-radius: 20px; white-space: nowrap;
}
.pill--ok   { background: color-mix(in srgb, var(--ok) 12%, var(--white));   color: var(--ok); }
.pill--warn { background: color-mix(in srgb, var(--warn) 12%, var(--white)); color: var(--warn); }
.pill--bad  { background: color-mix(in srgb, var(--bad) 12%, var(--white));  color: var(--bad); }
/*
 * Выбор из нескольких вариантов с пояснением — качество картинок.
 * Строкой в столбик, а не в ряд: у каждого варианта своя цена и своё
 * объяснение, и рядом друг с другом они не читаются.
 */
.picks { display: grid; gap: 10px; margin-top: 6px; }
.picks__i { display: flex; gap: 10px; align-items: start; font-size: 14px;
            padding: 10px 12px; border: 1px solid var(--hair-2); border-radius: var(--r-in);
            cursor: pointer; }
.picks__i:hover { border-color: var(--navy); }
.picks__i input { margin-top: 3px; }
/*
 * Цена внутри метки — отдельным узлом, потому что её переписывает
 * скрипт при смене модели. Без своего узла пришлось бы собирать всю
 * строку заново, а вместе с ней — и пояснение под ней.
 */
.picks__p { font-variant-numeric: tabular-nums; }
/*
 * Ступень качества, которой выбранная модель не умеет. Не прячем, а
 * гасим: исчезнувшая строка читается как «её и не было», а погасшая
 * — как «есть, но не с этой моделью», что и правда.
 */
.picks__i.is-off { opacity: .45; cursor: not-allowed; }
/*
 * Ступень, выбранная у проекта: не выделение ради красоты, а ответ на
 * вопрос «мне какой брать». Абонемент платит только за свою ступень, и
 * без подсказки человек купит не тот.
 */
.picks__i.is-on { border-color: var(--navy); background: var(--white); }
.picks__i.is-off:hover { border-color: var(--hair-2); }

/*
 * Два поля, которые читаются как одно: «не короче N, не длиннее M».
 * Порознь они выглядят как два независимых вопроса, и человек
 * заполняет одно, забыв про второе.
 */
.pair { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.pair__i { display: flex; align-items: center; gap: 8px; }
.pair__l { font-size: 13px; color: var(--fg-mute); white-space: nowrap; }
.pair__i input { width: 8ch; }

/*
 * ОКНО ПОВЕРХ СТРАНИЦЫ — галерея картинок поста.
 *
 * Своё, а не библиотечное: одно окно на весь кабинет не оправдывает
 * чужой зависимости, которую потом обновлять и чинить.
 */
.modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center;
         justify-content: center; padding: 16px; background: rgba(16, 24, 40, .55); }
.modal[hidden] { display: none; }
.modal__box { background: var(--paper); border-radius: 12px; max-width: 760px; width: 100%;
              max-height: 90vh; display: flex; flex-direction: column; overflow: hidden;
              box-shadow: 0 24px 60px rgba(16, 24, 40, .28); }
.modal__head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
               padding: 16px 18px; border-bottom: 1px solid var(--hair); }
.modal__head h2 { margin: 0; }
.modal__body { padding: 16px 18px; overflow: auto; }
.modal__foot { display: flex; gap: 10px; justify-content: flex-end;
               padding: 14px 18px; border-top: 1px solid var(--hair); }

/*
 * Плитка картинок. Выбранная обведена — без обводки человек не знает,
 * какая уйдёт в пост, и нажимает «сохранить» наугад.
 */
.gal { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.gal__i { position: relative; border: 2px solid transparent; border-radius: 10px;
          overflow: hidden; cursor: pointer; background: var(--panel); padding: 0;
          aspect-ratio: 1 / 1; }
.gal__i img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gal__i.is-on { border-color: var(--accent); }
.gal__i.is-wait, .gal__i.is-bad { display: flex; align-items: center; justify-content: center;
                                  text-align: center; font-size: 12.5px; padding: 10px;
                                  color: var(--fg-mute); cursor: default; }
.gal__i.is-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

/* Отжившее, но не ошибка: истёкший абонемент, закрытая сессия. */
.pill--mute { background: color-mix(in srgb, var(--fg-mute) 10%, var(--white)); color: var(--fg-mute); }

/* --------------------------------------------------------- СООБЩЕНИЯ */
/*
 * ═══════════════════════════════════════════════════════════════════
 *  ЦВЕТНОЙ ПОЛОСЫ СЛЕВА БОЛЬШЕ НЕТ
 * ═══════════════════════════════════════════════════════════════════
 *
 * Здесь стояла border-left: 3px в цвет состояния. Приём знакомый, и
 * именно поэтому от него интерфейс выглядит как шаблон: полоса слева
 * ничего не сообщает сверх того, что уже говорит подложка, зато режет
 * плашку пополам и сбивает край текста с общей вертикали страницы.
 *
 * Состояние теперь несут подложка и точка перед текстом — точка стоит
 * там же, где начинается строка, и не спорит с сеткой.
 */
/*
 * `display: flex` ниже сильнее встроенного `hidden`, и скрытая
 * подсказка оставалась на экране пустой полосой. Правило снимает это
 * для всех сообщений сразу, а не для одного.
 */
.note[hidden] { display: none; }

.note {
  border: 1px solid var(--hair-2);
  border-radius: var(--r-in); padding: 13px 16px; font-size: 14.5px;
  display: flex; gap: 11px; align-items: start;
  background: var(--surface);
}
.note::before {
  content: ""; flex: none;
  width: 7px; height: 7px; border-radius: 999px;
  background: var(--hair-2); margin-top: .55em;
}
.note + .note, .note + .card, .card + .note { margin-top: 16px; }
.note--ok   { border-color: color-mix(in srgb, var(--ok) 26%, var(--bg));   background: color-mix(in srgb, var(--ok) 5%, var(--white)); }
.note--warn { border-color: color-mix(in srgb, var(--warn) 26%, var(--bg)); background: color-mix(in srgb, var(--warn) 5%, var(--white)); }
.note--bad  { border-color: color-mix(in srgb, var(--bad) 26%, var(--bg));  background: color-mix(in srgb, var(--bad) 5%, var(--white)); }
.note--ok::before   { background: var(--ok); }
.note--warn::before { background: var(--warn); }
.note--bad::before  { background: var(--bad); }
.note b { font-weight: 650; }
.note form { margin-left: auto; }
/*
 * Кнопка в плашке не переносится.
 *
 * «Отправить ещё раз» ломалось на две строки посреди плашки о
 * подтверждении почты: кнопка сжималась под остаток ширины, и надпись
 * в ней рвалась по слову. Плашка — самое заметное место на главной,
 * и рваная кнопка в ней читается как недоделка.
 */
.note .btn { white-space: nowrap; flex: none; }

/* ------------------------------------------------------------- ФОРМЫ */
.form { display: grid; gap: 16px; max-width: 460px; }
.form--wide { max-width: none; }
.field { display: grid; gap: 5px; }
/*
 * Подпись поля — и <label>, и <span class="field__label"> внутри него.
 *
 * Оба вида встречаются законно: где подпись отдельным элементом (тогда
 * label связывается с полем через for), и где сам label обёртка вокруг
 * поля (тогда подпись внутри — отдельным span). Раньше второй вид
 * оформляли чужим классом от списка сессий, и подпись в интеграциях
 * была другого размера и цвета, чем везде.
 */
.field label, .field__label { font-size: 13px; font-weight: 650; color: var(--fg-mute); }

/* Флажок со словами: поле и подпись в строку, а не столбиком */
.check { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.check input { width: 16px; height: 16px; }

/* Отбитая группа полей внутри формы — например настройки под секретами */
.field-group {
  display: grid; gap: 12px;
  border-top: 1px solid var(--hair); padding-top: 14px; margin-top: 4px;
}
/*
 * ═══════════════════════════════════════════════════════════════════
 *  ПОЛЯ ОДЕТЫ САМИ ПО СЕБЕ, А НЕ ПО ОБЁРТКЕ
 * ═══════════════════════════════════════════════════════════════════
 *
 * Здесь стояло «.field input, .field select» — то есть поле выглядело
 * как наше, только если о нём позаботились снаружи. Кто писал экран,
 * не зная про обёртку, получал голое системное поле.
 *
 * Именно это и вышло: поддержка, обращение, системная админка и
 * интеграции написаны с классом form-control, которого в этой таблице
 * нет ВООБЩЕ. Пять экранов подряд стояли без оформления, и заметить
 * это по коду было нельзя — класс выглядит как настоящий.
 *
 * Поэтому одеваем сам элемент. Обёртка .field остаётся, но отвечает
 * теперь только за раскладку: подпись, подсказка, текст ошибки.
 * Новый экран выглядит правильно, даже если про .field не знали.
 *
 * Перечисляем виды полей поимённо: у флажка, переключателя и кнопки
 * своё оформление, и рамка с подкладкой им только мешает.
 */
:where(
  input[type="text"], input[type="email"], input[type="tel"], input[type="url"],
  input[type="number"], input[type="password"], input[type="search"],
  input[type="date"], input[type="datetime-local"], input[type="time"],
  input:not([type]), select, textarea
) {
  font: inherit; font-size: 15px; width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--hair-2); border-radius: var(--r-in);
  background: var(--white); color: var(--fg);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
:where(input, select, textarea):hover:not(:focus) { border-color: var(--accent-line); }
/* Подсказка в поле должна читаться, а не сереть до неразличимости. */
::placeholder { color: color-mix(in srgb, var(--ink) 46%, var(--white)); opacity: 1; }
textarea {
  min-height: 96px; resize: vertical; line-height: 1.5;
}
:where(input, select, textarea):focus {
  outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent;
}
:where(input, select, textarea)[aria-invalid="true"] { border-color: var(--bad); }
.field__err { font-size: 13px; color: var(--bad); font-weight: 600; }
.field__hint { font-size: 13px; color: var(--fg-mute); }
/*
 * Пометка «необязательно» прямо в подписи поля.
 *
 * Звёздочка у обязательных полей работала бы хуже: обязательных здесь
 * четыре из пяти, и помечать надо исключение, а не правило.
 */
.field__opt { font-weight: 400; color: var(--fg-mute); }

.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 560px) { .row2 { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------ КНОПКИ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 10px 18px; border: 1px solid transparent; border-radius: var(--r-in);
  font: inherit; font-size: 14.5px; font-weight: 600; line-height: 1.2;
  text-decoration: none; cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/*
 * Нажатие видно рукой, а не только цветом: кнопка чуть проседает.
 * Полтора процента — предел, за которым это уже трюк, а не отклик.
 */
.btn:active { transform: scale(.985); }
/*
 * Кнопка без модификатора — обычная кнопка, а не системная.
 *
 * База была прозрачной с прозрачной рамкой: <button class="btn"> без
 * модификатора выглядел как текст с отступами, а где ошибались в
 * имени модификатора (btn--p вместо btn--primary) — как серая кнопка
 * браузера. Ошибка в имени не должна раздевать кнопку догола.
 */
.btn { background: var(--white); color: var(--fg); border-color: var(--hair-2); }
.btn:hover { border-color: var(--navy); }

/*
 * Главная кнопка — фирменным цветом, а не пурпуром.
 *
 * Пурпур был акцентом по историческим причинам и спорил с navy в
 * шапке: на экране оказывалось два «главных» цвета, и ни один не
 * выигрывал. Теперь нажимаемое и выбранное — всегда navy.
 */
.btn--primary { background: var(--accent); color: var(--paper); border-color: transparent; box-shadow: var(--sh-1); }
.btn--primary:hover { background: color-mix(in srgb, var(--accent) 88%, var(--white)); box-shadow: var(--sh-2); }
.btn--ghost { background: transparent; color: var(--fg); border-color: var(--hair-2); }
.btn--ghost:hover { border-color: var(--navy); background: color-mix(in srgb, var(--navy) 5%, transparent); }
.btn--danger { background: transparent; color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, var(--paper)); }
.btn--danger:hover { background: color-mix(in srgb, var(--bad) 8%, transparent); }
.btn--sm { padding: 7px 12px; font-size: 13.5px; }
.btn--wide { width: 100%; }
/*
 * Кнопка-ссылка берёт цвет у окружения, а не свой.
 *
 * Стоял жёстко светлый цвет — он подходил тёмной шапке, где эта
 * кнопка появилась впервые («Выйти»). Потом её поставили на белую
 * карточку в системной админке («Сбросить»), и там она стала светло-
 * серой по белому, то есть невидимой.
 *
 * inherit решает это раз и навсегда: в тёмной шапке текст светлый, на
 * карточке тёмный. Цвет задаёт тот, кто знает свой фон.
 */
.btn--link {
  background: none; border: 0; padding: 0; color: inherit;
  font: inherit; font-size: 14px; cursor: pointer; text-decoration: underline;
}

/* -------------------------------------------------------- ВХОД, ФОРМЫ */
.auth {
  min-height: 100vh;
  display: grid; place-items: center;
  padding: 32px 20px;
  background: var(--navy);
}
.auth__box { width: min(440px, 100%); }
.auth__logo { display: flex; align-items: center; gap: 9px; justify-content: center; margin-bottom: 22px; text-decoration: none; color: var(--paper); }
.auth__logo svg { width: auto; height: 24px; display: block; }
.auth__card { background: var(--white); border-radius: 12px; padding: clamp(22px, 4vw, 32px); }
.auth__card h1 { font-size: 23px; }
.auth__sub { color: var(--fg-mute); font-size: 14.5px; margin-top: 8px; }
.auth__note { color: var(--fg-mute); font-size: 13px; line-height: 1.5; margin-top: 12px; }

/* Разделитель «или» между формой и входом через ВКонтакте: черта с
   надписью посередине, без картинок и без лишней разметки. */
.orsep { display: flex; align-items: center; gap: 12px; margin: 22px 0 16px; }
.orsep::before, .orsep::after { content: ''; flex: 1; height: 1px; background: var(--hair); }
.orsep span { color: var(--fg-mute); font-size: 13px; }

/* Синий ВКонтакте — свой, а не accent: кнопка чужой службы должна
   выглядеть чужой, иначе её принимают за наше главное действие. */
.btn--vk { background: #07f; color: #fff; border-color: transparent; gap: 9px; }
.btn--vk:hover { background: #0a6ee0; color: #fff; }
.btn--vk svg { flex: none; }
.auth__foot { margin-top: 18px; text-align: center; font-size: 14px; color: color-mix(in srgb, var(--paper) 62%, var(--navy)); }
.auth__foot a { color: color-mix(in srgb, var(--paper) 82%, var(--navy)); }
.auth .form { max-width: none; margin-top: 20px; }

/* -------------------------------------------------------- СПИСОК СЕССИЙ */
.sess { display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); border-radius: 6px; overflow: hidden; }
.sess__i { background: var(--white); padding: 12px 16px; display: grid; gap: 3px; }
.sess__t { font-weight: 600; font-size: 14.5px; }
.sess__m { font-size: 13px; color: var(--fg-mute); font-variant-numeric: tabular-nums; }
.sess__m code { font-family: var(--mono); font-size: 12.5px; }

.empty { text-align: center; padding: 28px 20px; color: var(--fg-mute); font-size: 14.5px; }

/* ------------------------------------------------------------ ТАРИФЫ */

/*
 * Карточки тарифов. Ширина 250 — при меньшей цена с разрядами
 * («299 900 ₽») переносится на две строки и колонка выглядит сломанной.
 */
.plans { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); align-items: stretch; }

/*
 * Колонка, а не блок, и кнопка прижата книзу через margin-top:auto.
 *
 * Описания у тарифов разной длины, и без этого кнопки «Купить»
 * оказываются на разной высоте — глаз читает это как перекос, даже
 * когда не может объяснить почему. Так они стоят на одной линии при
 * любом тексте.
 */
.plan {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 20px;
  position: relative;
}
.plan__h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.plan__name { font-size: 18px; font-weight: 700; letter-spacing: -.02em; }

/*
 * Приписка «для чего этот тариф» — плашкой с акцентом, а не серой
 * строкой. Это главный ответ карточки: человек выбирает не между
 * пределами, а между «лендинг» и «магазин», и ответ должен читаться
 * первым после названия.
 */
/* Полоса слева убрана здесь по той же причине, что и у плашек: она
   ничего не добавляет к подложке, а край текста уводит от вертикали. */
.plan__sub {
  font-size: 13.5px; line-height: 1.45; color: var(--fg);
  background: color-mix(in srgb, var(--teal) 6%, var(--white));
  border: 1px solid color-mix(in srgb, var(--teal) 18%, var(--white));
  border-radius: var(--r-in);
  padding: 10px 12px; margin-top: 12px; min-height: 56px;
}
.plan--forever .plan__sub {
  background: color-mix(in srgb, var(--paper) 10%, var(--navy));
  border-left-color: color-mix(in srgb, var(--teal) 55%, var(--navy));
  color: var(--paper); min-height: 0;
}

.plan__price {
  font-size: 27px; font-weight: 700; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums; margin-top: 14px; line-height: 1.1;
}
.plan__per  { font-size: 13px; font-weight: 400; color: var(--fg-mute); letter-spacing: 0; }
.plan__note { font-size: 13px; color: var(--fg-mute); margin-top: 4px; font-variant-numeric: tabular-nums; }

/* Что входит. Галочка и прочерк — плашками цвета, а не словами
   «да»/«нет»: колонка из «да, да, нет, да» не читается взглядом. */
.plan__feats { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 7px; }
.plan__feats li { display: grid; grid-template-columns: 16px 1fr; gap: 8px; font-size: 13.5px; align-items: start; }
.plan__feats li::before { content: "✓"; color: var(--ok); font-weight: 700; line-height: 1.45; }
.plan__feats li[data-no]::before { content: "—"; color: var(--hair-2); }
.plan__feats li[data-no] { color: var(--fg-mute); }

.plan__buy { margin-top: auto; padding-top: 18px; display: flex; gap: 8px; flex-wrap: wrap; }
.plan__buy .btn { flex: 1 1 auto; }

/* Текущий тариф. Рамкой, а не заливкой: заливка сделала бы его
   похожим на выделенное предложение, а это просто отметка «вы здесь». */
.plan--current { border-color: var(--ok); box-shadow: 0 0 0 1px var(--ok) inset; }

/*
 * Бессрочный. Тёмная карточка — единственная на странице, и это
 * оправдано: он один такой по сути, а не просто дороже остальных.
 */
.plan--forever { background: var(--navy); border-color: var(--navy); color: var(--paper); }
.plan--forever .plan__sub,
.plan--forever .plan__per,
.plan--forever .plan__note { color: color-mix(in srgb, var(--paper) 62%, var(--navy)); }
.plan--forever .plan__feats li::before { color: color-mix(in srgb, var(--teal) 55%, var(--paper)); }
.plan--forever .plan__feats li[data-no] { color: color-mix(in srgb, var(--paper) 55%, var(--navy)); }
.plan--forever .btn--primary { background: var(--paper); color: var(--navy); }
.plan--forever .btn--primary:hover { background: var(--white); }
.plan--forever .btn--ghost { color: var(--paper); border-color: color-mix(in srgb, var(--paper) 35%, var(--navy)); }
.plan--forever .btn--ghost:hover { background: color-mix(in srgb, var(--paper) 12%, transparent); border-color: var(--paper); }
.plan--forever .pill--ok { background: color-mix(in srgb, var(--teal) 30%, var(--navy)); color: var(--paper); }

/*
 * Бессрочный во всю ширину: слева суть, справа цена и кнопка.
 * На узком экране складывается в одну колонку — цена уходит под
 * перечисление, а не ужимается в полосу рядом с ним.
 */
.plan--wide { padding: 24px; }
.plan__wide { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px; align-items: center; }
.plan__buyside { min-width: 210px; }
.plan__buyside .plan__price { margin-top: 0; }
.plan__feats--row {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  column-gap: 18px; margin-top: 14px;
}
@media (max-width: 720px) {
  .plan__wide { grid-template-columns: 1fr; gap: 18px; }
  .plan__buyside { min-width: 0; }
}

/* Лента «выгодно» в углу карточки */
.plan__flag {
  position: absolute; top: 14px; right: -1px;
  background: var(--accent); color: var(--paper);
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: 3px 10px; border-radius: 20px 0 0 20px;
}

/* ------------------------------------------------- ТАБЛИЦА СВОЙСТВ */

/*
 * Пары «свойство — значение». Числа выравниваются по правому краю и
 * моноширинно: колонка пределов читается сверху вниз, а не по одному
 * значению за раз.
 */
/*
 * ЗАГОЛОВОК СТРАНИЦЫ
 *
 * Не карточка. Заголовок ничего не содержит, кроме себя, и обещать
 * содержимое рамкой ему нечем.
 */
.page { margin-bottom: 20px; }
.page__h { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.page__sub { color: var(--fg-mute); font-size: 14.5px; margin-top: 7px; max-width: 62ch; }
.page__find { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.page__find input { max-width: 280px; }

/* Ссылка «все сайты» в углу заголовка карточки — не кнопка: это
   продолжение чтения, а не действие. */
.card__more { margin-left: auto; font-size: 13.5px; }

.facts { display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); border-radius: var(--r-in); overflow: hidden; }

.facts__i {
  background: var(--white); padding: 10px 14px;
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: baseline;
  font-size: 14px;
}
.facts__k { color: var(--fg); }
.facts__v { color: var(--fg-mute); font-variant-numeric: tabular-nums; text-align: right; }
/*
 * ТРИ СОСТОЯНИЯ, А НЕ ДВА.
 *
 * Было два: «есть» зелёным и «нет» бледно-серым. Серым же пометили и
 * «не хватает» на странице баланса — и самое тревожное слово на
 * экране стало самым незаметным. Отсутствие возможности и нехватка
 * денег — разные вещи: первое просто факт, второе требует действия
 * сегодня.
 */
.facts__v--on  { color: var(--ok); font-weight: 650; }
.facts__v--off { color: var(--hair-2); }            /* нет такой возможности */
.facts__v--bad { color: var(--bad); font-weight: 650; }  /* требует действия */

/*
 * Полоса фактов: три величины в ряд, волосяные разделители между ними.
 *
 * auto-fit, а не fixed 3: на узком экране полоса становится столбцом
 * сама, без медиазапроса, и ни при какой ширине не оставляет сироту в
 * следующем ряду — ради чего всё и затевалось.
 */
.facts--wide {
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  background: var(--hair);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  margin-bottom: 18px;
}
.facts--wide .facts__i {
  display: grid; grid-template-columns: 1fr; gap: 3px;
  align-items: start; padding: 16px 18px;
}
.facts__n { font-size: 13px; color: var(--fg-mute); }
.facts__v--big {
  font-size: 27px; font-weight: 660; letter-spacing: -.03em;
  color: var(--fg); text-align: left; line-height: 1.15;
}
/* Название тарифа — слово, а не число: набирать его в размер суммы
   значит выдавать «Пробный» за величину. */
.facts__v--word { font-size: 19px; letter-spacing: -.02em; }


/* --------------------------------------------------- СТРОКА ОПЕРАЦИИ */

/*
 * Операция: слева описание и подробности, справа сумма и остаток.
 *
 * На узком экране колонки складываются одна под другую, а сумма
 * прижимается влево. Без этого «−15 480 ₽» и «остаток 34 140 ₽»
 * ужимаются в полосу шириной с ладонь и переносятся посреди числа.
 */
.tx { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: center; }
.tx__sum { text-align: right; }
.tx__v { font-size: 17px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tx__v--in { color: var(--ok); }
.tx__rest { font-size: 13px; color: var(--fg-mute); font-variant-numeric: tabular-nums; white-space: nowrap; display: block; }
@media (max-width: 560px) {
  .tx { grid-template-columns: 1fr; gap: 4px; }
  .tx__sum { text-align: left; }
}

/* ------------------------------------------------ ТАБЛИЦА АДМИНКИ */

/*
 * Плотная таблица системной админки — ТЗ §55.
 *
 * Плотная нарочно: сюда приходят СРАВНИВАТЬ строки, а не читать одну.
 * Просторные отступы дали бы восемь строк на экран, и разницу между
 * соседними записями пришлось бы держать в голове.
 *
 * Числа моноширинные (tabular-nums), иначе суммы в столбце не
 * выстраиваются по разрядам и глаз не ловит лишний ноль — а ловить
 * лишний ноль здесь и есть работа.
 */
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th, .tbl td {
  padding: 7px 10px;
  text-align: left;
  border-bottom: 1px solid var(--hair);
  white-space: nowrap;
  vertical-align: top;
}
.tbl th {
  font-weight: 600;
  color: var(--fg-mute);
  font-size: 12px;
  text-transform: lowercase;
  letter-spacing: .01em;
  position: sticky;
  top: 0;
  background: var(--surface);
}
.tbl td { font-variant-numeric: tabular-nums; }
.tbl tbody tr:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.tbl tbody tr:last-child td { border-bottom: 0; }
/*
 * Приглушённая ячейка — пояснение рядом с числом.
 *
 * Классом при таблице, а не общим `.muted`: общий за полгода
 * расползается по всем экранам и перестаёт что-либо значить.
 */
.tbl__quiet { color: var(--fg-mute); }

/* ------------------------------------------------ СОГЛАСИЕ НА СПИСАНИЯ */
/*
 * Требование банка: сумма и периодичность стоят РЯДОМ с галочкой, а
 * не мелким шрифтом внизу страницы. Поэтому блок нарочно заметный —
 * с подложкой и рамкой, а не приписка под кнопкой. Оформление здесь
 * часть смысла: спрятанное согласие не согласие.
 */
.consent {
  margin-top: 18px; padding: 16px;
  border: 1px solid var(--hair); border-radius: 12px;
  background: var(--surface-2, rgba(0,0,0,.02));
}
.consent__box { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.consent__box input { margin-top: 3px; width: 18px; height: 18px; flex: none; }
.consent__list { margin: 12px 0 0 28px; padding: 0; display: grid; gap: 6px; }
.consent__list li { font-size: 13px; color: var(--fg-mute); line-height: 1.45; }
.consent__foot { margin: 12px 0 0 28px; font-size: 13px; color: var(--fg-mute); }
.consent__more { margin-top: 14px; }
.consent__more summary { cursor: pointer; font-size: 14px; color: var(--fg-mute); }
.consent__text { margin-top: 10px; font-size: 13px; line-height: 1.55; color: var(--fg-mute); }

/* --------------------------------------------------- ОТКРЫТЫЕ СТРАНИЦЫ */
.doc { max-width: 760px; }
.doc h1 { margin-bottom: 10px; }
.doc h2 { margin: 28px 0 10px; font-size: 17px; }
.doc p, .doc li { line-height: 1.6; }
.doc ul { margin: 0; padding-left: 20px; display: grid; gap: 8px; }
.doc__lead { font-size: 16px; color: var(--fg-mute); }
.doc__note { font-size: 13px; color: var(--fg-mute); }
.doc__contacts { list-style: none; padding-left: 0; }
.doc__table { width: 100%; border-collapse: collapse; margin-top: 12px; }
.doc__table th, .doc__table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--hair);
  font-variant-numeric: tabular-nums;
}
.doc__table th { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-mute); }

/*
 * Низ карточки, прижатый к её основанию.
 *
 * Карточки в строке тянутся до одной высоты. У короткой это оставляет
 * пустоту снизу, и она читается как недогрузившийся блок. Прижатый к
 * низу хвост превращает пустоту в поле: заголовок вверху, итог внизу.
 *
 * Работает только когда карточка — колонка flex, поэтому правило
 * задаёт и это. Карточкам без .card__foot ничего не меняет: одна
 * колонка flex раскладывается так же, как обычный поток.
 */
.card:has(.card__foot) { display: flex; flex-direction: column; }
.card__foot { margin-top: auto; padding-top: 16px; }

/*
 * Полоса заполнения. Переполнение показываем полной полосой другого
 * цвета, а не обрезанной: обрезанная читается как «ещё есть место».
 */
.gauge { height: 8px; border-radius: 999px; background: var(--hair); overflow: hidden; }
.gauge__fill { height: 100%; background: var(--teal, var(--plum)); border-radius: 999px; }
.gauge__fill--over { background: var(--bad); }

/*
 * СТРОКА «СЛЕВА ТЕКСТ, СПРАВА КНОПКИ», УМЕЮЩАЯ ПЕРЕНОСИТЬСЯ.
 *
 * Такие строки набирались в атрибуте style как «1fr auto». Эта
 * запись не сжимается: колонка кнопок держит свою ширину, и карточка
 * получает неустранимый минимум. На странице сайта это давало 399 px
 * у карточки «Домены» и боковую прокрутку всей страницы на телефоне.
 *
 * Здесь то же самое, но с переносом: на узком экране строка
 * складывается в одну колонку, кнопки уходят под текст и выравниваются
 * влево — прижимать их вправо, когда они одни на строке, незачем.
 */
.rowsplit {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px; align-items: start;
}
.rowsplit__acts { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 560px) {
  .rowsplit { grid-template-columns: 1fr; }
  .rowsplit__acts { justify-content: flex-start; }
}

/*
 * ДЛИННЫЕ ТЕХНИЧЕСКИЕ СТРОКИ ПЕРЕНОСЯТСЯ.
 *
 * Ключ подтверждения домена — тридцать два знака без единого пробела,
 * и браузеру негде его разорвать: он выносит строку за край карточки,
 * а вместе с ней и всю страницу. То же с полным именем TXT-записи и с
 * номерами платежей.
 *
 * anywhere, а не break-all: обычный текст по-прежнему переносится по
 * словам, а рвётся только то, что иначе не помещается вовсе.
 */
code, .mono, .sess__m code { overflow-wrap: anywhere; }

/*
 * И сама карточка не растягивается содержимым.
 *
 * Даже с переносом остаётся что-нибудь неразрывное — длинное имя
 * сайта, адрес почты. Пусть лучше оно обрежется внутри своей карточки,
 * чем растянет страницу и даст боковую прокрутку на телефоне.
 */
.card { min-width: 0; overflow-wrap: break-word; }
.sess__i, .facts__i, .rowsplit { min-width: 0; }

/*
 * ОДНО ДЛИННОЕ СЛОВО НЕ ДОЛЖНО РАСПИРАТЬ СТРАНИЦУ.
 *
 * `main` — ячейка сетки, а у ячейки min-width по умолчанию `auto`: она
 * не может стать уже своего содержимого. Достаточно одного неразрывного
 * куска — адреса с ключом, длинного домена, вставленного токена, — и
 * ужаться не может уже вся страница: за поле выезжает не только он, а
 * весь текст рядом с ним.
 *
 * Так и случилось: в инструкции к автопостингу стоит адрес VK на
 * полтораста знаков, и владелец увидел, что «тексты вылазят за поля».
 *
 * Правило общее, а не для одной страницы, потому что беда общая:
 * длинные строки у нас показываются везде — домены, почты, названия
 * статей, «задано» вместо ключа.
 */
main { min-width: 0; }

/* Полоса «вы смотрите чужой кабинет» — §55.
   Цвет тревожный намеренно: её задача не украшать, а не дать забыть.
   position:sticky, потому что забыть можно и прокрутив страницу вниз. */
.imp {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 16px; background: #7A1F1F; color: #FFF3F0;
  font-size: 13px; line-height: 1.4;
}
.imp b { font-weight: 700; }
.imp__t { flex: 1 1 auto; min-width: 200px; }
.imp__f { flex: none; margin: 0; }
.imp .btn { background: #FFF3F0; color: #7A1F1F; border-color: #FFF3F0; padding: 7px 14px; }

/* ═══════════════════════════════════════════════════════════════════
 *  ВКЛАДКИ РАЗДЕЛОВ
 * ═══════════════════════════════════════════════════════════════════ */

.tabs {
  display: flex;
  align-items: stretch;
  gap: 4px;
  margin: 0 0 18px;
  border-bottom: 1px solid var(--line);
  /*
   * Прокрутка ТОЛЬКО вбок, и вторая ось погашена явно.
   *
   * Здесь стояло одно `overflow-x: auto`, и на плашке вкладок появлялась
   * вертикальная полоса прокрутки. Причина в правиле CSS, которое видно
   * не сразу: когда по одной оси задано `auto`, а по другой оставлено
   * `visible`, вторая ось тоже становится `auto`. Дальше хватало
   * счётчика с отступами, чтобы содержимое переросло строку на пиксель —
   * и браузер честно показывал полосу прокрутки высотой в эту полоску.
   */
  overflow-x: auto;
  overflow-y: hidden;
}
.tabs--sub { margin-top: -6px; }
.tabs__i {
  padding: 9px 14px 11px;
  font-size: 14.5px;
  font-weight: 550;
  color: var(--mut);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.tabs__i:hover { color: var(--ink); }
.tabs__i--on {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
/* Счётчик рядом с названием: сколько там всего, видно не заходя. */
.tabs__n {
  /*
   * inline-block со своими отступами и был тем, что перерастало строку.
   * Выравниваем по середине и не даём влиять на высоту строки.
   */
  display: inline-block;
  vertical-align: middle;
  line-height: 16px;
  min-width: 18px;
  padding: 1px 5px;
  margin-left: 3px;
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  color: var(--mut);
  background: var(--bg);
  border-radius: 20px;
}
.tabs__i--on .tabs__n { color: var(--accent); background: var(--accent-soft); }

/* ═══════════════════════════════════════════════════════════════════
 *  ЗАПИСЬ ВКОНТАКТЕ
 *
 *  Карточка нарочно похожа на запись в сообществе: человек принимает
 *  решение по тому, что увидит его читатель, а не по нашему списку
 *  абзацев. Похожа — не значит подделка: цвета наши, значка ВК нет.
 * ═══════════════════════════════════════════════════════════════════ */

/*
 * По две в ряд. Владелец просил именно две, и он прав: пост ВКонтакте —
 * это колонка текста, и в три она сжимается до нечитаемой ленты.
 * auto-fit с порогом в 320px оставляет одну колонку на телефоне, не
 * заводя отдельного правила под ширину экрана.
 */
.vkgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 16px;
  margin-top: 16px;
}
@media (min-width: 900px) {
  .vkgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.vkp {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.vkp__top {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px 10px;
}
.vkp__ava {
  flex: none;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  font-size: 15px; font-weight: 650;
  color: var(--white);
  background: var(--accent);
  border-radius: 50%;
}
.vkp__who { display: flex; flex-direction: column; min-width: 0; }
.vkp__name {
  font-size: 14.5px; font-weight: 620; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vkp__when { font-size: 12.5px; color: var(--mut); }
.vkp__pill { margin-left: auto; flex: none; }

/*
 * Картинка поста — в своей пропорции, а не подрезанная под 16:9.
 *
 * Здесь стояло aspect-ratio: 16/9 с object-fit: cover. Обложки завода
 * квадратные (1080×1080), и треть каждой уходила под нож — причём
 * именно низ, где у обложки заголовок. Превью показывало не то, что
 * увидит читатель: ВКонтакте картинку не режет.
 *
 * Потолок по высоте оставлен на случай совсем вытянутых картинок: такая
 * заняла бы весь экран и вытолкнула текст поста вниз. До потолка дело
 * доходит редко, и тогда картинка вписывается целиком, а не режется.
 */
.vkp__img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 560px;
  object-fit: contain;
  background: var(--bg);
}
.vkp__text {
  padding: 12px 16px 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink);
  white-space: normal;
  /*
   * Обрезаем восемью строками. Не ради красоты сетки: если карточки
   * разной высоты, глаз ищет, где кончается одна и начинается другая,
   * вместо того чтобы читать. Полный текст — во всплывашке.
   */
  display: -webkit-box;
  -webkit-line-clamp: 8;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vkp__text--full {
  display: block;
  overflow: visible;
  max-width: 62ch;
  padding-bottom: 4px;
}
.vkp__note {
  margin: 10px 16px 0;
  padding: 8px 10px;
  font-size: 13px;
  color: var(--mut);
  background: var(--bg);
  border-radius: var(--r-in);
}
.vkp__foot {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: auto;
  padding: 12px 16px 14px;
}
.vkp__more {
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 550;
  color: var(--accent);
  background: none;
  border: 0;
  cursor: pointer;
}
.vkp__more:hover { text-decoration: underline; }
.vkp__link { font-size: 14px; color: var(--mut); text-decoration: none; }
.vkp__link:hover { color: var(--ink); text-decoration: underline; }

/* Примеры до оплаты — та же карточка, но без тени: это ещё не работа. */
.vkgrid--samples .vkp { box-shadow: none; }

/* ─── всплывашка ─────────────────────────────────────────────────── */

.vkm {
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  padding: 0;
  border: 0;
  border-radius: var(--r);
  box-shadow: var(--sh-2);
  overflow: auto;
  background: var(--white);
}
.vkm::backdrop { background: color-mix(in srgb, var(--navy) 55%, transparent); }
.vkm .vkp { border: 0; box-shadow: none; border-radius: 0; }
.vkm__x { position: sticky; top: 0; z-index: 1; display: flex; justify-content: flex-end; height: 0; }
.vkm__x button {
  margin: 8px 8px 0;
  width: 30px; height: 30px;
  font-size: 20px; line-height: 1;
  color: var(--mut);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 50%;
  cursor: pointer;
}
.vkm__x button:hover { color: var(--ink); }

/* ═══════════════════════════════════════════════════════════════════
 *  КОНТЕНТ-ЗАВОД СТАТЕЙ
 * ═══════════════════════════════════════════════════════════════════ */

/* Поле-галочка: подпись справа, а не над, — иначе она читается как заголовок. */
.field--check {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 18px;
  font-size: 14.5px;
  cursor: pointer;
}
.field--check input { width: 16px; height: 16px; margin: 0; }

/* Несколько узких полей в строку: «от … до …». */
.form--row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0 14px;
}

/* ─── статья целиком: пример на четвёртом шаге и всплывашка ───────── */

.art { max-width: 62ch; }
.art__t {
  margin: 0 0 12px;
  font-size: 22px;
  font-weight: 680;
  line-height: 1.25;
  letter-spacing: -.02em;
  color: var(--ink);
}
.art__b {
  font-size: 15.5px;
  line-height: 1.68;
  color: var(--ink);
}
.art__b img { max-width: 100%; border-radius: var(--r-in); margin: 14px 0; }
/*
 * ═══════════════════════════════════════════════════════════════════
 *  РАЗМЕТКА ВНУТРИ СТАТЬИ
 * ═══════════════════════════════════════════════════════════════════
 *
 * Завод стал отдавать подзаголовки и списки, а стилей на них не было:
 * браузер показывал их своими умолчаниями — крупнее заголовка статьи
 * и с чужими отступами. Выглядело это хуже, чем сплошной текст, ради
 * ухода от которого всё и затевалось.
 *
 * Отступ сверху больше, чем снизу: подзаголовок принадлежит тому, что
 * под ним, а не тому, что над.
 */
.art__b h2 {
  margin: 26px 0 10px;
  font-size: 18px;
  font-weight: 680;
  line-height: 1.3;
  letter-spacing: -.01em;
}
.art__b h3 {
  margin: 20px 0 8px;
  font-size: 16px;
  font-weight: 650;
  line-height: 1.35;
}
.art__b h2:first-child, .art__b h3:first-child { margin-top: 0; }
.art__b p { margin: 0 0 14px; }
.art__b ul, .art__b ol { margin: 0 0 14px; padding-left: 22px; }
.art__b li { margin: 4px 0; }
.art__b li::marker { color: var(--fg-mute); }
.art__b figure { margin: 16px 0; }
.art__b figcaption {
  margin-top: 6px;
  font-size: 13.5px;
  color: var(--fg-mute);
}
/*
 * Описания картинок словами — в примере до запуска мы их не рисуем.
 * Рисовать до оплаты значит платить за каждого любопытного.
 */
.art__pics {
  margin-top: 18px;
  padding: 12px 14px;
  font-size: 14px;
  color: var(--mut);
  background: var(--bg);
  border-radius: var(--r-in);
}
.art__pics ol { margin: 6px 0 0; padding-left: 20px; }
.art--full { max-width: none; }

/*
 * Значок сети. Ростом со строку и цветом текста — он служит опознанию,
 * а не рекламе чужого бренда: фирменные цвета рядом друг с другом
 * превращают список в светофор.
 */
.neti {
  width: 1.05em;
  height: 1.05em;
  vertical-align: -.16em;
  margin-right: 6px;
  flex: none;
}

/* ─── кадры историй: вертикали в ряд ─────────────────────────────── */

/*
 * Ширина колонки — 150px, а не «сколько поместится».
 *
 * Кадр истории вертикальный, 9:16, и при ширине в треть экрана одна
 * штука заняла бы полторы высоты окна. Их смотрят пачкой и сравнивают,
 * значит в ряд должно влезать шесть-семь, а не два.
 */
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px;
  margin-top: 12px;
}
.shots__i { display: flex; flex-direction: column; gap: 6px; }
.shots__i img {
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: var(--r-in);
  background: var(--bg);
  display: block;
}
/*
 * Место будущего кадра — той же формы и того же размера, что готовый.
 * Иначе список прыгает, когда картинка дорисовывается, и человек
 * теряет то, на что смотрел.
 */
.shots__w {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px;
  aspect-ratio: 9 / 16;
  font-size: 13px;
  color: var(--fg-mute);
  background: var(--bg);
  border: 1px dashed var(--hair-2);
  border-radius: var(--r-in);
}
.shots__w--bad { color: var(--bad); border-color: var(--bad); }
.shots__m { font-size: 12.5px; color: var(--fg-mute); }
/*
 * Причина отказа под кадром. Красным, потому что её надо заметить, не
 * наводя курсор: под курсор человек лезет, когда уже заподозрил
 * неладное, а заподозрить должен по строке.
 */
.shots__m--bad { color: var(--bad); }

/* ─── карточки статей: по три в ряд ──────────────────────────────── */

/*
 * Три, а не две, и это отличается от постов ВК намеренно.
 *
 * Пост ВК показывается целиком, и ему нужна ширина колонки текста.
 * Статья в карточке показывается обложкой и парой строк — читать её
 * тут никто не будет, для этого есть «Подробнее». Значит карточка
 * может быть уже, и в ряд их влезает три.
 */
.arts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 16px;
  margin-top: 16px;
}
@media (min-width: 980px) {
  .arts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.artc {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.artc__cover {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--bg);
}
/* Обложки нет — не пустая дыра, а спокойная заглушка с рубрикой. */
.artc__cover--none {
  display: grid;
  place-items: center;
  font-size: 13px;
  color: var(--mut);
  background: var(--accent-soft);
}
.artc__in { display: flex; flex-direction: column; flex: 1; padding: 14px 16px 16px; }
.artc__t {
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 640;
  line-height: 1.32;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.artc__x {
  font-size: 14px;
  line-height: 1.55;
  color: var(--mut);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.artc__meta { margin-top: 10px; font-size: 12.5px; color: var(--mut); }
.artc__foot { display: flex; align-items: center; gap: 12px; margin-top: auto; padding-top: 14px; }
.artc__more {
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 550;
  color: var(--accent);
  background: none;
  border: 0;
  cursor: pointer;
}
.artc__more:hover { text-decoration: underline; }

/* ─── значки площадок ────────────────────────────────────────────── */

/*
 * Серый — не опубликовано, цветной — опубликовано. Так просил владелец,
 * и это правильно: человеку нужен ответ не «вышло ли», а «дошло ли до
 * Хабра».
 *
 * Цвет несёт смысл, поэтому одного цвета мало: у опубликованных значок
 * ещё и плотнее по начертанию, а название площадки лежит в подсказке и
 * в тексте для чтения с экрана. Кто не различает цвета, всё равно
 * поймёт.
 */
/*
 * Значки сетей ВНУТРИ карточки поста.
 *
 * У карточки свои поля по бокам — их держат текст и примечание, — а
 * ряд значков жил на общих правилах и прилипал к левому краю. Отступы
 * те же, что у текста: они читаются как одна колонка.
 */
.marks--inpost { margin: 10px 16px 0; }
/*
 * Тот же ряд значков, но под кадром истории: там он стоит в колонке
 * шириной в полтораста точек, и отчёркивание сверху с двойным отступом
 * съедало бы половину карточки.
 */
.marks--tight { margin-top: 4px; padding-top: 0; border-top: 0; gap: 4px; }
.marks--tight .mark { min-width: 22px; height: 20px; padding: 0 4px; }

.marks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.mark {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  height: 22px;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 550;
  letter-spacing: .02em;
  color: var(--mut);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  cursor: default;
}
.mark--on {
  font-weight: 680;
  color: var(--white);
  background: var(--accent);
  border-color: var(--accent);
}
/*
 * Тот же значок, но ссылкой — когда адрес вышедшей статьи у нас есть.
 *
 * Отличается только курсором и подчёркиванием при наведении: значок и
 * ссылка должны стоять в ряду одинаково, иначе строка площадок
 * запрыгает от того, у какой из них нашёлся адрес.
 */
a.mark { cursor: pointer; text-decoration: none; }
a.mark:hover { text-decoration: underline; }
.mark--bad {
  color: var(--bad);
  background: color-mix(in srgb, var(--bad) 8%, var(--white));
  border-color: color-mix(in srgb, var(--bad) 30%, var(--white));
}

/*
 * Текст только для чтения с экрана.
 *
 * Нужен значкам площадок: цвет несёт смысл, а тем, кто цвета не
 * различает, нужно слово. Не display:none — так его не прочтут вовсе.
 */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Картинка внутри статьи — на месте своего маркера, с подписью. */
.art__b figure { margin: 18px 0; }
.art__b figure img { display: block; width: 100%; border-radius: var(--r-in); }
.art__b figcaption {
  margin-top: 8px;
  font-size: 13.5px;
  color: var(--mut);
}

/* ------------------------------------------------------- АВТОПОСТИНГ */

/*
 * Подзаголовок внутри карточки. Не <h2>: тот уже занят названием
 * карточки, и второй такой же ломает порядок заголовков на странице.
 */
.sub { font-size: 14px; font-weight: 650; margin: 20px 0 8px; }

/*
 * Нумерованная инструкция «как получить доступ».
 *
 * Своим классом, а не `.steps`: тот в платформе означает совсем другое —
 * горизонтальную ленту шагов мастера из кружков-таблеток. Взял бы я
 * его, и пронумерованная инструкция выстроилась бы в строку. Имена,
 * совпадающие по смыслу и расходящиеся по виду, — самая дешёвая ошибка
 * и самая заметная.
 */
.howto { margin: 0 0 4px; padding-left: 22px; }
.howto li {
  font-size: 14px; line-height: 1.6; color: var(--fg-mute);
  margin-bottom: 10px;
  /*
   * `anywhere`, а НЕ `break-word`, и разница здесь решающая.
   *
   * Оба переносят длинное слово, когда оно не влезает в строку. Но
   * `break-word` не уменьшает МИНИМАЛЬНУЮ ширину содержимого — то есть
   * блок продолжает распирать родителя изнутри, и текст выезжает за
   * поле, хотя правило переноса вроде бы стоит. Измерено: с
   * `break-word` содержимое 1017 при поле 892, с `anywhere` — ровно 892.
   */
  overflow-wrap: anywhere;
}
.howto li:last-child { margin-bottom: 0; }

/*
 * Картинки поста в истории — рядком с переносом.
 *
 * Не сетка из равных клеток: картинки у поста разной формы, и
 * растягивать их в квадраты значит показывать человеку не то, что
 * увидят подписчики.
 */
/*
 * Выбор сетей под постом.
 *
 * Строками, а не в ряд: у каждой сети есть вторая строка — цена и вид
 * картинок либо причина, по которой она недоступна. В ряд это не
 * читается, а без второй строки серая галочка превращается в загадку.
 */
.nets { display: grid; gap: 8px; margin-top: 6px; }
.net {
  display: grid; grid-template-columns: auto 1fr; gap: 2px 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--hair); border-radius: var(--r-xs);
  background: var(--panel);
  cursor: pointer;
}
.net input { grid-row: span 2; }
.net__n { font-size: 14px; font-weight: 600; }
.net__w { font-size: 12.5px; color: var(--fg-mute); grid-column: 2; }
/*
 * Недоступная сеть приглушена, но ЧИТАЕМА: её текст — единственное
 * место, где сказано, почему она недоступна. Спрячь его в бледность —
 * и объяснение пропадёт вместе с ним.
 */
.net--off { opacity: .62; cursor: default; }
.net--off .net__n { font-weight: 500; }

/*
 * Схемы к инструкциям.
 *
 * Ширину держим по месту, но не растягиваем сверх собственной: схема на
 * весь экран выглядит плакатом, а нужна она как подсказка сбоку.
 */
.shotbox { margin: 0 0 18px; max-width: 520px; }
.shotbox figcaption {
  font-size: 12.5px; color: var(--fg-mute); margin-top: 6px;
}
.shot {
  width: 100%; height: auto; display: block;
  border-radius: var(--r-xs);
}

.pics { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.pics__i {
  height: 96px; width: auto; max-width: 100%;
  border-radius: var(--r-xs);
  border: 1px solid var(--line);
  object-fit: cover;
}


/* ─────────────────────────────────────────────────────────────────────
   Картинка поста с кнопками — ручной режим завода ВК.

   Кнопки показываются при наведении, но ТОЛЬКО там, где наведение
   вообще бывает. На телефоне hover не наступает никогда, и спрятанные за
   ним кнопки оказались бы недоступны совсем — поэтому там они видны
   всегда.
   ───────────────────────────────────────────────────────────────────── */
.vkpic { position: relative; overflow: hidden; border-radius: 10px; }
.vkpic .vkp__img { display: block; margin: 0; }

/*
 * Пустое место вместо картинки — чтобы кнопкам было где стоять.
 *
 * Пропорция квадратная: ровно столько места займёт нарисованная
 * обложка, и карточка не прыгнет, когда картинка появится.
 */
.vkpic--none {
  aspect-ratio: 1 / 1; max-height: 360px; background: var(--hair);
  /*
   * Столбиком, а не наложением.
   *
   * Кнопки лежат поверх картинки — и в пустой карточке они ложились
   * поверх подписи «Картинки нет», перекрывая её словами. Здесь
   * накладывать не на что, поэтому подпись и кнопки просто стоят друг
   * под другом.
   */
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px;
}
.vkpic__empty { color: var(--fg-mute); font-size: 14px; margin: 0; }

.vkpic__tools { position: absolute; inset: 0; display: flex; gap: 10px;
                align-items: center; justify-content: center; flex-wrap: wrap;
                padding: 12px; opacity: 0; transition: opacity .15s;
                background: color-mix(in srgb, #000 42%, transparent); }
.vkpic:hover .vkpic__tools,
.vkpic:focus-within .vkpic__tools { opacity: 1; }
.vkpic--none .vkpic__tools {
  position: static; inset: auto;
  opacity: 1; background: transparent;
  padding: 0; flex: none;
}

.vkpic__btn { border: 0; border-radius: 8px; padding: 9px 14px; cursor: pointer;
              font: inherit; font-size: 13.5px; background: var(--paper); color: var(--fg); }
.vkpic__btn:hover { background: var(--white); }
.vkpic--none .vkpic__btn { border: 1px solid var(--hair-2); }

/* Корзина — в углу и поодаль от остальных: её нажимают реже всех, а
   последствия у неё самые заметные. */
.vkpic__bin { position: absolute; top: 8px; right: 8px; margin: 0; }
.vkpic__x { border: 0; border-radius: 8px; width: 34px; height: 34px; cursor: pointer;
            font-size: 15px; line-height: 1; background: var(--paper); color: var(--bad); }
.vkpic__x:hover { background: var(--white); }

.vkp__go { margin: 14px 0 0; }
/* Когда пост выйдет — под кнопкой, а не вместо неё: нажатие ставит в
   очередь на его дату, и это надо сказать до нажатия. */
.vkp__gohint { display: block; margin-top: 7px; text-align: center;
               font-size: 12.5px; color: var(--fg-mute); }

/* ─────────────────────────────────────────────────────────────────────
   Окно вопроса: подтвердить платное действие, написать описание.

   Отдельно от .vkm нарочно. У той padding: 0 — внутрь кладут карточку
   поста со своими полями, и лишний отступ там был бы рамкой вокруг
   рамки. Здесь же внутри обычный текст, и без отступов он упирается в
   края: именно так это и выглядело — «колхозно», как сказал владелец.

   Устройство простое: тело с воздухом и подвал с кнопками, отделённый
   волоском. Подвал прижат к низу и не уезжает вместе с текстом.
   ───────────────────────────────────────────────────────────────────── */
.ask {
  width: min(27rem, calc(100vw - 32px));
  padding: 0;
  border: 0;
  border-radius: var(--r);
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 24px 64px color-mix(in srgb, var(--navy) 22%, transparent),
              0 2px 8px color-mix(in srgb, var(--navy) 10%, transparent);
}
.ask::backdrop { background: color-mix(in srgb, var(--navy) 55%, transparent); }

/* Крестик поверх содержимого, а не в потоке: иначе он отодвигает заголовок. */
.ask__x { position: absolute; top: 10px; right: 10px; margin: 0; }
.ask__x button {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  font-size: 20px; line-height: 1;
  color: var(--fg-mute);
  background: transparent;
  border: 0; border-radius: var(--r-xs);
  cursor: pointer;
}
.ask__x button:hover { background: var(--panel); color: var(--fg); }

.ask__body { padding: 28px 28px 22px; }

.ask__h {
  margin: 0 0 8px;
  font-size: 1.15rem; font-weight: 650; letter-spacing: -0.01em;
  /* Место под крестик: заголовок не должен подлезать ему под руку. */
  padding-right: 28px;
}
.ask__lead { margin: 0; color: var(--fg-mute); font-size: 14.5px; line-height: 1.55; }

/*
 * Цена — отдельной плашкой, а не строкой в абзаце.
 *
 * Это единственное, ради чего окно вообще открылось: человек решает,
 * тратить ли деньги. В сплошном тексте цифра теряется.
 */
.ask__price {
  margin: 18px 0 0;
  padding: 11px 14px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-in);
  background: var(--accent-soft);
  color: var(--fg);
  font-size: 14px; font-weight: 550;
}

.ask__note { margin: 14px 0 0; color: var(--fg-mute); font-size: 13px; line-height: 1.5; }

.ask__label {
  display: block; margin: 20px 0 7px;
  font-size: 13px; font-weight: 550; color: var(--fg);
}
.ask__area {
  width: 100%;
  padding: 11px 13px;
  font: inherit; font-size: 14.5px; line-height: 1.5;
  color: var(--fg);
  background: var(--surface);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-in);
  resize: vertical;
}
.ask__area::placeholder { color: color-mix(in srgb, var(--fg-mute) 70%, transparent); }
.ask__area:focus {
  outline: 0;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.ask__foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 16px 28px 20px;
  border-top: 1px solid var(--hair);
  background: color-mix(in srgb, var(--panel) 55%, var(--surface));
  border-radius: 0 0 var(--r) var(--r);
}
.ask__foot form { margin: 0; }

@media (max-width: 480px) {
  .ask__body { padding: 24px 20px 18px; }
  .ask__foot { padding: 14px 20px 18px; }
  /* На узком кнопки в строку не помещаются — ставим их столбиком. */
  .ask__foot { flex-direction: column-reverse; }
  .ask__foot .btn { width: 100%; }
}

@media (hover: none) {
  .vkpic__tools { opacity: 1; background: color-mix(in srgb, #000 30%, transparent); }
}

/* ─────────────────────────────────────────────────────────────────────
   Предложение привязать ВКонтакте — на главной кабинета.

   Отдельный оттенок, а не «внимание»: это не беда и не ошибка, а
   совет. Покрась его как предупреждение — и человек перестанет
   отличать его от настоящих предупреждений, которые рядом.
   ───────────────────────────────────────────────────────────────────── */
.note--vk {
  border-color: color-mix(in srgb, #07f 26%, var(--surface));
  background: color-mix(in srgb, #07f 5%, var(--surface));
  align-items: flex-start;
}
.note--vk .note__go { display: flex; gap: 8px; align-items: center; flex: none; }
.note--vk .btn--vk { gap: 7px; }

@media (max-width: 640px) {
  /* На узком кнопки уезжают под текст, а не жмутся к нему. */
  .note--vk { flex-direction: column; }
  .note--vk .note__go { width: 100%; }
  .note--vk .note__go .btn { flex: 1; justify-content: center; }
}

/* Кнопки подключения сети — рядом, с пояснением под ними. */
.conn { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.conn__hint { margin: 10px 0 0; color: var(--fg-mute); font-size: 13px; line-height: 1.5; }

/* Свои картинки проекта — сетка карточек с подписью и кнопкой «убрать». */
.assets { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 14px; }
.assets__i { margin: 0; width: 132px; }
.assets__i img { width: 132px; height: 96px; object-fit: cover; border-radius: 8px;
                 background: var(--panel); display: block; }
.assets__i figcaption { font-size: 12px; color: var(--fg-mute); margin-top: 6px;
                        overflow-wrap: anywhere; }
.linkish { background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
           color: var(--accent); text-decoration: underline; }

/*
 * Форма переключения доступа. Скрыта: её отправляет ссылка «выключить».
 * Класс нужен, чтобы ссылка находила именно ЕЁ — рядом в строке стоит
 * форма удаления, и «первая форма» указывала бы уже не туда.
 */
.net__toggle { display: none; }

/*
 * «Выбрать все / убрать все» над списком сетей. Появляется от трёх
 * доступных целей: раньше кнопка — шум, позже отметка руками надоедает.
 */
.nets__all { display: flex; gap: 8px; align-items: center; margin-top: 6px;
             font-size: 13px; }
.nets__sep { color: var(--fg-mute); }
