/* screens.css — дополнения по экранам.
   Фундамент (T01) сюда почти ничего не кладёт: экраны появляются в тасках
   02–07, каждый дописывает только свой блок и только через токены tokens.css.
   Порядок блоков — порядок потока: hero, looks, question, interlude,
   cases, result, offer, try-on. */

/* ── Экран вопроса ─────────────────────────────────────────────────
   Колонка: навигационный ряд → полоса → вопрос → подсказка → карточки.
   Ритм из DESIGN.md: 8px внутри группы, 12–18px между группами,
   18px под полосой прогресса. Действие — только у множественного
   вопроса: одиночный уходит сам. */

.question > .progress {
  margin-top: var(--space-md);
}

.question__title {
  margin-top: var(--space-lg);
}

.question__help {
  margin-top: var(--space-sm);
  color: var(--field-text-muted);
}

.question__options {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-top: var(--space-lg);
}

/* Вопросы с фото: миниатюра кадрирована 4:5, как и все снимки образов. */
.question--photo .option-card__thumb {
  height: auto;
  aspect-ratio: 4 / 5;
}

/* «Начать заново» видно только на продолженном прохождении. Призрачная
   кнопка: тише всего на экране, но с полноценной целью нажатия. Общий вид —
   `.restart-link` (используется здесь и на герое); отличается только отступ
   сверху, он вынесен модификатором `--question`/`--hero`. */
.restart-link {
  align-self: flex-start;
  min-height: var(--tap-min);
  padding: var(--space-sm) 0;
  border: 0;
  background: none;
  color: var(--field-text-muted);
  font-family: var(--font-text);
  font-size: var(--type-sub-size);
  line-height: var(--type-sub-line);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--motion-surface);
}

.restart-link:hover {
  color: var(--field-text);
}

.restart-link--question {
  margin-top: var(--space-xl);
}

/* ── Первый экран ──────────────────────────────────────────────────
   Композиция по образцу https://donskih.com/make-up (мобильная версия,
   замеры — тикет 02): кремовый верх с заголовком → оксбладовая карточка
   во всю ширину → вырезанная фигура выходит за верхний ВЕРХНИЙ край
   карточки — голова и волосы на кремовом, тело внутри карточки. Внутри
   карточки снизу — наш призыв и белая кнопка-пилюля. Берём композицию, не их
   контент: своя типографика (Oswald капсом, слово в лаке), свой призыв,
   без цен и «доступа через приложение» (DESIGN.md → Signature devices,
   PRODUCT.md). Цвет карточки и её скругление — токены, не их #930F1E. */

/* Кнопка теперь обычная, внутри карточки, а не в липкой зоне понизу
   экрана — этот экран её не резервирует. */
.hero {
  padding-bottom: var(--space-xl);
}

.hero__title {
  margin: 0;
}

.hero__title-line {
  display: block;
}

.hero__promise {
  margin: var(--space-lg) 0 0;
  color: var(--field-text);
}

/* Те же четыре слова, что раньше стояли выносками на кисти, — настоящим текстом. */
.hero__parts {
  margin: var(--space-md) 0 0;
  color: var(--field-text-muted);
}

/* Та же призрачная кнопка, что на экране вопроса (`.restart-link` выше в
   этом файле) — здесь только отступ сверху, он меньше, чем у вопроса.
   Живёт в кремовом вступлении, не в карточке: раньше её держали перед
   фигурой из-за липкой зоны действия понизу экрана — той зоны здесь больше
   нет (кнопка теперь обычная, внутри карточки), но место не изменилось —
   так восстановление прохождения остаётся первым действием на экране. */
.restart-link--hero {
  margin-top: var(--space-lg);
}

/* Сцена: карточка и фигура делят одну область — фигура поверх карточки,
   с бо́льшей высотой, поэтому её верх выступает над карточкой на кремовое
   поле. `--hero-figure-h`/`--hero-card-h` (tokens.css) держат высоты
   пропорциональными на любой ширине — не два независимых размера, которые
   на какой-то ширине разъедутся. `.bleed`: карточка идёт во всю ширину
   экрана, как и другие полноширинные элементы системы (DESIGN.md → Layout). */
.hero__stage {
  position: relative;
  height: var(--hero-figure-h);
  /* Только верхнее поле: короткая запись `margin` обнуляла бы боковые
     отрицательные поля из `.bleed` (base.css), и полноширинная карточка
     уезжала бы за правый край экрана ровно на величину поля колонки. */
  margin-top: var(--space-2xl);
}

/* Три слоя друг на друге в порядке рисования (все `position: absolute`
   внутри `.hero__stage`, без z-index — позже в DOM значит выше): сперва
   оксбладовый прямоугольник, поверх него фигура (тело перекрывает карточку,
   голова выходит над ней на кремовое), и сверху текст с кнопкой — иначе
   подол платья на кадре, доходящий почти до низа карточки, оказался бы
   выше кнопки и перекрыл её. Три слоя, а не один `<div>` с содержимым:
   иначе фигуру некуда вставить между фоном карточки и её текстом. */
.hero__card {
  position: absolute;
  inset: auto 0 0 0;
  height: var(--hero-card-h);
  border-radius: var(--radius-xl);
  background: var(--field-bg);
}

/* Фигура: центр по ширине сцены, низ вровень с низом карточки (замер
   эталона: 681.4px у обоих — не совпадение, а как задумана композиция),
   верх — там, где кончается её собственная высота, то есть над карточкой.
   Без рамки, без тени: альфа-канал уже несёт силуэт. `pointer-events: none`
   — иначе прозрачные поля кадра над кнопкой перехватывали бы клик по ней. */
.hero__figure {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.hero__cta {
  position: absolute;
  inset: auto 0 0 0;
  height: var(--hero-card-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 0 var(--space-xl) var(--space-xl);
  text-align: center;
}

.hero__cta-copy {
  margin: 0 0 var(--space-lg);
  color: var(--field-text);
}

/* Кнопка внутри карточки — обычная (не липкая зона понизу экрана: та
   существует ради экранов без своего места для кнопки, а здесь оно есть,
   в самой карточке) и единственная громкая кнопка на этом экране. Форма —
   пилюля, как в эталоне; всё остальное — тот же `.btn-primary`, что и
   везде в системе, включая инверсию цвета на оксбладовом поле. */
.hero__cta-button {
  border-radius: var(--radius-pill);
}

/* Без hover-масштаба, который был здесь раньше (DESIGN.md → Motion, 1.02
   за 700мс): `.hero__figure` теперь `pointer-events: none` (см. выше) —
   клик должен доставаться кнопке под фигурой, а не самой картинке, и
   заодно она не может ловить наведение для :hover. */
.hero__photo {
  width: auto;
  height: var(--hero-figure-h);
  max-width: 100%;
}

/* ── Экран выбора образа ───────────────────────────────────────────
   Это вопрос 1 из 18: нав-ряд, полоса прогресса, заголовок, подсказка,
   карточки и восстановление рисует общий рендерер question.js (у одного
   вопроса — один рендерер, `.question`/`.question__*` из его блока выше).
   Здесь — только то, что принадлежит этому экрану: приём «torn strip»,
   вставленный между подсказкой и карточками. Фотография проступает
   вертикальной полосой в `--strip-width` (42%) ширины колонки между
   панелью с текстом и узкой панелью у правого края — как будто страницу
   держат открытой. Кадр лежит под всей плашкой во всю её ширину, а
   панели его закрывают. */

.looks__strip {
  position: relative;
  display: grid;
  /* Полоса остаётся вертикальной и там, где текста в панели мало:
     половина колонки — нижняя граница её высоты. */
  min-height: calc(var(--column) / 2);
  /* Поля колонки внутри плашки: колонки сетки считаются от ширины
     колонки, а не от полного вылета, — полоса ровно 42% колонки. */
  grid-template-columns: 1fr var(--strip-width) var(--space-2xl);
  margin-top: var(--space-lg);
  margin-inline: var(--bleed);
  padding-inline: var(--gutter);
  overflow: hidden;
}

.looks__strip-photo {
  position: absolute;
  inset: 0;
  height: 100%;
  /* Класс общий с прежним приёмом «torn strip» на экране выбора образа
     (см. `looks.js` — там его больше нет, торн-полосу сняли раньше, ещё
     до вырезанных фигур этого таска). Сейчас его использует только
     `result.js` для фото выбранного образа; кроп по вертикали — 20%
     сверху, под лица образов в этой галерее. */
  object-position: 45% 20%;
}

/* Панели непрозрачны и дотягиваются до краёв экрана — между ними и
   остаётся полоса фотографии. */
.looks__panel {
  position: relative;
  grid-column: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-sm);
  margin-left: var(--bleed);
  padding: var(--space-xl) var(--space-base) var(--space-xl) var(--gutter);
  background: var(--field-bg);
}

.looks__edge {
  position: relative;
  grid-column: 3;
  margin-right: var(--bleed);
  background: var(--field-bg);
}

.looks__note {
  margin: 0;
  color: var(--field-text-muted);
}

/* Обёртка вокруг каждой карточки образа (`screens/looks.js`): карточка
   выбора и кнопка-лупа — соседние элементы внутри неё, а не вложенные
   друг в друга (`<button>` внутри `<button>` — невалидный HTML), поэтому
   клик по лупе никогда не всплывает в обработчик выбора. Сама обёртка —
   обычный блочный `<div>`, без своих отступов и рамки: она в точности
   повторяет прямоугольник `.option-card` внутри, только даёт лупе точку
   отсчёта для абсолютного позиционирования. */
.look-card {
  position: relative;
}

/* Лупа стоит на нижнем правом углу миниатюры — `--look-card-zoom-top` и
   `--look-card-zoom-left` (tokens.css) выводят его из паддинга карточки
   и размера миниатюры, поэтому угол совпадает и на узкой ширине, где
   миниатюра меньше (`--thumb-size-narrow`). Плашка тёмная и непрозрачная
   независимо от текущего поля — она лежит на фотографии произвольной
   яркости, а не на грунте экрана: тот же приём читаемости, что и у
   `.panel-frosted`/`--panel-frosted-bg-fallback` (components.css). */
.look-card__zoom {
  position: absolute;
  top: var(--look-card-zoom-top);
  left: var(--look-card-zoom-left);
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--panel-frosted-bg-fallback);
  color: var(--color-text-on-oxblood);
  transition: background-color var(--motion-surface), transform var(--motion-press);
}

.look-card__zoom:hover {
  background: var(--color-oxblood);
}

.look-card__zoom:active {
  transform: scale(var(--motion-press-scale));
}

.look-card__zoom-icon {
  width: var(--space-lg);
  height: var(--space-lg);
}

/* ── Вставка между этапами ───────────────────────────────────────
   Оксбладовое поле во всю ширину: сверху фигура без фона, своя для
   каждого этапа, ниже текст на сплошном поле — не поверх фигуры, лицо
   всегда видно целиком. Между блоками 34px (DESIGN.md, «Rhythm»). Сами
   штрих и обводка живут в components.css: рисуются 620 мс, обводка
   на 180 мс позже, при отключённой анимации — нарисованы сразу. */

/* Как у героя: липкой зоны понизу экрана здесь нет — кнопка живёт внутри
   плашки, — поэтому нижний отступ обычный, а не под высоту той зоны
   (`.screen` в base.css резервирует её всем экранам). */
.interlude {
  padding-bottom: var(--space-xl);
  /* Когда остаток высоты упирается в потолок сцены (высокий экран,
     короткая поддержка), лишнее уходит в зазор над сценой, а не под неё:
     плашка всегда стоит на низу экрана, как на первом. */
  justify-content: space-between;
}

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

   Высота — по остатку экрана, не по ширине: исходный кадр
   вертикальный и узкий (силуэт в рост), см. `.hero__figure` в этом же
   файле для того же приёма. На обычных и высоких экранах она вольна занимать заметную
   долю вьюпорта (30dvh) — под текстом всегда остаётся много места, и
   зазоры вокруг текста держат общий ритм DESIGN.md (34px между блоками).
   Низкие экраны (`@media (max-height: 720px)` ниже) — отдельный расчёт:
   там той же доле высоты и тем же зазорам не хватает места, чтобы под
   самым длинным из четырёх абзацев (fallback этапа «Техника», 5 строк)
   осталась зона действия, а не обрезанный текст под её градиентом —
   обрезка и была причиной этой правки (см. CLAUDE.md → «Грабли»). Общее
   правило на все высоты не годится: то, что чинит 320×568, на 768×1024
   оставляет от фигуры едва заметный силуэт в море пустого поля — поэтому
   сниженные значения живут только внутри медиа-запроса, а не в общем
   правиле. Если на ещё более длинном будущем тексте на низком экране
   всё же не хватит — прокрутка не баг: `.screen`-паддинг снизу
   (`base.css`) уже держит нужный отступ, так что после неё текст не
   остаётся под кнопкой ни на одной ширине. */
/* Сцена забирает весь остаток высоты экрана под текстом (`flex: 1`), а не
   держит свой рост: длина поддержки гуляет от двух строк до пяти, и при
   фиксированной высоте между текстом и плашкой оставалась дыра в треть
   экрана на коротком тексте. Границы остатка — двумя токенами: ниже
   минимума фигура перестаёт читаться, выше потолка (планшет, высокий
   экран) разрастается на весь экран.

   Только верхнее поле, не короткая запись `margin`: она обнулила бы
   боковые отрицательные поля из `.bleed` (см. `.hero__stage` выше). */
.interlude__stage {
  position: relative;
  flex: 1 1 auto;
  min-height: var(--interlude-figure-h-min);
  max-height: var(--interlude-figure-h-max);
  margin-top: var(--space-2xl);
}

.interlude__card {
  position: absolute;
  inset: auto 0 0 0;
  height: calc(var(--hero-card-ratio) * 100%);
  border-radius: var(--radius-xl);
  background: var(--field-bg);
}

/* `pointer-events: none` — прозрачные поля кадра лежат поверх кнопки,
   и без этого они перехватывали бы клик по ней (та же причина, что у
   `.hero__figure`). */
.interlude__figure {
  position: absolute;
  /* Все четыре стороны, а не только низ: рост фигуры задан в процентах
     от сцены, а процент от родителя высотой `auto` не разрешается. */
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin: 0;
  pointer-events: none;
}

.interlude__photo {
  width: auto;
  height: 100%;
  max-width: 100%;
}

.interlude__cta {
  position: absolute;
  inset: auto 0 0 0;
  height: calc(var(--hero-card-ratio) * 100%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 var(--space-xl) var(--space-xl);
}

.interlude__cta-button {
  border-radius: var(--radius-pill);
}

.interlude__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* Низкие экраны: жмётся только текст. Рост сцены не трогаем — она берёт
   остаток высоты сама, а границы остатка заданы в долях вьюпорта. */
@media (max-height: 720px) {
  .interlude__text {
    gap: var(--space-md);
  }

  .interlude__stage {
    margin-top: var(--space-lg);
  }
}

.interlude__index,
.interlude__insight,
.interlude__body {
  margin: 0;
}

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

/* Каждая пометка получает свою строку: один SVG-путь, растянутый на
   многострочную фразу, перестаёт читаться как рукотворный штрих. Ширина
   по содержимому — чтобы штрих кончался там же, где кончается фраза.
   Кегль свой (`--type-insight-size`), мельче вопроса: обводке нужен
   зазор до букв. Он один на обе строки — зачёркнутую и обведённую.
   Зазор между строками меньше, чем между блоками текста, — иначе две
   половины одной мысли рассыпались бы на два отдельных утверждения. */
.interlude__insight {
  font-size: var(--type-insight-size);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  overflow-wrap: break-word;
}

.interlude__insight .marker-mark {
  display: block;
  width: fit-content;
  max-width: 100%;
}

/* ── Кейсы учениц ────────────────────────────────────────────────
   Чернильное поле. Каждый кейс — карточка с 1px границей: пара «до/после»
   4:5 с видимыми подписями, имя, цитата и результат — там, где он есть. */

.cases__eyebrow {
  margin: 0 0 var(--space-sm);
  color: var(--field-text-muted);
}

.cases__title {
  margin: 0 0 var(--space-md);
}

.cases__lead {
  margin: 0 0 var(--space-2xl);
  color: var(--field-text-muted);
}

.cases__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

.case {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-base);
  border: var(--hairline) solid var(--field-line);
  border-radius: var(--radius-md);
  background: var(--field-surface);
}

.case__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

/* Остальные снимки кейса и галерея участниц: колонки набираются по ширине,
   поэтому семь работ не превращаются в семь полос на узком экране. */
.case__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: var(--space-sm);
}

.case__shot {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin: 0;
}

.case__frame {
  overflow: hidden;
  border: var(--hairline) solid var(--field-line);
  border-radius: var(--radius-sm);
}

.case__image {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

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

.case__name {
  margin: var(--space-sm) 0 0;
}

.case__count,
.case__outcome,
.case__extra,
.case__quote-line {
  margin: 0;
}

/* Цитата отбивается линейкой, а не кавычками: текст не трогаем вовсе. */
.case__quote {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin: 0;
  padding-left: var(--space-md);
  border-left: var(--stroke) solid var(--field-line-strong);
}

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

/* Редакционная сноска: там, где исходная фраза оборвана, это видно. */
.case__note {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin: 0;
  padding-top: var(--space-sm);
  border-top: var(--hairline) solid var(--field-line);
  color: var(--field-text-muted);
}

.case__note-label {
  color: var(--field-text-muted);
}
/* ── Экран результата ────────────────────────────────────────────
   Костяное поле: та же грамматика компонентов, что и на остальных
   экранах, — меняются только грунт, текст и границы (DESIGN.md,
   «The result screen switches to the bone field»). Торн-полоса в шапке —
   `.looks__strip` / `.looks__panel` / `.looks__edge` из блока «Экран
   выбора образа» выше: тот же приём на двух экранах, а не двойник под
   новым именем (DESIGN.md, «Used for the look-selection screen and the
   result hero»). Здесь — только то, что у результата своё: подводка под
   заголовком, до трёх техник большими номерами и косметичка рядами. */

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

.result__pitch {
  margin-top: var(--space-sm);
}

.result__meta {
  margin-top: var(--space-sm);
  color: var(--field-text-muted);
}

.result__gaps {
  margin-top: var(--space-2xl);
}

.result__gaps-note {
  color: var(--field-text-muted);
}

.result__gaps-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  margin-top: var(--space-lg);
}

.result__gap {
  display: flex;
  align-items: baseline;
  gap: var(--space-base);
}

/* Большой номер — часть диагностики, не декоративный счётчик: `<ol>`
   уже объявляет порядковое место каждого пункта голосом, поэтому сама
   цифра `aria-hidden`. */
.result__gap-index {
  flex: none;
  min-width: 1.6em;
  color: var(--field-line-strong);
}

.result__gap-copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.result__kit {
  margin-top: var(--space-2xl);
}

.result__kit-title {
  margin-bottom: var(--space-sm);
}

.result__kit-status {
  color: var(--field-text-muted);
}

.result__kit-group + .result__kit-group {
  margin-top: var(--space-xl);
}

.result__kit-stage {
  color: var(--field-text-muted);
  padding-bottom: var(--space-xs);
  border-bottom: var(--hairline) solid var(--field-line);
}

/* Ряды каталога: строка целиком — ссылка, обычный текст без подчёркивания
   ссылки. Наведение поднимает ряд до `bone-surface` и сдвигает текст
   на 7px (DESIGN.md, «Result and makeup bag»). */
.result__kit-row {
  border-bottom: var(--hairline) solid var(--field-line);
}

.result__kit-row:last-child {
  border-bottom: 0;
}

.result__kit-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-base);
  min-height: var(--tap-min);
  padding: var(--space-sm) 0;
  color: var(--field-text);
  text-decoration: none;
  transition: background var(--motion-surface);
}

.result__kit-link:hover,
.result__kit-link:focus-visible {
  background: var(--field-raise);
}

.result__kit-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  transition: transform var(--motion-surface);
}

.result__kit-link:hover .result__kit-info,
.result__kit-link:focus-visible .result__kit-info {
  transform: translateX(7px);
}

.result__kit-brand {
  color: var(--field-text-muted);
}

.result__kit-shade {
  color: var(--field-text-muted);
}

.result__kit-arrow {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--field-text-muted);
}

.result__kit-error {
  display: flex;
  flex-direction: column;
  gap: var(--space-base);
  align-items: flex-start;
}

.result__kit-error-text {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  color: var(--field-text);
}

.result__kit-error-icon {
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  color: var(--color-error);
}

.result__kit-error .btn-primary {
  align-self: stretch;
}

/* ── Примерка (`src/tryon.js`) ───────────────────────────────────
   DESIGN.md → «Try-on»: «a bordered two-pane tool on ink». Инструмент
   монтируется внутри оксбладового экрана оффера, поэтому поле здесь не
   меняет `body` (в потоке зарегистрирован один экран `offer`) — вместо
   этого `.tryon` переопределяет ровно тот набор `--field-*` переменных,
   что и `.field-ink` в tokens.css, локально для себя и всех вложенных
   кирпичей (`.t-sub`, `.btn-primary`…). Токены остаются те же самые,
   просто применены на вложенном узле, а не на `body` — карточка того же
   рода, что описана в DESIGN.md: «only the ground, ink, and border
   tokens swap. A card is the same card in all three [fields]». */

.tryon {
  --field-bg: var(--color-ink);
  --field-raise: var(--color-ink-raise);
  --field-surface: var(--color-card);
  --field-surface-hover: var(--color-card-hover);
  --field-line: var(--color-line);
  --field-line-strong: var(--color-line-strong);
  --field-text: var(--color-text);
  --field-text-muted: var(--color-text-muted);
  --field-text-faint: var(--color-text-faint);
  /* Синхронизировано с .field-ink (tokens.css): поле светлое, контур —
     лаковый, а не --focus-ring-oxblood (тот — только для оксблада). */
  --field-focus: var(--color-lacquer);
  --field-veil: var(--color-veil);
  --field-veil-line: var(--color-veil-line);
  --field-action-bg: var(--color-lacquer);
  --field-action-bg-hover: var(--color-lacquer-hover);
  --field-action-text: var(--color-bone-surface);
  --field-action-shadow: var(--shadow-glow);

  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  background: var(--field-bg);
  color: var(--field-text);
  border: var(--hairline) solid var(--field-line);
  border-radius: var(--radius-lg);
  padding: var(--panel-padding);
}

/* Превью и результат — один и тот же кадр: `object-fit: contain`, фото
   гостьи никогда не обрезается молча (история 27). Пустое поле вокруг —
   это грунт кадра, а не потерянный кусок фотографии. */
.tryon__frame {
  position: relative;
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--field-bg);
  border: var(--hairline) solid var(--field-line);
  border-radius: var(--radius-md);
}

.tryon__image {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* base.css сбрасывает `img` в `display: block` авторским правилом — оно
   перебивает встроенное `[hidden] { display: none }` браузера независимо
   от специфичности (тот же случай уже решён для `.nav-row__back[hidden]`
   в components.css). Без этой строки скрытая карточка превью иногда
   рисовала бы пустую рамку под текстом «Фото появится здесь». */
.tryon__image[hidden] {
  display: none;
}

.tryon__frame-empty {
  margin: 0;
  padding: 0 var(--space-lg);
  color: var(--field-text-faint);
  text-align: center;
}

.tryon__controls {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.tryon__upload {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: var(--space-sm) var(--space-base);
  border: var(--hairline) dashed var(--field-line-strong);
  border-radius: var(--radius-sm);
  background: var(--field-raise);
  color: var(--field-text);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--motion-surface), background-color var(--motion-surface);
}

.tryon__upload:hover {
  border-color: var(--color-lacquer);
}

.tryon__upload:focus-within {
  outline: var(--focus-width) solid var(--field-focus);
  outline-offset: var(--focus-offset);
}

.tryon__hint {
  margin: 0;
}

/* Согласие — настоящий чекбокс с постоянно видимым текстом рядом: он
   прямо называет внешний сервис и отсутствие хранения на сайте
   (история 25a). Квадрат — та же геометрия, что у множественного выбора
   карточек (`--checkbox-size`), а не новый размер. */
.tryon__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  cursor: pointer;
}

.tryon__consent-input {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: var(--checkbox-size);
  height: var(--checkbox-size);
  margin: 2px 0 0;
  display: grid;
  place-items: center;
  border: var(--stroke) solid var(--field-line-strong);
  border-radius: var(--radius-xs);
  background: var(--field-raise);
  transition: background-color var(--motion-surface), border-color var(--motion-surface);
}

.tryon__consent-input:checked {
  background: var(--color-lacquer);
  border-color: var(--color-lacquer);
}

.tryon__consent-input:checked::after {
  content: '';
  width: 9px;
  height: 6px;
  border-left: 2px solid var(--color-bone-surface);
  border-bottom: 2px solid var(--color-bone-surface);
  transform: rotate(-45deg) translateY(-1px);
}

.tryon__consent-input:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* Декоративный дубль квадрата не нужен: настоящий чекбокс уже несёт
   свою собственную рамку и галочку выше. */
.tryon__consent-mark {
  display: none;
}

.tryon__cost {
  margin: 0;
}

/* Тише главной кнопки: лак/инверсия у оффера метит ровно одно действие
   («the primary action», DESIGN.md → «Primary action»). И примерка, и
   отправка формы-заглушки — второстепенные действия рядом с ней, поэтому
   делят один сдержанный стиль вместо своей копии `.btn-primary`: контур,
   без заливки и свечения, полная ширина и та же типографика кнопки —
   узнаётся как кнопка, но не спорит с главным CTA за внимание. Собран из
   тех же `--field-*`, что и `.btn-primary`, поэтому на чернильной карточке
   примерки и на оксбладовом поле оффера выглядит верно без явного цвета. */
.btn-quiet {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--button-padding);
  border: var(--hairline) solid var(--field-line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--field-text);
  font-family: var(--font-text);
  font-size: var(--type-action-size);
  font-weight: var(--type-action-weight);
  line-height: var(--type-action-line);
  letter-spacing: var(--type-action-tracking);
  text-transform: var(--type-action-case);
  transition: background-color var(--motion-surface),
    border-color var(--motion-surface), transform var(--motion-press);
}

.btn-quiet:hover:not(:disabled) {
  background: var(--field-veil);
  border-color: var(--field-text);
}

.btn-quiet:active:not(:disabled) {
  transform: scale(var(--motion-press-scale));
}

.btn-quiet:disabled {
  color: var(--field-text-faint);
  border-color: var(--field-line);
  cursor: not-allowed;
}

/* Статус несёт значок и текст, а не только цвет (история 26). */
.tryon__status {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
}

.tryon__status[data-kind='error'] {
  color: var(--color-error);
}

.tryon__status[data-kind='pending'],
.tryon__status[data-kind='info'] {
  color: var(--field-text-muted);
}

.tryon__status[data-kind='success'] {
  color: var(--color-success);
}

.tryon__status-icon {
  flex: none;
  width: var(--space-base);
  height: var(--space-base);
  margin-top: 2px;
}

.tryon__recheck {
  align-self: flex-start;
  min-height: var(--tap-min);
  padding: var(--space-xs) 0;
  border: 0;
  background: none;
  color: var(--field-text-muted);
  font-family: var(--font-text);
  font-size: var(--type-sub-size);
  font-weight: 700;
  text-decoration: underline;
  transition: color var(--motion-surface);
}

.tryon__recheck:hover:not(:disabled) {
  color: var(--field-text);
}

.tryon__recheck:disabled {
  color: var(--field-text-faint);
  cursor: not-allowed;
}

/* ── Оффер (`screens/offer.js`) ──────────────────────────────────
   Оксбладовое поле во всю ширину (история 28): заголовок и кнопки —
   костяные (кнопка инвертирована самим полем через `--field-action-*`,
   см. tokens.css → `.field-oxblood`), тело — приглушённый костяной.
   Лаковое слово в заголовке сюда не переезжает вслед за результатом:
   лак — это яркий брат оксблада, тот же оттенок двумя интенсивностями,
   и на оксбладовом грунте не читается (DESIGN.md → «Colors» → «The
   accent»). Ни таймера, ни цены, ни выдуманной цифры здесь нет. */

.offer__tryon {
  margin-top: var(--space-lg);
}

.offer__intro {
  margin-top: var(--space-2xl);
}

.offer__eyebrow {
  color: var(--color-text-on-oxblood-muted);
}

.offer__title {
  margin-top: var(--space-sm);
}

.offer__body {
  margin-top: var(--space-base);
  color: var(--color-text-on-oxblood-muted);
}

.offer__app {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-top: var(--space-2xl);
}

.offer__app-link {
  text-decoration: none;
}

.offer__app-note {
  margin: 0;
  color: var(--color-text-on-oxblood-muted);
  text-align: center;
}

/* Форма-заглушка: линия сверху отделяет её от оффера, честная пометка —
   строкой под кнопкой, а не только атрибутом `data-stub` в разметке. */
.offer__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-base);
  margin-top: var(--space-2xl);
  padding-top: var(--space-2xl);
  border-top: var(--hairline) solid var(--field-veil-line);
}

.offer__form-note {
  margin: 0;
  color: var(--color-text-on-oxblood-muted);
  text-align: center;
}
