/* Swage landing + shared page stylesheet (U11, docs/handoff/U11-dev.md).
   DECISIONS 2026-09-21: "файл стиля один и общий для лендинга и рабочих
   страниц" -- этот файл рассчитан на переиспользование в самом стенде,
   поэтому классы называются по смыслу компонента (.card, .format-row,
   .stamp-wrap), а не по месту на странице. Токены брендбука (brand/tokens.css)
   подключаются ОТДЕЛЬНЫМ файлом раньше этого, здесь только то, что
   строже брендбука не определяет заново. */

* { box-sizing: border-box; min-width: 0; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  overflow-x: hidden;
}
img, svg { max-width: 100%; }
a { color: var(--water); }
h1, h2, h3 { line-height: 1.2; margin: 0 0 10px; }
p { margin: 0 0 12px; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.icon { width: 16px; height: 16px; display: inline-block; vertical-align: -3px; flex: none; }
.icon-lg { width: 22px; height: 22px; flex: none; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* --- Палитра данных, задача U11: цвета берутся из классов чертежа,
   не выдуманы для лендинга. Общий словарь для превью, схемы и иконок
   форматов, псевдонимы поверх уже проверенных на контраст токенов
   брендбука (BRANDBOOK.md, §7 «Состояния» -- --ok/--warn/--bad уже
   прошли AA на --bg и --card в обеих темах; --water и --copper — это
   действующие текстовые/акцентные цвета интерфейса). Контраст пар
   ниже посчитан на fill/stroke поверх --bg и --card (WCAG формула
   относительной яркости), тела результатов -- в Result. */
/* Round 5, п.2: owner согласился с находкой -- медь и данные были
   смешаны (--data-road был псевдонимом --copper). Медь теперь ТОЛЬКО
   у знака, печати, главной кнопки и орнамента; у дорог -- свой цвет,
   не медь и не жёлтый (жёлтый/янтарь -- ТОЛЬКО у потери, см. --warn
   ниже и Result). Новый тон -- тёмно-бирюзовый, не пересекается ни
   с одной уже занятой ролью (медь/вода/зелень-ок/красный-bad/янтарь-
   потеря/охра-зонирование). Контраст -- в Result. */
:root {
  --data-road: #2D6E6E;              /* дорога/трасса -- CAD-класс E_TRN_Roads_*, СВОЙ цвет, не медь */
  --data-water: var(--water);       /* вода -- реки, пруды, ливневые сети */
  --data-building: var(--text);     /* здания и сооружения */
  --data-label: var(--text-secondary); /* подписи и текстовые слои */
  --data-zoning: var(--ornament);   /* зонирование, прочая инфраструктура */
  /* U22, п.1: заливка под тегом/иконкой формата -- нужна ТОЛЬКО светлой
     теме (там же, где владелец увидел «блёкло»), поэтому по умолчанию
     прозрачна и тёмную тему не трогает. */
  --ok-fill: transparent; --warn-fill: transparent; --bad-fill: transparent;
}
:root[data-theme="dark"] { --data-road: #5FB3B3; }

/* Round 4, п.11: owner -- жёлтый на чёрном («3355») «вырви глаз».
   #EBC04F -- родной --warn тёмной темы брендбука (10.25:1 на --bg,
   9.17:1 на --card), контраст с запасом, но чистый насыщенный жёлтый
   на почти чёрном режет глаз именно за счёт насыщенности, не контраста
   -- контраст можно снизить и всё равно остаться выше 4.5:1. Заменён
   на более тёплый, менее насыщенный янтарь той же ролью (только для
   тёмной темы; светлая и «paper» тем не касается). Числа контраста --
   в Result. Это отступление от tokens.css (сам файл, "generated...
   do not edit", не тронут) -- переопределение только здесь, на
   лендинге, до решения владельца по брендбуку. */
:root[data-theme="dark"] {
  --warn: #D9A441;
}

/* Второе уточнение владельца поверх Round 5, п.1 (первое, «light =
   бывший paper», отменено самим владельцем -- он имел в виду не
   ЗАМЕНУ кремового, а добавление контраста К кремовому). Итог:
   светлая тема остаётся узнаваемо кремовой (фон чуть светлее и
   холоднее прежнего #FBF8F1, не нейтрально-белый), но текст,
   вторичный текст, акценты, разделитель и рамка поля -- заметно
   темнее/плотнее версии из brand/tokens.css. «paper» и
   `index-paper.html` не существуют. Точные значения до/после и
   контраст каждой пары -- в Result. Отступление живёт только здесь,
   в swage.css (brand/tokens.css, "generated... do not edit",
   не тронут) -- решение о брендбуке за владельцем. */
:root[data-theme="light"] {
  --bg: #F7F4EC; --card: #FFFFFF; --text: #17140F; --text-secondary: #55524C;
  --border-input: #7A776F; --divider: #A8A59C; --water: #17497E;
  --row-selection: #DBE5EF; --search-highlight: #FFF0A8; --search-highlight-alt: #FFF0A8;
  --copper: #8A4A2A;
  /* U22, п.1: владелец сравнил матрицу форматов в обеих темах -- тёмная
     «хорошие и наглядные цвета», светлая «блёклые и невыразительные».
     Прежние --ok/--warn/--bad (#255A30/#5E3C00/#74221F) проходили
     контраст с большим запасом (7.4:1/9.0:1/9.6:1 на --bg по формуле
     WCAG, см. Result), но были затемнены настолько, что потеряли
     насыщенность исходного семейства тона (зелёный/янтарный/красный) --
     warn читался скорее коричневым, чем янтарём. Новые значения ближе
     по тону к тёмной теме (--ok:#6CA176, --warn:#D9A441, --bad:#E06A5F)
     и всё ещё держат 5.0-6.3:1 на --card и 4.3-5.2:1 на своей заливке
     (--*-fill, ниже) -- числа в Result. */
  --ok: #1B7A3C; --warn: #8F5600; --bad: #B23126;
  --ok-fill: #DFF1E3; --warn-fill: #FBEDD0; --bad-fill: #FBE1DE;
  --ornament: #B8895F; color-scheme: light;
}

/* --- Айдентика: орнамент-подложка (Round 2, owner: «больше айдентики,
   символизма и цветов»). Тот же ассет, что и на обложке отчёта
   (brand/svg/ornament/contours.svg, brand/BRANDBOOK.md: "обложка тёмная,
   медные горизонтали 35%"). На обложке ассет стоит один раз и держит
   35% -- здесь он живёт ЗА текстом всей верхней части страницы, поэтому
   непрозрачность взята заметно ниже (12%), чтобы не спорить с текстом;
   отступление и его причина названы в Result. */
/* Round 5, п.4: было 900px -- заметно короче героя с его большой
   панелью, поэтому орнамент читался как «обрубленный» после первого
   экрана. Поднято до 1300px, чтобы захватить герой целиком и часть
   первых шагов. Дополнительные повторы -- ниже (.ornament-band,
   .ornament-host). */
.ornament-wash {
  position: absolute; top: 0; left: 0; right: 0; height: 1300px;
  overflow: hidden; z-index: 0; pointer-events: none;
  color: var(--copper); opacity: .12;
}
.ornament-wash svg { width: 100%; height: 100%; display: block; }
header.shapka, .rail, main, footer.podval { position: relative; z-index: 1; }

/* Повтор орнамента дальше по странице (Round 5, п.4): полноширинная
   лента между разделами (не декорирует конкретные данные, в отличие
   от бывшей медной полосы Round 4 -- здесь и не должна: орнамент,
   не геометрия чертежа) и вставки внутри «Скоро»/подвала. Тот же
   приём просвечивания токенами, что и у превью: цвет читается по
   текущей теме. */
.ornament-band {
  position: relative; height: 220px; overflow: hidden; opacity: .14;
  color: var(--copper); border-top: var(--divider-width) solid var(--divider);
  border-bottom: var(--divider-width) solid var(--divider);
}
.ornament-band svg { width: 100%; height: 520px; display: block; margin-top: -140px; }
.ornament-host { position: relative; overflow: hidden; }
.ornament-inline {
  position: absolute; inset: 0; z-index: 0; opacity: .12; color: var(--copper);
  pointer-events: none;
}
.ornament-inline svg { width: 100%; height: 100%; display: block; }
#news.ornament-host > *:not(.ornament-inline),
footer.ornament-host .podval-inner { position: relative; z-index: 1; }
@media (prefers-color-scheme: dark) {}
/* U23: владелец -- «на светлой теме всё-таки тяжело читать на фоне
   изолиний». Round 5, п.4 подняло непрозрачность до 24%, чтобы вылечить
   «давящий» ровный кремовый фон -- но тот же орнамент лежит ПОД текстом
   героя, и на светлом фоне тёмная медь (--copper: #8A4A2A, темнее
   версии тёмной темы) читается плотнее, чем на тёмном фоне светлая.
   Снижено до 8% -- линии остаются видимой текстурой (не исчезли), но
   текст поверх них читается как на обычной бумаге. Та же причина
   касается .ornament-inline (новости, подвал) -- не только .ornament-wash,
   поэтому снижена и она. .ornament-band тут не трогается: лента пуста
   (текста поверх неё нет, см. комментарий выше), контраста с текстом
   не бывает ни в одной теме. */
:root[data-theme="light"] .ornament-wash { opacity: .08; }
:root[data-theme="light"] .ornament-inline { opacity: .07; }

/* Round 4, п.5: узкая медная полоса реальных данных под героем убрана --
   owner прочитал её как глитч («что это?»). На её месте -- пример
   обратного хода (см. .reverse-example ниже), не декоративная полоса. */
.reverse-example {
  max-width: 1180px; margin: 28px auto 0; padding: 16px 22px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card);
}
.reverse-icon { color: var(--text-secondary); flex: none; }
.reverse-example p { margin: 0; flex: 1 1 260px; font-size: 15px; color: var(--text-secondary); }
.reverse-example b { color: var(--text); }
/* Round 5, п.2: стрелка -- не бренд и не данные, нейтральный цвет. */
.reverse-arrow { color: var(--text-secondary); flex: none; }

/* --- Шапка ---
   Round 2, пункт 7: «сделать шапку явно стилизованной» -- полупрозрачная
   плашка с размытием фона (backdrop-filter), а не просто заливка var(--bg).
   Отступление от брендбука (шапка там сплошная, без прозрачности),
   названо в Result. Запасной вариант для браузеров без backdrop-filter --
   обычная почти-непрозрачная заливка (без него читается так же). */
/* Round 4, п.3: строка бара -- на всю ширину окна (это и держит вид
   стеклянной панели), а СОДЕРЖИМОЕ -- в том же контейнере, что и
   main (max-width 1180 + отступы), иначе на широком экране лого и
   меню упираются в самые края, а в центре пусто. */
header.shapka {
  height: var(--header-height);
  border-bottom: var(--divider-width) solid var(--divider);
  position: sticky; top: 0; z-index: 20;
  background: rgba(251, 248, 241, .86);
}
:root[data-theme="dark"] header.shapka, :root:not([data-theme="light"]) header.shapka {
  background: rgba(26, 24, 25, .82);
}
@supports (backdrop-filter: blur(1px)) {
  header.shapka { backdrop-filter: blur(10px) saturate(1.3); }
}
.shapka-inner {
  max-width: 1180px; margin: 0 auto; padding: 0 24px; height: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.shapka-left { display: flex; align-items: center; gap: 40px; min-width: 0; flex: 1 1 auto; }
/* Round 4, п.4: лого было мельче навигации рядом -- поднято, чтобы
   знак и слово читались как главный элемент шапки, не наравне со
   строчными пунктами меню. */
/* Round 5, п.3: owner -- «стесняемся знака». Поднято ещё раз (было 36px
   после Round 4). */
.lockup { height: 44px; width: auto; display: block; flex: none; }
.lockup .swage-mark { color: var(--copper); }
.lockup .swage-word { color: var(--text); }
nav.glavnaya { display: flex; gap: 22px; align-items: center; white-space: nowrap; overflow-x: auto; min-width: 0; }
nav.glavnaya a {
  color: var(--text-secondary); text-decoration: none; font-size: var(--t4);
  padding: 6px 2px; border-bottom: 2px solid transparent; transition: color .12s, border-color .12s;
}
nav.glavnaya a:hover { color: var(--text); }
/* Round 5, п.2: текущая страница -- не медь (медь только знак/печать/
   кнопка/орнамент); текст + подчёркивание сами по себе несут состояние. */
nav.glavnaya a[aria-current="page"] { color: var(--text); border-color: var(--text); font-weight: 600; }
.shapka-right { display: flex; align-items: center; gap: 16px; flex: none; }
.voyti { color: var(--text-secondary); text-decoration: none; font-size: var(--t4); }
.voyti:hover { color: var(--text); text-decoration: underline; }
.cta-header {
  background: var(--copper); color: #fff; text-decoration: none;
  padding: 9px 18px; border-radius: var(--button-radius); font-size: var(--t4); font-weight: 600;
  transition: filter .12s;
}
.cta-header:hover { filter: brightness(1.08); }
@media (max-width: 720px) {
  header.shapka { height: auto; }
  .shapka-inner { padding: 10px 14px; flex-wrap: wrap; row-gap: 8px; }
  nav.glavnaya { gap: 14px; }
  .cta-header { display: none; }
}

/* --- Правая полоса шагов (owner, 25.09: «весь процесс как длинный
   вертикальный лендинг... справа отметки шагов — содержания»).
   Работает БЕЗ JS: обычные якорные ссылки. JS (внизу страницы) только
   подсвечивает активный пункт и отмечает пройденные через
   IntersectionObserver -- прогрессивное улучшение, не условие работы.
   Round 6 (owner: «рельс справа мелковат — надо сделать заметнее,
   не прятать его»): было -- точки 7px и подпись 12px, терялось рядом
   с орнаментом. Теперь -- кольца с номером (тот же мотив, что
   у .step-num шагов и печати «сверено»), подпись 15px, сплошная линия-
   трек между кольцами, карточная подложка с размытием, чтобы рельс
   читался поверх орнамента-подложки, а не спорил с ним. Медь здесь
   НЕ используется (owner, round 6: медь -- только знак/печать/кнопка/
   орнамент) -- состояние несёт сам текст/кольцо через var(--text),
   тем же приёмом, что уже стоит на nav.glavnaya a[aria-current]. */
.rail {
  position: fixed; right: 20px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; z-index: 15;
  background: rgba(251, 248, 241, .86); border: var(--divider-width) solid var(--divider);
  border-radius: 14px; padding: 14px 14px 14px 12px;
}
:root[data-theme="dark"] .rail, :root:not([data-theme="light"]) .rail {
  background: rgba(26, 24, 25, .82);
}
@supports (backdrop-filter: blur(1px)) {
  .rail { backdrop-filter: blur(10px) saturate(1.3); }
}
/* Линия-трек позади колец: один непрерывный штрих от центра первого
   кольца до центра последнего. Кольца непрозрачны (background: var(--card)
   в .rail-marker), поэтому линия видна только МЕЖДУ ними, как и задумано. */
.rail-list { position: relative; display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
/* U16, п.4 (owner: «криво, а почему кружочки выбраны?»): трек стоял
   мимо центра колец. .rail-item несёт padding 6px 4px, .rail-marker --
   26px, значит центр кольца лежит в 4px(padding)+13px(половина
   диаметра)=17px от левого края списка, а первая/последняя строки
   начинаются в 6px(padding-top)+13px=19px от верхнего/нижнего края --
   было 13px/17px, трек проходил мимо. Исправлено расчётом, не на
   глаз, проверено снимком. */
.rail-list::before {
  content: ''; position: absolute; left: 16px; top: 19px; bottom: 19px; width: 2px;
  background: var(--divider); z-index: 0;
}
.rail-item {
  position: relative; z-index: 1; display: flex; align-items: center;
  text-decoration: none; color: var(--text-secondary); padding: 6px 4px;
  transition: color .15s;
}
.rail-marker {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px; font-family: var(--font-mono);
  border: 2px solid var(--text-secondary); color: var(--text-secondary);
  background: var(--card); transition: background .15s, border-color .15s, color .15s;
}
.rail-label {
  margin-left: 10px; font-size: 15px; line-height: 1.2; white-space: nowrap;
  transition: max-width .15s, opacity .15s, margin-left .15s;
}
.rail-item:hover { color: var(--text); }
.rail-item:hover .rail-marker { border-color: var(--text); color: var(--text); }
/* Пройденный пункт: кольцо заполнено абрисом var(--text), не медью --
   «отмечен как пройденный», не «активен». */
.rail-item.done .rail-marker { border-color: var(--text); color: var(--text); }
/* Активный пункт: заливка, а не абрис -- явно другое состояние, плюс
   жирная подпись (owner, round 6: «активный пункт -- залитый маркер
   и жирная подпись»). */
.rail-item.active { color: var(--text); }
.rail-item.active .rail-label { font-weight: 700; }
.rail-item.active .rail-marker {
  background: var(--text); border-color: var(--text); color: var(--card);
}
/* 1280 и шире: полный рельс, числа и подписи видны всегда (owner,
   round 6: «не прятать его»). Колонку контента сужает --content-width
   выше, если естественного поля не хватает. */
/* 1024--1279: компактный рельс -- только числа, подпись выезжает
   по наведению/фокусу (не по умолчанию) -- ширины колонки 1180px
   рядом с полным рельсом тут уже не хватает, но прятать пункты целиком
   владелец запретил явно. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .rail { padding-right: 10px; }
  .rail-label {
    max-width: 0; opacity: 0; overflow: hidden; margin-left: 0;
  }
  .rail-item:hover .rail-label, .rail-item:focus .rail-label, .rail-item:focus-visible .rail-label {
    max-width: 160px; opacity: 1; margin-left: 10px;
  }
}
/* Ниже 1024 у рельса просто нет места рядом с колонкой контента, и это
   уже не «стол» в смысле этой задачи -- телефон (>=640) держит свой
   отдельный приём разметки без рельса. */
@media (max-width: 1023px) { .rail { display: none; } }

/* Round 6, п.1 «рельс справа мелковат»: полный рельс (числа + подписи)
   с 1280px нуждается в месте, которого у колонки 1180px рядом с рельсом
   просто нет (на 1280 естественное поле -- 50px на сторону, рельсу
   нужно больше). Ширина колонки -- переменная, а не число в трёх
   местах: в узком диапазоне, где рельс включён, но естественного поля
   не хватает (1280--1599), колонка сама сужается и освобождает правое
   поле под рельс, вместо того чтобы рельс наезжал на текст. От 1600
   естественного поля уже достаточно, колонка возвращается к 1180. */
/* Компактный рельс (1024--1279, только числа) уже у́же, но своё поле ему
   тоже нужно -- на 1024 колонка иначе становится вровень с окном
   (max-width её просто не ограничивает), и кольца рельса легли прямо
   на правый край превью «Результат» (найдено на снимке 1024-light,
   round 6, до правки). */
:root { --content-width: 1180px; }
@media (min-width: 1024px) and (max-width: 1279px) { :root { --content-width: 860px; } }
@media (min-width: 1280px) and (max-width: 1599px) { :root { --content-width: 1000px; } }
main { max-width: var(--content-width); margin: 0 auto; padding: 0 24px; }
section { padding: 64px 0; border-top: var(--divider-width) solid var(--divider); position: relative; }
/* Round 5, п.5: «длинная распечатка из плоттера» -- owner's own words
   for one flat --bg the whole way down. Чередование земли: некоторые
   разделы берут --card (чуть другой тон, не новый цвет) на всю ширину
   окна. Первая попытка была box-shadow 0 0 0 100vmax -- нашлась
   настоящая ошибка при проверке: vmax здесь считается от БОЛЬШЕЙ
   стороны, а у длинной страницы это высота (7000+ px на реальном
   снимке), и тень такого радиуса кладёт Chromium настолько, что герой
   и несколько следующих секций переставали прорисовываться на снимке
   вовсе -- не «страница сломалась», а найдено и заменено ДО показа,
   см. Result. Теперь -- обычный приём «выход за контейнер» через
   отрицательные поля по ширине (vw, не vmax) и компенсирующий
   padding, что при любой высоте страницы остаётся в разумных пределах
   1440px, а не 7000+. */
.section-alt, .dark-band {
  margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
  padding-left: max(24px, calc((100vw - var(--content-width)) / 2 + 24px));
  padding-right: max(24px, calc((100vw - var(--content-width)) / 2 + 24px));
}
.section-alt { background: var(--card); }
section:first-of-type { border-top: none; }
/* Round 5, п.6: кикер и заголовок раздела были мелкими рядом с герой-
   кеглем h1 -- шкала брендбука (--t1=22px) рассчитана на плотные
   интерфейсные экраны, не на длинный лендинг с воздухом между
   разделами. Кикер -- крупнее и жирнее, заголовок -- отдельный шаг
   между --t1 и --hero, не сам --t1. */
.section-kicker {
  color: var(--copper); font-size: 15px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; margin: 0 0 10px;
}
.section-head { max-width: 720px; margin: 0 0 32px; }
.section-head h2 { font-size: clamp(28px, 3.4vw, 40px); }
.section-head p { color: var(--text-secondary); font-size: var(--t3); }
/* Акцент раздела -- цвет из палитры данных, свой на каждый смысловой
   блок (Round 2, п.3: «толкнуть палитру сильнее»). Медь остаётся
   умолчанием там, где кикер не переопределён явно (Сверка -- ядро
   печати, поэтому у неё нет своего цвета, только медь/печать). */
.section-kicker.c-water { color: var(--data-water); }
.section-kicker.c-zoning { color: var(--data-zoning); }
.section-kicker.c-alert { color: var(--data-alert); }
.section-kicker.c-ok { color: var(--ok); }
.section-kicker.c-label { color: var(--data-label); }
.mini-head { font-size: 16px; font-weight: 600; margin: 0 0 10px; }

/* --- Герой: воронка начинается сразу с конвертации ---
   Fix round (коорд-2): раньше герой был двумя равными колонками
   (текст | маленькая карточка превью), и текстовая колонка держала
   ЕЩЁ одну карточку-дропзону -- рядом с самим превью-«карточкой» это
   читалось как два места для файла. Теперь текстовый блок и дропзона
   -- один узкий столбец сверху (одна дропзона), а само превью
   источник->результат -- отдельный блок на всю ширину ПОД ним, и он
   и есть тезис страницы, а не боковая иллюстрация. */
.hero { padding-top: 48px; position: relative; overflow: hidden; }
.hero-top { position: relative; z-index: 1; }
/* Round 4, п.2: на широком экране узкая колонка (680px по центру)
   читалась как страница, сжатая до ширины телефона, и подпись под
   числом переносилась по словам. Герой теперь использует всю ширину
   главной колонки: текст и дропзона слева, крупные числа и печать --
   в отдельной колонке справа, а не под текстом в один столбец. */
.hero-top {
  display: grid; grid-template-columns: 1.5fr 1fr; gap: 48px; align-items: start;
  margin: 0 0 32px;
}
.hero h1 { font-size: var(--hero); }
.hero .lead { font-size: var(--t2); color: var(--text-secondary); }

.hero-side {
  display: flex; flex-direction: column; align-items: flex-start; gap: 20px;
  padding: 24px; border: var(--divider-width) solid var(--divider);
  border-radius: var(--radius-card); background: var(--card);
}
/* Числа крупным Plex Mono там, где они несут мысль (Round 2, п.6). */
.hero-stats { display: flex; flex-direction: column; gap: 18px; }
.stat { display: flex; flex-direction: column; }
.stat-num { font-size: 44px; font-weight: 600; line-height: 1; color: var(--ok); }
.stat.stat-warn .stat-num { color: var(--warn); }
/* Round 4, п.2: было max-width:22ch -- именно оно и переносило подпись
   по словам в узкой колонке. Убрано: колонка своя, широкая, перенос
   подписи больше не нужно сдерживать шириной строки текста. */
.stat-cap { font-size: 14px; color: var(--text-secondary); margin-top: 4px; white-space: nowrap; }
/* Round 5, п.3: печать поднята с 84 до 120px -- заметный элемент
   первого экрана, а не мелкая деталь карточки. */
.hero-seal { width: 120px; height: 120px; color: var(--text); align-self: center; }
.hero-seal svg { width: 100%; height: 100%; display: block; }
/* Крупный знак-водяной знак поверх орнамента (Round 5, п.3). Только
   декоративный слой -- aria-hidden, под текстом по z-index. */
.hero-mark-bg {
  position: absolute; top: -40px; right: -60px; width: 480px; height: 480px;
  color: var(--copper); opacity: .1; z-index: -1; pointer-events: none;
}
.hero-mark-bg svg { width: 100%; height: 100%; display: block; }
@media (max-width: 1100px) { .hero-mark-bg { width: 320px; height: 320px; right: -80px; } }
@media (max-width: 640px) { .hero-mark-bg { display: none; } }
@media (max-width: 1100px) {
  .hero-top { grid-template-columns: 1fr; }
  .hero-side { flex-direction: row; align-items: center; justify-content: space-between; }
  .hero-stats { flex-direction: row; gap: 28px; }
  .stat-cap { white-space: normal; }
}
@media (max-width: 640px) {
  .hero-side { flex-direction: column; align-items: flex-start; }
}

.hero-cta { display: flex; gap: 14px; flex-wrap: wrap; margin: 20px 0 8px; }
.btn-primary, .btn-secondary {
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  font-size: var(--t3); font-weight: 600; padding: var(--button-pad);
  border-radius: var(--button-radius); min-height: var(--button-min-height);
}
.btn-primary { background: var(--copper); color: #fff; border: none; }
.btn-primary:hover { filter: brightness(1.08); }
.btn-secondary { background: transparent; color: var(--text); border: var(--button-border) solid var(--border-input); }
.btn-secondary:hover { background: var(--row-selection); }
.hero-note { font-size: var(--t5); color: var(--text-secondary); margin-bottom: 18px; }
/* U13 п.6: короткая строка "для кого", между лидом и кнопками. */
.hero-who { font-size: var(--t5); color: var(--text-secondary); margin: -6px 0 4px; }
/* U13 п.8: подпись источника чисел, под парой hero-stats. */
.hero-stats-note { font-size: 13px; color: var(--text-secondary); margin: 6px 0 0; }

/* U13 п.1: переключатель «до запуска». По умолчанию <html> несёт класс
   prelaunch (владелец, 01.10: лендинг выходит раньше рабочей части) --
   герой зовёт подписаться, а не загрузить, а дропзона помечена примером.
   Сняв класс с <html>, получаем сегодняшнее поведение (загрузка как
   основная кнопка, дропзона кликабельна) без правки разметки. */
.btn-primary-prelaunch { display: none; }
.prelaunch .btn-primary-live { display: none; }
.prelaunch .btn-primary-prelaunch { display: inline-flex; }
.dropzone-title-prelaunch { display: none; }
.prelaunch .dropzone-title-live { display: none; }
.prelaunch .dropzone-title-prelaunch { display: block; }
.prelaunch .dropzone { cursor: default; }
.prelaunch .dropzone select { pointer-events: none; }

/* Одна дропзона на страницу: компактная полоса, не вторая карточка
   такого же веса, как превью ниже. */
.dropzone {
  border: 1.5px dashed var(--border-input); border-radius: var(--radius-card);
  padding: 18px 22px; text-align: center; background: var(--card); max-width: 480px;
}
.dropzone .icon-lg { color: var(--text-secondary); }
.dropzone-title { font-weight: 600; margin: 8px 0 4px; }
.dropzone-sub { color: var(--text-secondary); font-size: var(--t5); margin: 0; }
.dropzone select {
  margin-top: 12px; padding: 8px 12px; border-radius: var(--radius-control);
  border: var(--divider-width) solid var(--border-input); background: var(--bg); color: var(--text);
  font-family: var(--font-sans); font-size: var(--t4);
}

/* Превью источник -> результат: полная ширина главной колонки, явно
   самый крупный визуальный блок раздела (тезис страницы). Round 2,
   п.1: чертёж должен читаться сразу, край в край, без полей внутри
   половины -- поэтому у сцен нет внутреннего padding под саму SVG
   (только у подписи и легенды поверх неё, абсолютным позиционированием),
   и высота сцены задана явно (440px), а не «сколько поместится». */
.hero-visual {
  position: relative; border: var(--divider-width) solid var(--divider);
  border-radius: var(--radius-card); overflow: hidden;
}
.hero-visual .split {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch;
}
.hero-visual .stage { position: relative; height: 440px; overflow: hidden; background: var(--card); }
/* Только прямой потомок -- сама геометрия чертежа/результата.
   Дочерний селектор (не просто «внутри»), иначе бейджи поверх (тоже
   внутри .stage) наследуют width:100% и раздуваются -- см. Result. */
.hero-visual .stage > svg {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
}
/* Источник -- тёмный "лист чертежа", независимо от темы страницы: это
   бумага/планшет, а не карточка интерфейса. Переменные, которые
   использует сама SVG (--text-secondary), переопределены здесь же,
   поэтому линии остаются видимыми на тёмном фоне в ЛЮБОЙ теме страницы --
   отступление от брендбука (внутри карточки данных обычно всё в токенах
   текущей темы), названо в Result. */
.hero-visual .source-stage {
  background: #14110F; --text-secondary: #C9A27A; --divider: #33291f;
}
.hero-visual .stage-label {
  position: absolute; top: 12px; left: 14px; font-size: 12px; font-weight: 600;
  letter-spacing: .03em; text-transform: uppercase; z-index: 2;
  color: var(--text-secondary); background: rgba(20,17,15,.55); padding: 3px 8px; border-radius: 5px;
}
.hero-visual .result-stage .stage-label {
  color: var(--text-secondary); background: var(--bg);
}
.hero-visual .stage-arrow {
  display: flex; align-items: center; justify-content: center; padding: 0 18px;
  color: var(--text-secondary); border-left: var(--divider-width) solid var(--divider);
  border-right: var(--divider-width) solid var(--divider); background: var(--bg);
}
.legend-chips {
  position: absolute; top: 12px; right: 12px; z-index: 2; display: flex; gap: 6px; flex-wrap: wrap;
  justify-content: flex-end; max-width: 60%;
}
.legend-chips .chip {
  display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--text);
  background: var(--bg); border: var(--divider-width) solid var(--divider);
  border-radius: 20px; padding: 3px 8px 3px 6px;
}
.legend-chips .chip i { width: 8px; height: 8px; border-radius: 50%; display: block; }
.seal-badge {
  position: absolute; left: 14px; bottom: 14px; z-index: 2; width: 34px; height: 34px;
  color: var(--warn); opacity: .9;
}
.seal-badge svg { width: 100%; height: 100%; display: block; }
.hero-visual .loss-badge {
  position: absolute; right: 14px; bottom: 14px; z-index: 2; max-width: 56%;
  background: var(--bg); border: 1.5px solid var(--warn); color: var(--warn);
  border-radius: 8px; padding: 8px 12px; font-size: 12px; display: flex; align-items: center; gap: 10px;
}
.loss-badge .loss-num { font-size: 26px; font-weight: 600; line-height: 1; flex: none; }
.loss-badge span:last-child { line-height: 1.3; }
@media (max-width: 1024px) {
  .hero-visual .split { grid-template-columns: 1fr; }
  .hero-visual .stage { height: 320px; }
  .hero-visual .stage-arrow { border: none; padding: 10px 0; transform: rotate(90deg); height: 34px; }
}

/* --- Три шага --- */
.steps-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
/* Round 4, п.6: четвёртый шаг «Процессы» -- 4 колонки на широком
   столе, 2×2 на среднем (1280 всё ещё широкий, но 4 узких карточки
   там уже мельче, чем читается), 1 в столбец на телефоне (сама
   секция на телефоне скрыта отдельным правилом ниже, это на случай
   промежуточных ширин). */
.steps-grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1200px) { .steps-grid-4 { grid-template-columns: repeat(2, 1fr); } }
/* U12: «Как это работает» стало двумя путями рядом (owner, 2026-10-01:
   «показать два пути — простой и сложный, чтобы одних не пугать
   сложностью, а вторых — простотой»), каждый путь -- своя колонка
   шагов/этапов в один ряд (steps-grid-1), а не сетка в несколько
   колонок -- колонка пути и так узкая вдвое. */
/* U16, п.0 (owner: «хочется выровнять»): «Инженерный» подзаголовок
   длиннее и переносится на две строки там, где «Простой» умещается
   в одну, и карточки шагов съезжали ниже у соседа. Фиксированная
   высота заголовка была бы верна только для одной ширины экрана --
   subgrid делит высоту заголовка по БОЛЬШЕМУ из двух на любой ширине,
   не угадывая число строк. .path-col сам становится grid-контейнером
   с двумя строками (заголовок, шаги) и просит их размер у родителя. */
/* U21, п.1 (owner: «хочется выровнять», уточнение 02.10 -- каждая
   карточка в «Простом» обязана стоять вровень И сверху, И снизу со
   своей парой в «Инженерном»): двух строк (заголовок, шаги) мало --
   U16 выравнивал только заголовок, а сами карточки 1/2/3 внутри были
   отдельной вложенной сеткой (.steps-grid-1), не делящей строки
   с соседней колонкой. Теперь у .paths-grid пять строк (заголовок
   + 4 шага), .path-col -- subgrid по всем пяти, а .steps-grid-1 стал
   display:contents: он перестаёт быть отдельным грид-контейнером
   и отдаёт свои .step-card прямо в строки родителя, так что шаг N
   «Простого» и шаг N «Инженерного» встают в одну и ту же строку
   и тянутся (stretch, умолчание grid) до её высоты -- значит делят
   верх И низ. Строка 4 (четвёртый шаг) занята только в «Инженерном»;
   в «Простом» клетка пустая, а не растянутая карточка-3. */
.paths-grid { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto repeat(4, auto); gap: 20px 40px; }
.path-col { display: grid; grid-template-rows: subgrid; grid-row: span 5; }
.path-col-eng { border-left: var(--divider-width) solid var(--divider); padding-left: 40px; }
.path-head { margin-bottom: 4px; align-self: start; }
.path-head h3 { font-size: var(--t2); margin: 0 0 4px; }
.path-head p { margin: 0; color: var(--text-secondary); font-size: 15px; }
.steps-grid-1 { display: contents; }
/* Браузер без subgrid (редкость к 2026 году) получает запасной
   фиксированный запас под две строки подписи вместо выравнивания --
   хуже разъезда карточек, но хотя бы не ломается. Та же ветка отменяет
   display:contents на .steps-grid-1 -- без subgrid он не вернёт
   выравнивание по шагам, и лучше остаться обычной колонкой карточек
   (поведение до U21), чем рассыпать разметку на отдельные элементы.
   Правило должно идти ПОСЛЕ безусловного .steps-grid-1 выше: при
   равной специфичности побеждает порядок в файле, а не то, что одно
   из правил условное -- иначе в браузере без subgrid сработал бы
   именно безусловный display:contents, а не этот откат. */
@supports not (grid-template-rows: subgrid) {
  .path-head { min-height: 68px; }
  .steps-grid-1 { display: grid; grid-template-columns: 1fr; gap: 16px; }
}
@media (max-width: 900px) {
  .paths-grid { grid-template-columns: 1fr; }
  /* На телефоне колонки идут одна под другой, делить строки больше
     не с кем -- .path-col теряет subgrid, и .steps-grid-1 обязан сам
     вернуть себе display:grid с зазором, иначе карточки лягут
     вплотную (display:contents из настольной раскладки зазора не
     даёт: у него самого нет блока, а значит и "gap"). */
  .path-col { display: block; }
  .path-col-eng { border-left: none; padding-left: 0; border-top: var(--divider-width) solid var(--divider); padding-top: 24px; }
  .steps-grid-1 { display: grid; grid-template-columns: 1fr; gap: 16px; }
}
.step-card {
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card); padding: 18px; display: flex; flex-direction: column; gap: 10px;
}
/* Кольцо, не заливка: тот же рисунок, что у знака и печати (кольцо +
   число вместо кольца + укуса), чтобы отметки шагов рифмовались с
   печатью «сверено» как один узнаваемый мотив (Round 2, п.2). */
.step-num {
  width: 30px; height: 30px; border-radius: 50%; background: transparent;
  border: 2px solid var(--copper); color: var(--copper);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: var(--t4);
}
.step-card h3 { font-size: var(--t3); margin: 0; }
.step-card p { color: var(--text-secondary); font-size: 16px; margin: 0; }
.step-mini {
  border-top: var(--divider-width) solid var(--divider); padding-top: 10px; margin-top: auto;
  font-size: 15px; font-weight: 600;
}
/* Round 3, п.5: настоящий фрагмент интерфейса внутри карточки шага,
   не только подпись под текстом -- занимает освободившееся пустое
   место и одновременно показывает компонент, который увидит
   пользователь на самом стенде. */
/* Round 5, п.7: разделитель и сам фрагмент прижаты книзу margin-top:auto
   уже были (Round 3), но высота фрагмента у всех четырёх карточек
   разная (1 строка текста у «Файл», 2 строки у «Процессы») -- значит
   сам РАЗДЕЛИТЕЛЬ вставал на разной высоте, хотя низ карточки общий.
   Фиксированная min-height у фрагмента выравнивает именно линию, а не
   только нижний край карточки. */
.step-demo {
  margin-top: auto; padding-top: 12px; border-top: var(--divider-width) solid var(--divider);
  display: flex; align-items: center; gap: 10px; min-height: 60px;
}
.step-demo > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.step-demo strong { font-size: 14px; }
.step-demo span { font-size: 13px; color: var(--text-secondary); }
.step-demo svg { flex: none; color: var(--text-secondary); }
.format-icon.small { width: 26px; height: 26px; }
.mini-seal { width: 40px; height: 40px; color: var(--copper); flex: none; }
.mini-seal svg { width: 100%; height: 100%; display: block; }
.step-result-num { display: flex; flex-direction: column; }
.step-result-num .mono { font-size: 26px; font-weight: 600; line-height: 1; color: var(--ok); }
.step-result-num small { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
@media (max-width: 900px) { .steps-grid { grid-template-columns: 1fr; } }

/* --- Форматы --- */
.formats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
/* Уточнение владельца поверх Round 5, п.8: 7 самых используемых
   форматов + 1 раскрывающаяся карточка «больше форматов» = 8 клеток,
   4×2 на столе и 2×4 на среднем/телефоне -- без auto-fill, оно даёт
   разное число колонок на разных брейкпоинтах и риск сироты. */
.formats-grid-8 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1300px) { .formats-grid-8 { grid-template-columns: repeat(2, 1fr); } }
.format-card-more { background: transparent; border-style: dashed; padding: 0; }
.format-card-more details { width: 100%; }
.format-more-summary {
  cursor: pointer; list-style: none; display: flex; gap: 12px; align-items: flex-start;
  padding: 14px;
}
.format-more-summary::-webkit-details-marker { display: none; }
.format-icon.sev-neutral { color: var(--text-secondary); }
.format-more-list {
  padding: 0 14px 6px; display: flex; flex-direction: column; gap: 14px;
  border-top: var(--divider-width) solid var(--divider); margin-top: 2px; padding-top: 12px;
}
.format-more-item .format-name { font-size: 14px; margin-bottom: 4px; }
.format-more-item .format-summary { font-size: 14px; margin: 0; }
.formats-more {
  font-size: 14px; color: var(--text-secondary); font-style: italic;
  margin: 10px 14px 14px; padding-top: 10px; border-top: var(--divider-width) solid var(--divider);
}
.format-card {
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card); padding: 14px; display: flex; gap: 12px; align-items: flex-start;
}
.format-icon {
  width: 34px; height: 34px; border-radius: var(--radius-control);
  border: var(--divider-width) solid var(--divider); display: flex; align-items: center;
  justify-content: center; flex: none; color: var(--text-secondary);
}
/* Иконка формата тонирована по тому, что он теряет, а не произвольно
   (Round 2, п.3): зелёная -- ничего не снимает (по нашим замерам),
   янтарная -- что-то снимает, и это названо в списке рядом. */
.format-icon.sev-ok { color: var(--ok); border-color: var(--ok); background: var(--ok-fill); }
.format-icon.sev-warn { color: var(--warn); border-color: var(--warn); background: var(--warn-fill); }
.format-icon.sev-bad { color: var(--bad); border-color: var(--bad); background: var(--bad-fill); }
.format-body { min-width: 0; }
.format-name { font-weight: 600; font-size: var(--t3); margin-bottom: 6px; }
/* Round 3, п.4: карточка формата вела с текстом; теперь ведёт с рядом
   коротких чипов «что держит / что снимает», затем максимум одна-две
   строки, а весь прежний список уходит под <details> «подробнее» --
   тот же приём, что уже стоит на превью данных (реальные числа не
   потеряны, просто не все видны сразу). */
.chip-row { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
/* U22, orchestrator fix (п.1 re-check): `white-space: nowrap` made a
   tag's intrinsic width equal its full text width -- `* { min-width: 0 }`
   at the top of this file lets the flex item SHRINK, but nowrap text has
   no break opportunity to shrink INTO, so the pill kept its full width
   and ran past the card edge («координата -- только WGS84», «геометрия
   смешанная» on narrower cards). A tag must never exceed its container:
   wrap onto a second line instead, in both themes. */
.tag {
  font-size: 12px; font-weight: 600; padding: 4px 9px; border-radius: 12px;
  border: 1.5px solid var(--divider); white-space: normal; max-width: 100%;
  line-height: 1.35; overflow-wrap: break-word; word-break: break-word;
  box-sizing: border-box;
}
.tag-ok { color: var(--ok); border-color: var(--ok); background: var(--ok-fill); }
.tag-warn { color: var(--warn); border-color: var(--warn); background: var(--warn-fill); }
.tag-bad { color: var(--bad); border-color: var(--bad); background: var(--bad-fill); }
/* U22, п.1: на светлой теме рамка в 1px/1.5px у тега и иконки формата
   тонула в кремовом фоне даже после смены цвета -- держим её чуть
   плотнее только там, где у тёмной темы и так достаточно контраста
   самим цветом на почти чёрном фоне. */
:root[data-theme="light"] .tag-ok,
:root[data-theme="light"] .tag-warn,
:root[data-theme="light"] .tag-bad,
:root[data-theme="light"] .format-icon.sev-ok,
:root[data-theme="light"] .format-icon.sev-warn,
:root[data-theme="light"] .format-icon.sev-bad { border-width: 2px; }
.format-summary { font-size: 15px; color: var(--text-secondary); margin: 0 0 8px; max-width: 42ch; }
.format-card details { font-size: 14px; }
.format-card summary {
  cursor: pointer; color: var(--water); font-size: 13px; font-weight: 600;
  list-style: none; margin-bottom: 4px;
}
.format-card summary::-webkit-details-marker { display: none; }
.format-limits { margin: 6px 0 0; padding-left: 18px; font-size: 14px; color: var(--text-secondary); }
.format-limits li { margin-bottom: 3px; }
.format-limits .clean { color: var(--ok); }

/* --- Сверка ---
   Round 5, п.5: одна секция -- тёмная лента даже в светлой теме (owner
   сам назвал «Сверка» примером). Токены переопределены на конкретные
   значения тёмной темы брендбука (не var(--bg) темы страницы -- эта
   секция принудительно тёмная независимо от переключателя). Контраст
   пар внутри -- те же самые, что уже проверены для тёмной темы
   (brand/out/check.md), потому что это и есть тёмная тема, просто
   внутри светской страницы. */
.dark-band {
  --bg: #1A1819; --card: #242223; --text: #ECE6DC; --text-secondary: #9C9892;
  --divider: #413E3D; --border-input: #706C69; --water: #8AB8E8;
  --copper: #C16A3D; --ok: #6CA176; --warn: #D9A441; --bad: #E06A5F;
  --ornament: #543526; --data-road: #5FB3B3;
  background: var(--bg); color: var(--text);
}
.verdict-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
.verdict-card {
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card); padding: 16px; text-align: center;
}
.verdict-card .stamp-wrap { width: 88px; height: 88px; margin: 0 auto 10px; color: var(--text); }
.verdict-card .stamp-wrap svg { width: 100%; height: 100%; display: block; }
.verdict-card:first-child .stamp-wrap { color: var(--ok); }
.verdict-card.state-broken .stamp-wrap { color: var(--bad); }
.verdict-card h3 { font-size: 17px; margin: 0 0 4px; }
.verdict-card p { font-size: 15px; color: var(--text-secondary); margin: 0; }
.verdict-number { font-family: var(--font-mono); font-size: var(--result-number); font-weight: 600; margin: 18px 0; }
@media (max-width: 900px) { .verdict-grid { grid-template-columns: 1fr; } }

/* --- Инженерная схема --- */
.schema-wrap {
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card); padding: 20px; overflow-x: auto;
}
/* Round 3, п.3: раньше диаграмма была ограничена 680px внутри широкой
   панели -- сама разметка читалась мелко именно из-за этого масштаба
   вниз (viewBox 880 шириной, показанный в 680px -- меньше единицы),
   а не из-за размера шрифта в разметке. На всю ширину панели тот же
   viewBox масштабируется ВВЕРХ (на 1440 панель ~1130px), и подписи
   читаются без изменения самих чисел font-size. */
.schema-wrap svg { display: block; margin: 0 auto; width: 100%; height: auto; }
.schema-caption { font-size: var(--t5); color: var(--text-secondary); margin-top: 10px; }

/* --- Превью данных ---
   Round 3, п.1: было auto-fit(240px) -- при 6 карточках это давало
   4 + 2 на широких столах (последняя строка повисала с пустым местом
   сбоку). Явная сетка 3 колонки при 1440/1280 и 2 при 1024 всегда
   заполняет обе строки без сирот, раз карточек ровно 6 = 3×2 = 2×3. */
.previews-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 1024px) {
  .previews-grid { grid-template-columns: repeat(2, 1fr); }
}
.preview-card {
  border: var(--divider-width) solid var(--divider); border-radius: var(--radius-card);
  background: var(--card); overflow: hidden;
}
.preview-card .preview-img { padding: 10px; }
.preview-card .preview-img svg { display: block; width: 100%; height: auto; }
.preview-meta { padding: 10px 14px 14px; border-top: var(--divider-width) solid var(--divider); }
.preview-meta h3 { font-size: var(--t4); margin: 0 0 2px; }
.preview-meta p { font-size: var(--t5); color: var(--text-secondary); margin: 0; }

/* --- Доверие и данные --- */
.trust-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
.trust-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.trust-list li { display: flex; gap: 10px; font-size: 16px; color: var(--text-secondary); }
.trust-list svg { color: var(--ok); flex: none; margin-top: 2px; }
.limits-list { margin: 0; padding-left: 18px; font-size: 16px; color: var(--text-secondary); }
@media (max-width: 900px) { .trust-grid { grid-template-columns: 1fr; } }

/* --- FAQ --- */
.faq-list { display: flex; flex-direction: column; gap: 2px; }
.faq-item { border-bottom: var(--divider-width) solid var(--divider); }
.faq-item summary {
  cursor: pointer; padding: 14px 0; font-weight: 600; font-size: var(--t4);
  list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary .chev { transition: transform .15s; flex: none; color: var(--text-secondary); }
.faq-item[open] summary .chev { transform: rotate(90deg); }
.faq-item p { padding: 0 0 16px; color: var(--text-secondary); font-size: 16px; max-width: 70ch; }

/* --- «О проекте» (U21, п.4) --- */
#about .section-head p { max-width: 70ch; }
.about-principles {
  list-style: none; margin: 0 0 24px; padding: 0; display: flex; flex-direction: column;
  gap: 10px; max-width: 70ch; font-size: 16px;
}
.about-principles li { padding-left: 20px; position: relative; }
.about-principles li::before { content: "—"; position: absolute; left: 0; color: var(--copper); }
.about-feedback { font-size: 16px; max-width: 70ch; }
/* U23: реальный адрес вместо заглушки (владелец назвал почту, не
   личный ящик) -- обычная ссылка, текст выделяется и копируется как
   любой другой текст на странице, ничего больше не подчёркиваем. */
.contact-link { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* --- «Новости» (U16, п.3): владелец — e-mail пугает русских
   пользователей, предложил «надпись или проверяйте анонсы».
   Форма-заглушка снята, вместо неё один список фактов уже сделанного,
   самый новый сверху. Список — ОДИН блок разметки: добавить новость --
   вставить <li> первым в .news-list (документировано в DEPLOY.md).
   U21, п.2 (owner, 02.10: «не раскрывать всех подробностей — не писать
   дат... нужны хотя бы месяцы, чтобы прогресс был сразу виден»):
   точный день (<time datetime>) снят -- заголовок группы называет
   только месяц и год, самая новая группа сверху. Группа -- .news-group,
   добавить месяц -- новый блок перед существующими (DEPLOY.md). */
.news-group + .news-group { margin-top: 24px; }
.news-month {
  font-size: var(--t5); font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-secondary); margin: 0 0 10px;
}
.news-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.news-list li { font-size: 16px; }
/* U21, п.3 (owner, через оркестратора): e-mail пугает именно русских
   пользователей (U16) -- значит снимается только с RU, а не как класс
   решения. EN получает поле обратно рядом со списком новостей, ТОЙ ЖЕ
   формой, что была до U16 (notify-form), но без фальшивого обещания
   "придёт письмо": бэкенда для него ещё нет, и примечание говорит
   об этом прямо, а не только то, что почта не передаётся на сторону. */
.news-signup {
  margin-top: 24px; padding-top: 20px; border-top: var(--divider-width) solid var(--divider);
}
.news-signup p.news-signup-lead { margin: 0 0 12px; font-size: 16px; color: var(--text-secondary); }
.notify-form { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.notify-form input[type="email"] {
  flex: 1 1 260px; padding: 12px 16px; border-radius: var(--button-radius);
  border: var(--divider-width) solid var(--border-input); background: var(--card);
  color: var(--text); font-family: var(--font-sans); font-size: var(--t3);
  min-height: var(--button-min-height);
}
.notify-note { font-size: var(--t5); color: var(--text-secondary); margin: 0; }
.notify-note + .notify-note { margin-top: 6px; }
/* U23, п.4: форма подписки РУ со 152-ФЗ -- U21 снял e-mail с RU целиком
   («пугает русских пользователей»), но владелец выбрал рассыльщика
   (Unisender/Sendsay) и подаёт уведомление в РКН, так что поле
   возвращается, теперь с двумя раздельными согласиями, которых
   требует закон: на обработку персональных данных и отдельно на
   получение новостей. Оба чекбокса не отмечены по умолчанию и оба
   обязательны -- так и должно быть, это не недоделанная форма.
   Бэкенда всё ещё нет (как у EN-формы: .notify-note ниже говорит
   об этом прямо), и оба текста согласия -- простые `<label>` без
   своей разметки, чтобы не городить компонент под форму, которая
   пока никуда не отправляет. */
.notify-consent {
  display: flex; align-items: flex-start; gap: 8px; flex: 1 1 100%;
  font-size: var(--t5); color: var(--text-secondary); cursor: pointer;
}
.notify-consent input[type="checkbox"] { margin-top: 3px; flex: none; width: 16px; height: 16px; }
.notify-consent a { color: inherit; }

/* --- Подвал ---
   Round 4, п.3 и п.4: было -- пустая широкая строка от края до края
   с именем слева и ссылками справа. Теперь -- тот же контейнер
   1180px, что у main и шапки, и настоящий брендовый блок (полный
   локап + строка о продукте), а не только слово «Swage». */
footer.podval {
  border-top: var(--divider-width) solid var(--divider); padding: 40px 0 32px;
  color: var(--text-secondary); font-size: var(--t5);
}
.podval-inner {
  max-width: 1180px; margin: 0 auto; padding: 0 24px;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 32px;
}
footer.podval a { color: var(--text-secondary); text-decoration: underline; }
footer.podval nav { display: flex; gap: 16px; flex-wrap: wrap; align-content: flex-start; }
.podval-brand { max-width: 360px; }
.podval-brand .lockup { height: 26px; margin-bottom: 10px; }
.podval-brand p { margin: 0; font-size: var(--t5); color: var(--text-secondary); }
/* U16, п.7: копирайта не было вообще -- владелец попросил добавить. */
.podval-copy { margin-top: 10px; }

/* U16, п.5: статические страницы «Условия»/«Конфиденциальность» --
   тот же логотип и подвал, что у лендинга, но без его разделов:
   простая проза поверх общих токенов, без нового макета страницы. */
.legal-page { padding: 48px 0 72px; }
.legal-page h1 { font-size: var(--t1); margin-bottom: 6px; }
.legal-page .legal-draft {
  display: inline-block; margin: 0 0 28px; padding: 6px 12px;
  border: var(--divider-width) solid var(--warn); border-radius: var(--radius-control);
  color: var(--warn); font-weight: 600; font-size: var(--t4);
}
.legal-page h2 { margin-top: 36px; font-size: 19px; }
.legal-page ul { padding-left: 20px; }
.legal-page li { margin: 4px 0; }
.legal-page table { width: 100%; border-collapse: collapse; margin: 16px 0; font-size: var(--t4); }
.legal-page th, .legal-page td {
  border: var(--divider-width) solid var(--divider); padding: 8px 10px;
  text-align: left; vertical-align: top;
}
.legal-page th { background: var(--card); }
.legal-page code {
  font-family: var(--font-mono); font-size: .92em; background: var(--card);
  padding: 1px 4px; border-radius: 4px;
}
.legal-page .back-link { display: inline-block; margin-bottom: 20px; }

/* U16, п.6 (владелец, уточнение через оркестратора: речь была про
   переключатель темы, не про подвал) -- рабочий стенд переключателя
   темы не ставит нигде в коде (проверено по ui.py/webpage.py), сам
   лендинг держит тёмную и светлую версии РАЗНЫМИ файлами (U11).
   Кнопка переключает атрибут data-theme на <html> и держит выбор
   в localStorage, поверх уже готовых блоков :root[data-theme=light]/
   [data-theme=dark] в этом же файле -- без них переключение жило бы
   только на бумаге. index.html и index-light.html остаются отдельными
   файлами (прямая ссылка на тему работает без JS), кнопка — поверх. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  border: var(--divider-width) solid var(--divider); background: transparent;
  color: var(--text-secondary); cursor: pointer; margin-right: 4px;
}
.theme-toggle:hover { color: var(--text); border-color: var(--text-secondary); }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* --- Печать: анимация появления, только при согласии на движение --- */
@media (prefers-reduced-motion: no-preference) {
  .stamp-anim { animation: stamp-in .4s cubic-bezier(.2,.9,.3,1.2) both; }
  @keyframes stamp-in {
    0% { opacity: 0; transform: scale(1.5) rotate(-8deg); }
    100% { opacity: 1; transform: scale(1) rotate(-6deg); }
  }
  /* Раскрытие результата слева направо -- сама конвертация читается
     как процесс, а не как две статичные картинки (Round 2, п.1). */
  /* Короткая длительность НАРОЧНО (не «для красоты быстрее»): скриншот
     в headless-хроме снимается почти сразу после load, и анимация в
     секунду-полторы означала бы, что на КАЖДОМ снимке этой задачи
     раскрытие оказалось бы на середине -- то есть страница выглядела
     бы сломанной именно на артефакте проверки. 350-450мс укладываются
     до захвата и остаются анимацией для живого посетителя. */
  .hero-visual .result-stage { animation: reveal-h .38s ease-out both; }
  @keyframes reveal-h { 0% { clip-path: inset(0 100% 0 0); } 100% { clip-path: inset(0 0 0 0); } }
  .seal-badge, .loss-badge { animation: fade-up .3s ease-out both; animation-delay: .38s; }
  @keyframes fade-up { 0% { opacity: 0; transform: translateY(6px); } 100% { opacity: 1; transform: translateY(0); } }
}

@media (max-width: 640px) {
  main { padding: 0 16px; }
  section { padding: 40px 0; }
  .verdict-grid, .formats-grid { grid-template-columns: 1fr; }
  /* Телефон -- своя, урезанная концепция (owner, 2026-09-30: «для
     телефона своя концепция... не переносим ограничения маленького
     экрана туда, где есть где развернуться»): только герой (=
     Простая конвертация), форматы, доверие и FAQ. Шаги, сверка,
     инженерная схема и подборка превью -- десктопные разделы,
     на телефоне их не сжимаем, а убираем целиком. Round 2, п.8:
     сама айдентика (орнамент, печать, пример обратного хода, крупные
     числа) с телефона НЕ снимается -- ограничена только раскладка. */
  #steps, #verdict, #engineering, #previews { display: none; }
  .ornament-wash { height: 520px; }
  .hero-stats { gap: 12px; }
  .stat-num { font-size: 32px; }
  .hero-visual .stage { height: 260px; }
  .reverse-example { margin-top: 20px; padding: 14px 16px; }
  /* U13 п.28: на узком экране карточка формата ведёт одним чипом (главный
     предел) и одной строкой (главная потеря); остальные чипы дублируют
     то же самое текстом внутри <details>, уже раскрываемым «подробнее» --
     прячем их тут, а не убираем данные. Раскладка шире 640px не меняется. */
  .chip-row .tag:nth-child(n+2) { display: none; }
}
