/* ============================================================
   SafePac — база: сброс, типографика, сетка, движение
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-kerning: normal;
}

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

/* ---------- Заголовки ----------
   Вес 500 везде. Bold в системе нет: акцент даётся размером и цветом,
   а не жирностью. Это прямо снято с референса и держит всю страницу. */

/* Заголовки набираются MagistralC: в нём один вес, и он светлый, поэтому
   иерархия здесь держится кеглем и воздухом, а не толщиной. В основном
   тексте он не используется — на 15 px штрих слишком тонкий для чтения. */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--ink-strong);
  text-wrap: balance;
}
/* h4 набран Montserrat, а у него начертания есть. Здесь шаг веса
   настоящий, а не подделанный: 600 против 400 в тексте. */
h4 {
  margin: 0;
  font-weight: 600;
  color: var(--ink-strong);
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); line-height: var(--lh-heading); letter-spacing: var(--track-heading); }
h2 { font-size: var(--fs-h2); line-height: var(--lh-heading); letter-spacing: var(--track-heading); }
h3 { font-size: var(--fs-h3); line-height: var(--lh-title);   letter-spacing: var(--track-heading); }
h4 { font-size: var(--fs-h4); line-height: var(--lh-title);   letter-spacing: var(--track-body); }

.display {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: 400;
  color: var(--ink-strong);
  line-height: var(--lh-display);
  letter-spacing: var(--track-display);
  text-wrap: balance;
}

p { margin: 0; max-width: var(--measure); }
p + p { margin-top: var(--s-4); }

.lead    { font-size: var(--fs-lead);  line-height: 1.55; color: var(--ink-muted); }
.small   { font-size: var(--fs-small); line-height: var(--lh-tight); }
.muted   { color: var(--ink-muted); }

/* ---------- Моношрифт: только измерения ----------
   Моно здесь не «костюм технаря». Он несёт миллиметры, допуски,
   плотность и артикулы, то есть настоящие числа. Больше нигде. */
.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 400;
  letter-spacing: var(--track-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}
.mono--strong { font-weight: 500; color: var(--ink); }

/* ---------- Ссылки ---------- */
a {
  color: var(--accent-ink);
  text-decoration: none;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color var(--t-fast) var(--ease-seat);
}
a:hover { color: var(--ink); text-decoration: underline; }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 2px;
  border-radius: var(--cutter);
}

/* ---------- Раскладка ---------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

.section { padding-block: var(--section-y); }
.section--sunk { background: var(--paper-sunk); }

/* Над заголовком воздуха больше, чем под ним. Один ритм на весь сайт. */
.section > * + * { margin-top: var(--s-5); }
.section > * + h2 { margin-top: var(--s-9); }
.section > h2 + * { margin-top: var(--s-5); }

/* minmax(0, 1fr) вместо 1fr: иначе длинное неразрывное содержимое
   раздувает трек и страница уезжает вбок на мобильном. */
.grid { display: grid; gap: var(--gutter); grid-template-columns: repeat(12, minmax(0, 1fr)); }

/* Автоколонки: min() не даёт треку стать шире экрана на узких вьюпортах. */
.cols { display: grid; gap: var(--gutter); grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr)); }

.stack   { display: flex; flex-direction: column; gap: var(--s-4); }
.stack-2 { display: flex; flex-direction: column; gap: var(--s-2); }
.row     { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }

/* ---------- Контур реза ----------
   Единственный способ показать глубину. Теней в системе нет:
   вырез не отбрасывает тень, у него есть кромка. */
.rule { border: 0; border-top: var(--hairline) solid var(--rule); margin: 0; }
.rule--soft { border-top-color: var(--rule-soft); }

/* ---------- Надзаголовок секции ----------
   Маркер квадрата — это метка реза на кромке. Регистр обычный,
   разрядки нет: тракинг-капс здесь чужой. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-eyebrow);
  line-height: 1;
  color: var(--ink-muted);
  letter-spacing: var(--track-body);
}
.eyebrow::before {
  content: '';
  width: var(--bullet); height: var(--bullet);
  background: var(--accent);
  flex: none;
}

/* ---------- Движение ----------
   Посадка: контур прочерчивается, содержимое садится в него.
   Один момент на страницу, а не эффект на каждом блоке. */
@media (prefers-reduced-motion: no-preference) {
  .seat { --seat-delay: 0ms; }

  .seat > .seat__edge {
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--t-cut) var(--ease-seat) var(--seat-delay);
  }
  .seat > .seat__body {
    opacity: 0;
    transform: translateY(8px);
    transition:
      opacity   var(--t-base) var(--ease-seat) calc(var(--seat-delay) + 120ms),
      transform var(--t-base) var(--ease-seat) calc(var(--seat-delay) + 120ms);
  }
  .seat.is-seated > .seat__edge { transform: scaleX(1); }
  .seat.is-seated > .seat__body { opacity: 1; transform: none; }
}

/* Появление блока: содержимое садится в полость со сдвигом 10 px.
   Класс .reveal вешает скрипт, поэтому без JS ничего не спрятано.
   Метка секции при этом прочерчивается слева направо — тот же рез,
   что и в остальной системе, поэтому движение читается как одно, а не
   как эффект, повешенный на каждый блок отдельно. */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    /* Ход 16 px читался как дрожание, а не как движение: на экране ноутбука
       это меньше строки текста. 28 px видно, но блок при этом не «прилетает»
       издалека — сдержанность системы сохраняется. */
    transform: translateY(28px);
    transition:
      opacity   var(--t-reveal) var(--ease-seat),
      transform var(--t-reveal) var(--ease-seat);
  }
  .reveal.is-in { opacity: 1; transform: none; }

  .reveal .eyebrow::before {
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--t-cut) var(--ease-seat) 120ms;
  }
  .reveal.is-in .eyebrow::before { transform: scaleX(1); }
}

/* Контент виден по умолчанию: без JS и при reduce ничего не прячется. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
}

/* ---------- Утилиты ---------- */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ---------------------------------------------------------- УЗКИЙ ЭКРАН
   Горизонтальной прокрутки у страницы быть не должно: на телефоне она
   читается как поломка, а не как способ что-то увидеть.

   clip, а не hidden: hidden создаёт контейнер прокрутки и ломает
   position: sticky у шапки. clip обрезает, не создавая контейнера. */
html { overflow-x: clip; }
body { overflow-x: clip; max-width: 100%; }

/* Ничто не шире своего места: картинки, ролики, встроенные кадры. */
img, video, iframe, svg, canvas { max-width: 100%; }

/* Длинное слово без пробелов — вторая частая причина выноса. */
@media (max-width: 560px) {
  body { overflow-wrap: anywhere; }
}

/* Неделимая единица: номер закона, размер, артикул. Перенос внутри них
   по дефису читается как ошибка вёрстки — «44-» на одной строке, «ФЗ»
   на следующей. Дефис при этом остаётся обычным, чтобы поиск находил
   строку как есть. */
.nowrap { white-space: nowrap; }

/* ------------------------------------------------ СЛУЖЕБНЫЕ КЛАССЫ
   Небольшой набор классов взамен инлайновых стилей.

   Зачем. В редакторе WordPress разметка блока пересобирается и
   сравнивается с сохранённой. Инлайновый style на обёртке ядрового
   блока в эту пересборку не попадает, и редактор объявляет содержимое
   повреждённым: «блок имеет неожиданное или неверное содержимое».
   Класс же описан в атрибутах блока и переживает пересборку.

   Поэтому в разметку страниц уходят классы, а не style. Значения те же
   самые, из общей шкалы ритма — никакой «магии на глаз» здесь нет. */

.u-mt-2 { margin-top: var(--s-2); }
.u-mt-4 { margin-top: var(--s-4); }
.u-mt-5 { margin-top: var(--s-5); }
.u-mt-6 { margin-top: var(--s-6); }
.u-mt-7 { margin-top: var(--s-7); }
.u-mt-8 { margin-top: var(--s-8); }
.u-mb-4 { margin-bottom: var(--s-4); }
.u-pt-5 { padding-top: var(--s-5); }

/* Снятие ограничения ширины у абзацев: по умолчанию строка держится
   в пределах --measure ради удобочитаемости, но подписи внутри карточек
   и ячеек таблиц должны занимать всю доступную ширину. */
.u-wide { max-width: none; }

.u-fs-h1   { font-size: var(--fs-h1); }
.u-fs-h3   { font-size: var(--fs-h3); }
.u-fs-h4   { font-size: var(--fs-h4); }
.u-fs-body { font-size: var(--fs-body); }

.u-align-start { align-items: start; }
.u-no-border-top { border-top: 0; }
.u-lead-gap { margin: var(--s-8) 0 var(--s-4); }

/* Сетка карточек с автозаполнением: используется там, где число
   элементов заранее не известно. */
.u-grid-auto { grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr)); }
