/* Zubok & Partners — общая основа для всех вариантов главной
   Требует variants/shared/tokens.css, подключённого раньше.
   Здесь ровно словарь .zp-* из .autopilot/home-variants/interfaces.md, плюс
   одна добавка ремонта формы — .zp-fields, сетка ряда полей внутри формы (§10).
   Вариантный CSS живёт под своим корневым классом (.v-memorandum / .v-chapters /
   .v-partner) и .zp-* глобально не переопределяет.

   Три правила, из-за которых страница выглядит референсом, а не «тёмной темой»:
   заливок нет — карточку отделяет волосяная линия, её фон равен фону страницы;
   теней нет — box-shadow только у фокусного кольца;
   радиус 2 px — скругления принадлежали рамке презентации, а не макету. */

/* ═══ 1. Сброс и корпус страницы ═══════════════════════════════════════ */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: var(--header-h);
  scrollbar-color: var(--ink-600) var(--ink-900);
  scrollbar-width: thin;
}

body {
  margin: 0;
  background-color: var(--ink-800);
  color: var(--text-hi);
  font-family: var(--font-text);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img,
svg,
video,
canvas { display: block; max-width: 100%; }

img { height: auto; }

button,
input,
select,
textarea { font: inherit; color: inherit; }

/* Поверхности, которые рисует браузер, — тоже часть системы. */
::selection {
  background-color: var(--brass-500);
  color: var(--ink-900);
}

:focus-visible {
  outline: var(--focus-w) solid var(--focus);
  outline-offset: var(--focus-offset);
}

/* ═══ 2. Служебное ═════════════════════════════════════════════════════ */

.zp-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.zp-skip {
  position: fixed;
  z-index: 300;
  inset-block-start: var(--s-4);
  inset-inline-start: var(--s-4);
  padding: var(--s-3) var(--s-5);
  border: var(--border) solid var(--brass-500);
  border-radius: var(--radius);
  background-color: var(--ink-900);
  color: var(--brass-400);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  translate: 0 calc(-100% - var(--s-8));
  transition: translate var(--dur-hover) var(--ease);
}

.zp-skip:focus { translate: 0 0; }

/* ═══ 3. Контейнер и мера строки ═══════════════════════════════════════ */

/* ≥1440 → контент 1320 при полях 60; ниже поля сужаются по брейкпоинтам (2.3). */
.zp-container {
  width: 100%;
  max-width: calc(var(--container) + var(--margin) * 2);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.zp-measure { max-width: var(--measure); }

/* ═══ 4. Типографика ═══════════════════════════════════════════════════ */

/* Капслок разрешён ровно в двух местах: .zp-label и .zp-card-title (2.2). */
.zp-label {
  margin: 0;
  color: var(--brass-500);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

.zp-h1,
.zp-h2,
.zp-h3 {
  margin: 0;
  color: var(--text-hi);
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}

.zp-h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); }
.zp-h2 { font-size: var(--fs-h2); line-height: var(--lh-h2); }
.zp-h3 { font-size: var(--fs-h3); line-height: var(--lh-h3); }

.zp-card-title {
  margin: 0;
  color: var(--champagne);
  font-family: var(--font-display);
  font-size: var(--fs-card-title);
  font-weight: 500;
  line-height: var(--lh-card-title);
  letter-spacing: var(--ls-card-title);
  text-transform: uppercase;
}

.zp-num {
  display: block;
  margin: 0;              /* на <p> браузер иначе даёт 48 px сверху и снизу */
  color: var(--brass-500);
  font-family: var(--font-display);
  font-size: var(--fs-num);
  font-weight: 500;
  line-height: var(--lh-num);
  font-variant-numeric: tabular-nums;
}

.zp-lead,
.zp-body,
.zp-small {
  margin: 0;
  font-family: var(--font-text);
  font-weight: 400;
  text-wrap: pretty;
}

.zp-lead  { color: var(--text-hi); font-size: var(--fs-lead);  line-height: var(--lh-lead); }
.zp-body  { color: var(--text-hi); font-size: var(--fs-body);  line-height: var(--lh-body); }
.zp-small { color: var(--text-lo); font-size: var(--fs-small); line-height: var(--lh-small); }

.zp-quote {
  margin: 0;
  padding-inline-start: var(--s-5);
  border-inline-start: var(--border-accent) solid var(--brass-500);
  color: var(--text-hi);
  font-family: var(--font-display);
  font-size: var(--fs-quote);
  font-style: italic;
  font-weight: 400;
  line-height: var(--lh-quote);
}

/* Кавычки не рисуются (2.6): гасим и авторские, и браузерные. */
.zp-quote > p { margin: 0; }
.zp-quote q::before,
.zp-quote q::after { content: none; }

/* ═══ 5. Линии и разделитель ═══════════════════════════════════════════ */

.zp-rule {
  block-size: var(--border);
  margin: 0;
  border: 0;
  background-color: var(--hairline-dark);
}

/* Линия во всю ширину с разрывом посередине; в разрыве — шеврон из знака Z.
   SVG подаётся маской, поэтому латунь остаётся токеном, а не запечена в файл. */
.zp-divider {
  position: relative;
  display: block;
  block-size: var(--s-4);
  margin: 0;
  border: 0;
  background-color: transparent;
  background-image: linear-gradient(
    to right,
    var(--hairline-dark) 0 calc(50% - var(--s-5)),
    transparent calc(50% - var(--s-5)) calc(50% + var(--s-5)),
    var(--hairline-dark) calc(50% + var(--s-5)) 100%
  );
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% var(--border);
}

.zp-divider::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 50%;
  inline-size: var(--s-5);
  translate: -50% 0;
  background-color: var(--brass-500);
  -webkit-mask: var(--mark-chevron) no-repeat center / contain;
  mask: var(--mark-chevron) no-repeat center / contain;
}

/* ═══ 6. Действия ══════════════════════════════════════════════════════ */

/* Единственное место в системе, где латунь становится заливкой, — ховер этой кнопки. */
.zp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  border: var(--border) solid var(--brass-500);
  border-radius: var(--radius);
  background-color: transparent;
  color: var(--brass-400);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-hover) var(--ease),
    border-color var(--dur-hover) var(--ease),
    color var(--dur-hover) var(--ease);
}

.zp-btn:hover {
  border-color: var(--brass-400);
  background-color: var(--brass-400);
  color: var(--ink-900);
}

/* Фокус читается иначе, чем ховер: ховер заливает кнопку латунью, фокус оставляет её
   спокойной и обводит кольцом. Кольцо приходит из общего правила :focus-visible. */

.zp-btn:disabled,
.zp-btn[aria-disabled="true"] {
  border-color: var(--hairline-card);
  color: var(--text-lo);
  cursor: not-allowed;
}

.zp-btn:disabled:hover,
.zp-btn[aria-disabled="true"]:hover {
  background-color: transparent;
  color: var(--text-lo);
}

.zp-link {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-2);
  color: var(--text-hi);
  font-family: var(--font-text);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  text-decoration: none;
  transition: color var(--dur-hover) var(--ease);
}

.zp-link::after {
  content: "\27F6";           /* длинная стрелка вправо, 2.6 */
  color: var(--brass-500);
  transition: color var(--dur-hover) var(--ease);
}

.zp-link:hover {
  color: var(--brass-400);
  text-decoration: underline;
  text-decoration-thickness: var(--border);
  text-underline-offset: 0.3em;
}

.zp-link:hover::after { color: var(--brass-400); }

/* ═══ 7. Шапка и навигация ═════════════════════════════════════════════ */

.zp-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  border-block-end: var(--border) solid var(--hairline-dark);
}

/* Подложка --ink-900 92 % + blur 12 живёт в псевдоэлементе, а не на самой шапке:
   backdrop-filter делает элемент containing block для fixed-потомков, и панель
   мобильного меню тогда раскрывается не на экран, а внутрь шапки. */
.zp-header::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background-color: color-mix(in srgb, var(--ink-900) 92%, transparent);
  -webkit-backdrop-filter: blur(var(--blur-header));
  backdrop-filter: blur(var(--blur-header));
}

.zp-header > .zp-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  min-block-size: var(--header-h);
}

/* Знак в шапке. Один и тот же во всех трёх: шапка — общая, и подменять
   в ней марку на другой знак значит менять общее, а не своё. */
.zp-brand {
  display: flex;
  flex: none;
  align-items: center;
  line-height: 0;
}

.zp-brand img {
  block-size: var(--s-6);
  inline-size: auto;
}

@media (max-width: 767px) { .zp-brand img { block-size: var(--s-5); } }

/* Кнопка шапки. Класс живёт в базе, а не в вариантах: пороги её появления —
   часть общей шапки, и три страницы обязаны вести себя одинаково. */
.zp-header__cta { flex: none; }

.zp-nav {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  margin: 0;
  padding: 0;
  list-style: none;
}

.zp-nav a {
  display: inline-block;
  padding-block: var(--s-2);
  border-block-end: var(--border) solid transparent;
  color: var(--text-hi);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  transition:
    color var(--dur-hover) var(--ease),
    border-color var(--dur-hover) var(--ease);
}

.zp-nav a:hover,
.zp-nav a[aria-current] {
  border-block-end-color: var(--brass-500);
  color: var(--brass-400);
}

/* ═══ 8. Мобильное меню — <details> + <summary>, без единой строки JS ═══
   Разметка: <details class="zp-menu"><summary class="zp-menu-toggle"></summary>
             <div> … ссылки … </div></details>
   Панель — всё, что внутри .zp-menu кроме .zp-menu-toggle. */

.zp-menu { position: relative; }

.zp-menu-toggle {
  position: relative;
  display: block;
  inline-size: var(--s-7);
  block-size: var(--s-7);
  margin-inline-end: calc(var(--s-3) * -1);
  list-style: none;
  cursor: pointer;
  background-color: transparent;
  background-image: linear-gradient(var(--brass-500), var(--brass-500));
  background-repeat: no-repeat;
  background-position: center;
  background-size: var(--s-5) var(--border);
  transition: background-size var(--dur-hover) var(--ease);
}

.zp-menu-toggle::-webkit-details-marker { display: none; }

.zp-menu-toggle::before,
.zp-menu-toggle::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--s-5);
  block-size: var(--border);
  background-color: var(--brass-500);
  transition:
    translate var(--dur-hover) var(--ease),
    rotate var(--dur-hover) var(--ease);
}

.zp-menu-toggle::before { translate: -50% calc(-50% - var(--s-2)); }
.zp-menu-toggle::after  { translate: -50% calc(-50% + var(--s-2)); }

.zp-menu[open] > .zp-menu-toggle { background-size: 0 var(--border); }
.zp-menu[open] > .zp-menu-toggle::before { translate: -50% -50%; rotate: 45deg; }
.zp-menu[open] > .zp-menu-toggle::after  { translate: -50% -50%; rotate: -45deg; }

.zp-menu > :not(.zp-menu-toggle) {
  position: fixed;
  z-index: 90;
  inset: var(--header-h) 0 0 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--s-5);
  padding: var(--s-8) var(--margin);
  overflow-y: auto;
  border-block-start: var(--border) solid var(--hairline-dark);
  background-color: var(--ink-900);
  overscroll-behavior: contain;
}

/* Пункты списком по центру экрана крупным кеглем (2.9).
   Кнопка внутри панели под это правило не попадает — она остаётся кнопкой. */
.zp-menu a:not(.zp-btn) {
  color: var(--text-hi);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: var(--lh-h3);
  text-decoration: none;
  transition: color var(--dur-hover) var(--ease);
}

.zp-menu a:not(.zp-btn):hover,
.zp-menu a:not(.zp-btn)[aria-current] { color: var(--brass-400); }

/* Телефон под пунктами (2.9): не пункт меню, а строка контакта. */
.zp-menu__tel {
  margin: 0;
  color: var(--brass-400);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

/* Вес селектора здесь не украшение: .zp-menu a:not(.zp-btn) выше — это (0,2,1),
   и набирает ссылку Playfair-ом прямо на элементе. Наследование от абзаца
   до неё не доходит, поэтому телефон возвращает себе шрифт сам и таким же весом. */
.zp-menu .zp-menu__tel a { font: inherit; color: inherit; text-decoration: none; }

.zp-menu__tel a:hover {
  text-decoration: underline;
  text-decoration-thickness: var(--border);
  text-underline-offset: 0.3em;
}

/* ── Порог шапки, один на все три варианта ─────────────────────────────
   Замер на реальной строке: знак 106 + навигация 795 + кнопка 245 и два
   промежутка по 32 — это 1210 px. При полях 48 такая строка требует окна
   в 1306 px, поэтому прежний порог и стоял на 1440: ниже него навигация
   уходила в гамбургер целиком. Цена оказалась не та: на ноутбуках 1280
   и 1366 корпоративный сайт встречал гамбургером, хотя места хватало.

   Ужимается промежуток навигации, а не состав шапки. Ниже 1440 он идёт
   шагом --s-5 вместо --s-6: навигация садится с 795 до 747, вся строка —
   до 1146, и ей довольно окна в 1242. Порог поставлен на 1260, а не на
   1280: медиазапрос меряет вьюпорт без классического скроллбара, и окно
   1280 в Windows отдаёт 1263 px. Запас 21 px — цена того, чтобы 1280
   попадало в порог наверняка.
   Кнопка шапки живёт до 768; ниже её место в панели меню — иначе на 375
   знак, кнопка и гамбургер не встают в строку. Правило одно и общее:
   вариантам переопределять его нечем и незачем. */
@media (min-width: 1260px) { .zp-menu { display: none; } }

@media (max-width: 1439px) {
  /* Семь пунктов на шаг теснее: промежуток внутри группы остаётся вдвое
     меньше промежутка между группами, и строка перестаёт упираться в поля. */
  .zp-nav { gap: var(--s-5); }
}

@media (max-width: 1259px) {
  .zp-nav { display: none; }
  /* Навигации нет — space-between развёл бы кнопку в середину строки. */
  .zp-header__cta { margin-inline-start: auto; }
}

/* Кнопка в панели меню — замена кнопке шапки, а не вторая такая же:
   пороги ровно дополняют друг друга, и одновременно их не бывает никогда. */
@media (max-width: 767px) { .zp-header__cta { display: none; } }
@media (min-width: 768px)  { .zp-menu a.zp-btn { display: none; } }

/* ═══ 9. Футер ═════════════════════════════════════════════════════════ */

.zp-footer {
  border-block-start: var(--border) solid var(--hairline-dark);
  background-color: var(--ink-900);
  color: var(--text-lo);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}

.zp-footer > .zp-container {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-7) var(--gutter);
  padding-block: var(--s-9);
}

/* Первая колонка футера — знак, название и адрес (copy-deck §9). */
.zp-footer__brand {
  display: grid;
  align-content: start;   /* иначе колонка растягивает строки на всю высоту футера */
  gap: var(--s-4);
  justify-items: start;
}

.zp-footer__brand img {
  inline-size: var(--s-10);
  max-inline-size: 100%;
  block-size: auto;
}

.zp-footer__brand p { margin: 0; max-width: 30ch; }

/* Строка дисклеймера и копирайта — четвёртый ряд футера во всю ширину.
   Правило живёт в базе: три варианта стилизовали её у себя по-разному,
   а это часть общего футера. */
.zp-footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-4) var(--s-7);
  grid-column: 1 / -1;
  padding-block-start: var(--s-6);
  border-block-start: var(--border) solid var(--hairline-dark);
}

.zp-footer__legal p { margin: 0; max-width: var(--measure); }

.zp-footer a {
  color: var(--text-lo);
  text-decoration: none;
  transition: color var(--dur-hover) var(--ease);
}

.zp-footer a:hover {
  color: var(--brass-400);
  text-decoration: underline;
  text-decoration-thickness: var(--border);
  text-underline-offset: 0.3em;
}

@media (max-width: 1023px) {
  .zp-footer > .zp-container { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  .zp-footer > .zp-container {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-6);
    padding-block: var(--s-8);
  }
}

/* ═══ 10. Форма ════════════════════════════════════════════════════════
   Поле без рамки: подпись капслоком сверху, ввод, волосяная линия снизу.
   Ошибка — <p role="alert"> внутри .zp-field, отдельного класса не заводим.

   Три дорожки поля — подпись / ввод / строка под полем — берутся из сетки
   ряда (grid-template-rows: subgrid). Поэтому у всех полей одного ряда
   подписи, линии ввода и подстрочные строки стоят на общих горизонталях:
   ни двухстрочная подпись у соседа, ни «Optional» под одним из полей
   больше не двигают чужой ввод. Ряды считает сетка, а не глазомер.

   Сетка ряда — .zp-form или .zp-fields (группа полей внутри формы).
   Промежутки внутри поля держат поля элементов, а не row-gap: пустая
   третья дорожка обязана быть нулевой высоты, иначе ряды без подстрочника
   разъезжаются с рядом, где он есть. */

.zp-form,
.zp-fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5) var(--gutter);
}

/* Поля тянутся во всю ширину формы, кнопка — нет. */
.zp-form > .zp-btn { justify-self: start; }

.zp-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  row-gap: 0;
}

@supports (grid-template-rows: subgrid) {
  .zp-form > .zp-field,
  .zp-fields > .zp-field {
    grid-row: span 3;
    grid-template-rows: subgrid;
  }
}

/* Подпись прижата к низу своей дорожки: короткая подпись стоит вплотную
   к своему полю, а не висит под потолком чужой двухстрочной. */
.zp-field__label {
  grid-row: 1;
  grid-column: 1;
  align-self: end;
  color: var(--brass-500);
  font-family: var(--font-text);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  transition: color var(--dur-hover) var(--ease);
}

.zp-field:focus-within .zp-field__label { color: var(--brass-400); }

.zp-field__control {
  grid-row: 2;
  grid-column: 1;
  inline-size: 100%;
  margin-block-start: var(--s-2);
  padding: var(--s-3) 0;
  border: 0;
  border-block-end: var(--border) solid var(--hairline-card);
  border-radius: 0;
  background-color: transparent;
  color: var(--text-hi);
  font-family: var(--font-text);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  caret-color: var(--brass-400);
  transition:
    border-color var(--dur-hover) var(--ease),
    box-shadow var(--dur-hover) var(--ease);
}

input.zp-field__control,
textarea.zp-field__control {
  -webkit-appearance: none;
  appearance: none;
}

/* Пол высоты — две строки текста плюс поля ввода: ниже textarea перестаёт
   читаться как место для рассказа о деле. Выше решает атрибут rows. */
textarea.zp-field__control {
  resize: vertical;
  min-block-size: calc(var(--lh-body) * 2em + var(--s-3) * 2);
}

/* Список раскрытого селекта рисует система; там, где цвета всё же наши,
   он обязан остаться тёмным — иначе светлый текст ляжет на светлый фон. */
.zp-field__control option {
  background-color: var(--ink-800);
  color: var(--text-hi);
}

.zp-field__control::placeholder {
  color: var(--text-lo);
  opacity: 1;
}

/* Селект теряет системную стрелку и получает шеврон из знака Z, развёрнутый
   вниз. Реализация одна на весь проект — вариантам её не переобъявлять.
   Шеврон живёт в дорожке ввода, а не приклеен к низу поля: с подстрочником
   «Optional» низ поля уезжает, а линия ввода остаётся на месте.
   Всё это — под :has(): без него снятую стрелку нечем заменить, и селект
   остаётся с родной системной. */
@supports selector(:has(*)) {
  select.zp-field__control {
    -webkit-appearance: none;
    appearance: none;
    padding-inline-end: var(--s-6);
  }

  /* Невыбранный селект читается как подсказка, а не как введённое значение. */
  select.zp-field__control:has(option[value=""]:checked) { color: var(--text-lo); }

  .zp-field:has(select)::after {
    content: "";
    grid-row: 2;
    grid-column: 1;
    justify-self: end;
    align-self: center;
    inline-size: var(--s-3);
    block-size: var(--s-2);
    margin-block-start: var(--s-2);
    rotate: 180deg;
    background-color: var(--brass-500);
    -webkit-mask: var(--mark-chevron) no-repeat center / contain;
    mask: var(--mark-chevron) no-repeat center / contain;
    pointer-events: none;
    transition: background-color var(--dur-hover) var(--ease);
  }

  .zp-field:focus-within:has(select)::after { background-color: var(--brass-400); }
}

.zp-field__control:hover { border-block-end-color: var(--brass-500); }

/* Фокус — линия латунью, утолщённая кольцом; outline не нужен, линия и есть
   индикатор. Ховер даёт линию 1 px --brass-500, фокус — 2 px --brass-400:
   состояния различаются и толщиной, и тоном. */
.zp-field__control:focus-visible {
  outline: none;
  border-block-end-color: var(--brass-400);
  box-shadow: 0 var(--border) 0 0 var(--brass-400);
}

.zp-field__control[aria-invalid="true"] { border-block-end-color: var(--danger); }

/* Подсказка под полем («Optional»): не подпись и не ошибка. Связывается
   с контролем через aria-describedby, а не подсовывается в placeholder —
   placeholder исчезает, как только человек начинает печатать. */
.zp-field__note,
.zp-field [role="alert"] {
  grid-row: 3;
  grid-column: 1;
  margin: var(--s-2) 0 0;
  font-family: var(--font-text);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}

.zp-field__note { color: var(--text-lo); }
.zp-field [role="alert"] { color: var(--danger); }

/* Дорожка под полем одна: ошибка приходит — подсказка уходит, иначе обе
   лягут в одну клетку. Ошибка важнее подсказки. */
.zp-field:has([role="alert"]) .zp-field__note { display: none; }

/* Состояние «отправлено»: заголовок Playfair шампань, строка Small, шеврон-разделитель. */
.zp-sent {
  display: grid;
  justify-items: center;
  gap: var(--s-4);
  padding: var(--s-7) var(--s-6);
  border: var(--border) solid var(--hairline-card);
  border-radius: var(--radius);
  text-align: center;
}

.zp-sent :is(h1, h2, h3, h4, p) { margin: 0; }

.zp-sent :is(h1, h2, h3, h4) {
  color: var(--champagne);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: var(--lh-h3);
}

/* Две строки под заголовком читаются по-разному: ответ фирмы — основным
   текстом, оговорка про прототип — Small и приглушённо. */
.zp-sent p {
  max-width: var(--measure);
  color: var(--text-hi);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.zp-sent p.zp-small {
  color: var(--text-lo);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}

.zp-sent .zp-divider { inline-size: 100%; }

/* ═══ 11. Фотография — единственная реализация дуотона ══════════════════
   grayscale(1) на самом снимке + слой --ink-800 в mix-blend-mode: color при 0.62.
   Вторых реализаций в вариантах быть не должно. */

.zp-photo {
  position: relative;
  display: block;
  overflow: hidden;
  border: var(--border) solid var(--hairline-card);
  border-radius: var(--radius);
  background-color: var(--ink-900);
  isolation: isolate;
}

.zp-photo > img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  filter: grayscale(1);
}

.zp-photo::after {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0;
  background-color: var(--ink-800);
  mix-blend-mode: color;
  opacity: 0.62;
  pointer-events: none;
}

/* Градиент лежит поверх дуотона и сам не смешивается: иначе текст на светлых
   участках снимка не читается (2.5). Снизу 85 %, кверху 25 %. */
.zp-photo--grad::before {
  content: "";
  position: absolute;
  z-index: 2;
  inset: 0;
  background-image: linear-gradient(
    to top,
    color-mix(in srgb, var(--ink-900) 85%, transparent),
    color-mix(in srgb, var(--ink-900) 25%, transparent)
  );
  pointer-events: none;
}

/* ═══ 12. Водяной знак ═════════════════════════════════════════════════
   Крупный знак Z цветом --ghost, контраст к фону 1.20:1. Один на секцию.
   Родитель должен быть position: relative, содержимое — над знаком.
   Ставить с aria-hidden="true". */

.zp-ghost {
  position: absolute;
  z-index: 0;
  inline-size: var(--s-11);
  aspect-ratio: var(--mark-aspect);
  background-color: var(--ghost);
  -webkit-mask: var(--mark-z) no-repeat center / contain;
  mask: var(--mark-z) no-repeat center / contain;
  pointer-events: none;
}

/* ═══ 13. Светлая секция ═══════════════════════════════════════════════
   Тёмная страница — норма, светлая секция — инструмент для длинного текста.
   Токены переопределяются внутри блока, поэтому весь словарь .zp-* переезжает
   на светлое сам: латунь текстом на --paper не появляется нигде. */

.zp-paper {
  --text-hi: var(--text-ink);
  --text-lo: var(--text-ink-lo);
  --champagne: var(--text-ink);
  --brass-400: var(--brass-800);
  --brass-500: var(--brass-800);
  --ghost: var(--paper-2);
  --hairline-dark: var(--hairline-light);
  --hairline-card: var(--hairline-light);
  --danger: var(--danger-ink);
  --focus: var(--brass-800);   /* --brass-400 на бумаге даёт 1.54:1 — кольца не видно */

  background-color: var(--paper);
  color: var(--text-ink);
}

/* --brass-800 на --paper даёт 5.38:1, а --ink-900 на --brass-800 — только 3.02:1,
   поэтому на светлом заливка ховера подписывается бумагой. */
.zp-paper .zp-btn:hover { color: var(--paper); }

.zp-paper::selection,
.zp-paper ::selection {
  background-color: var(--brass-800);
  color: var(--paper);
}

/* ═══ 14. Хвост ════════════════════════════════════════════════════════ */

/* Компоненты выше задают display, поэтому обычного [hidden] (0,1,0) им не хватает.
   Удвоенный атрибут даёт (0,2,0) и перебивает их без форсирования важности. */
[hidden][hidden] { display: none; }

/* Страховка на случай, если вариант всё же зашьёт длительность числом. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: var(--dur-instant);
    animation-delay: 0s;
    animation-iteration-count: 1;
    transition-duration: var(--dur-instant);
    transition-delay: 0s;
  }
}
