/* ==========================================================================
   Theme layer: multi-page CONTENT site (niu.relocationnz.com).
   Loaded THIRD, after site-core.css and theme-niu.css — it only adds the
   vocabulary those two lack and overrides them where a 72-page content site
   needs different behaviour than a single landing page.

   Why this file exists: site-core.css is a landing-page vocabulary (.hero,
   .ledger, .program-card, .signup). It has no prose typography, no site-wide
   navigation, no breadcrumbs and no language switcher — all of which a copy of
   a university website needs on every page.

   ---------------------------------------------------------------------------
   THE SYSTEM — "the registry"

   Replaces the previous system, which was the HBS Online course pages rebuilt
   in navy. That one was competent but borrowed: it made the site look like an
   American business school rather than like what it is. The job of these pages
   is not to impress, it is to be believed — a reader is checking whether the
   agreement, the RPL, the level and the credits are real. So the organising
   metaphor is a certified academic record, not a magazine spread.

   Three surfaces, one job each, and nothing else gets a background:
     --paper   white       the reading surface
     --navy    field       section plate, header, footer
     --stock   #EBE7DF     the checkable facts (.registry, Q&A)

   The one place the system raises its voice is .registry: the pair of
   institutions, the level, the credits. The product is literally a pair — two
   universities, two documents, two countries — so the block is built as a pair.
   Everything around it stays quiet.

   What was deliberately dropped from the previous system, as template chrome
   that appears on any generated page regardless of subject: uppercase +
   letter-spaced nav and label chips, the boxed gold language switcher, and the
   translateX(-0.06em) optical shift (which existed only to rescue headings set
   at line-height 1.0).
   ========================================================================== */

:root {
  /* Ink moves from neutral #232323 to a warm dark. This is measured, not
     taste: --navy sits at 2.80% lightness against the old ink's 1.68%, which
     is why an inline navy link read as bold black and why --navy-lit had to be
     invented. A warm ink adds a hue difference to the weak lightness one, so
     blue reads as blue. The two-tier accent survives the change and is still
     required — the numbers, against the ink:

       crimson  #a41034 / ink #232323   2.02   <- the distance HBS designed
       navy-lit #17529B / ink #241F1B   2.11   <- reproduced here
       navy     #0B2E5C / ink #241F1B   1.21   <- still merges; do not swap

     Readability: ink/paper 16.3, ink/stock 13.2, navy-lit/paper 7.73 (AAA),
     navy-lit/stock 6.27 (AA). Gold on paper is 1.83 — it physically cannot
     carry text on a light surface, which is why gold stays heraldic and only
     ever appears on navy (7.37). */
  --ink: #241F1B;
  --ink-soft: #5B534B;

  /* The third surface. Only .registry and the Q&A blocks may use it; if a
     second kind of card ever takes it, this system has failed and turned into
     the generic card kit it was built to avoid. */
  --stock: #EBE7DF;

  /* Шкала навью: четыре ступени поля, от записи к намерению.

     Цвета НЕ новые — тема уже несла ровно эти четыре значения, просто нигде не
     была названа шкалой. Измеренная светлота: L* 9.7 / 19.2 / 26.5 / 35.2, то
     есть шаги +9.5, +7.2, +8.7 — ряд уже равномерный, подгонять было нечего.
     Имена 1–4 нужны затем, чтобы ступенью можно было пользоваться как позицией
     в ряду, а не подбирать оттенок на глаз.

     Читаемость на каждой ступени (белый / stock как краска / золото):
       navy-1  17.24 / 13.98 / 9.44
       navy-2  13.47 / 10.92 / 7.37
       navy-3  10.60 /  8.60 / 5.80
       navy-4   7.73 /  6.27 / 4.23
     Пятой ступени нет сознательно: следующая по шагу дала бы stock ≈ 4.6 и
     золото ≈ 3.2 — на границе, а поле должно держать краску с запасом.

     Правя любое из четырёх значений в theme-niu.css, проверяй ряд целиком:
     смысл шкалы в равномерности шага, а не в самих оттенках. */
  --navy-1: var(--navy-deep);
  --navy-2: var(--navy);
  --navy-3: var(--navy-lit-deep);
  --navy-4: var(--navy-lit);

  /* Golos Text is not a neutral pick: it was drawn for Russian institutional
     documents, which is the exact register these pages need, and Cyrillic is
     its native script rather than an extension. It replaces Montserrat — the
     default geometric sans of the last decade, and shared with the landings,
     which left the content site with no voice of its own.
     Literata sets the long text: a book face with real Cyrillic and a variable
     optical size. Both are requested by the <link> that build_niu_site.mjs
     emits, NOT by an @import here: an @import inside the third stylesheet
     would not start downloading until this file had itself parsed, putting the
     fonts two round trips behind the text they set. */
  --font-ui: "Golos Text", "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Literata", Georgia, serif;

  /* Hairlines as alpha rather than flat greys, so they hold over both paper
     and stock without a second set of values. */
  --hairline: rgba(36, 31, 27, 0.14);
  --hairline-strong: rgba(36, 31, 27, 0.34);

  --sp-sm: clamp(12px, 2.5vw, 18px);
  --sp-md: clamp(32px, 2.5vw, 56px);
  --sp-lg: clamp(56px, 5vw, 104px);

  /* 34em of Literata at its clamped size lands near 66 characters. Media and
     tables are allowed past it: an image inside a 34em column is too small to
     be worth including. */
  /* Мера чтения. Была 34em и по спецификации считалась «≈66 знаков», но это
     не подтвердилось замером: на живых страницах строка держала 55–58 — em
     считается от кегля, а Literata в кириллице шире, чем закладывалось, и
     колонка недобирала около 15%. 41em измеренно дают ~70 знаков, верхняя
     часть комфортного диапазона (45–75).

     Следствие: --measure-wide (46em) теперь всего на 12% шире меры, и разница
     между колонкой прозы и таблицей почти стёрлась. Это осознанно — страница
     стала спокойнее, а ширин на ней стало меньше. */
  --measure: 41em;
  --measure-wide: 46em;
}

/* ---------------------------------------------------------------- overrides

   theme-niu.css sets the page background to cream, the body font to Montserrat
   and h1/h2/h3 to uppercase 900 — all written as literal values rather than
   through tokens, so each has to be overridden by name here. The landings keep
   all of it; they never load this file.
   -------------------------------------------------------------------------- */

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: clamp(17px, 1.3vw, 19px);
  line-height: 1.62;
  font-optical-sizing: auto;
}

.site-header h1,
.site-header h2,
.site-header h3,
.page-head h1,
.prose h2,
.prose h3,
.prose h4,
.prose h5,
.qa-section > h2 {
  font-family: var(--font-ui);
  text-transform: none;
}

/* ---------------------------------------------------------------- site header */

/* Single row: crest — navigation — actions. Below 1080px seven section links
   genuinely cannot share a row with the crest and the buttons, so navigation
   drops to a second row. */
.site-header .header-inner {
  display: flex;
  align-items: center;
  gap: 18px;
}

.site-header .brand {
  text-decoration: none;
  display: block;
  flex-shrink: 0;
}

.site-header .brand-logo {
  height: 52px;
  width: auto;
  display: block;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  margin-left: auto;
}

/* Compact CTA: the landing's default button padding costs 34px of the row. */
.header-actions .btn {
  font-family: var(--font-ui);
  padding: 10px 18px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 22px);
  flex-wrap: wrap;
  /* Without min-width:0 a flex item lays out at max-content and pushes the
     header wider than the viewport. */
  min-width: 0;
}

/* Sentence case at 14px, not the tracked-out uppercase chips this file used to
   carry: caps labels are the single commonest tell of a templated page, and
   Russian in caps is measurably slower to read. */
.site-nav a {
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, 0.82);
  text-decoration: none;
  padding: 5px 0;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}

.site-nav a:hover {
  color: #fff;
}

/* aria-current marks the section the page belongs to, not just the exact URL —
   an article deep in /akademicheski-centr still highlights that section. Gold
   in its heraldic role: it marks, it does not decorate. */
.site-nav a[aria-current] {
  color: #fff;
  border-bottom-color: var(--gold);
}

/* Two letters and a state. The previous switcher put both languages in
   gold-bordered uppercase boxes, which made a minor control the loudest thing
   in the header. */
.lang-switch {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
}

.lang-switch a,
.lang-switch span {
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  text-decoration: none;
}

.lang-switch a {
  color: rgba(255, 255, 255, 0.7);
}

.lang-switch a:hover {
  background: none;
  color: #fff;
}

/* The current language is a <span>, not a link: a page with no translation
   must not offer a dead one. */
.lang-switch span {
  color: var(--gold);
  cursor: default;
}

/* One radius across the system. */
.btn,
.content-card,
.registry,
.prose img {
  border-radius: 3px;
}

/* ------------------------------------------------- navigation disclosure

   Mobile-first: the base rules below ARE the phone. The menu is a collapsed
   <details>, its panel drops out of the sticky header, and the desktop row is
   the enhancement added back at 901px.

   The desktop override is the fragile part and needs both halves.

   Old engines hide a closed disclosure with the UA rule
       details > *:not(summary) { display: none }
   which an author `display` defeats. Chrome 131+, Safari 18.4+ and Firefox
   139+ instead route the children through ::details-content with
   `content-visibility: hidden`, which an author `display` does NOT defeat —
   the panel stays invisible however it is displayed. So the block at 901px
   writes both: a display for the old rule, and a content-visibility (plus the
   block-size the animation spec zeroes) for the new pseudo-element.

   If an engine still collapses the desktop menu, the fallback is to emit the
   `open` attribute from the generator and strip it with four inline lines at
   narrow widths — with JS off that leaves an expanded menu, which is correct. */

/* Phone row 1 is crest + burger, row 2 is the two CTAs. The wrap lives here and
   not in the site-header block because it exists only for this layout: above
   901px the header is a single nowrap row again. */
.site-header .header-inner {
  flex-wrap: wrap;
}

.nav-disclosure {
  order: 2;
  margin-left: auto;
}

.header-actions {
  order: 3;
  width: 100%;
  margin-left: 0;
}

/* 44px is the tap target, not the icon: the bars are 20px wide inside it. */
.nav-burger {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0;
  cursor: pointer;
  border-radius: 3px;
}

.nav-burger::-webkit-details-marker {
  display: none;
}

.nav-burger:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Three bars out of one element: the middle bar is the box, the outer two are
   its pseudo-elements. Open turns the set into a cross. */
.nav-burger-bars {
  position: relative;
}

.nav-burger-bars,
.nav-burger-bars::before,
.nav-burger-bars::after {
  display: block;
  width: 20px;
  height: 2px;
  background: #fff;
  transition: transform 0.18s, background-color 0.18s;
}

.nav-burger-bars::before,
.nav-burger-bars::after {
  content: '';
  position: absolute;
  left: 0;
}

.nav-burger-bars::before {
  transform: translateY(-6px);
}

.nav-burger-bars::after {
  transform: translateY(6px);
}

.nav-disclosure[open] .nav-burger-bars {
  background: transparent;
}

.nav-disclosure[open] .nav-burger-bars::before {
  transform: rotate(45deg);
}

.nav-disclosure[open] .nav-burger-bars::after {
  transform: rotate(-45deg);
}

/* The panel leaves the header row and spans the viewport under it. It is
   anchored to the header rather than to .header-inner, which is what makes it
   full-bleed; the header is already positioned (theme-niu.css gives it
   position: sticky), so it is the containing block without a new declaration. */
.nav-disclosure > .site-nav {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  background: var(--navy-deep);
  border-top: 1px solid rgba(232, 184, 106, 0.18);
  padding: 6px max(24px, calc((100vw - var(--maxw)) / 2 + 24px)) 14px;
  box-shadow: 0 14px 28px rgba(6, 27, 54, 0.28);
}

.nav-disclosure > .site-nav a {
  padding: 13px 0;
  font-size: 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* On the phone the current section is marked by the colour of its label, not by
   a 2px gold rule under a full-width row: there that rule reads as a divider,
   which these rows already have. */
.nav-disclosure > .site-nav a[aria-current] {
  color: var(--gold);
  border-bottom-color: rgba(255, 255, 255, 0.08);
}

.nav-disclosure > .site-nav a:last-child {
  border-bottom: none;
}

/* 1120px is measured, not chosen: crest 78 + nav 576 + actions 378 + two 18px
   gaps + 48 of .wrap padding = 1116. Below it the six links cannot share the
   row with the buttons, and the burger is the honest answer — a ragged
   three-row menu was what the old eight-item nav did here.

   The nav gap is capped at 18px rather than the 22px the rest of the file uses.
   At clamp(...,1.6vw,22px) the gap grows with the viewport while .wrap stays at
   1120, so the menu fitted one row at 1280 and broke at 1440 — wider window,
   broken header. */
@media (min-width: 1120px) {
  .site-header .header-inner {
    flex-wrap: nowrap;
  }

  .nav-disclosure {
    order: 0;
    margin-left: 0;
    flex: 1 1 auto;
    min-width: 0;
  }

  .header-actions {
    order: 0;
    width: auto;
    margin-left: auto;
  }

  .nav-burger {
    display: none;
  }

  /* Both halves of the override — see the note at the top of this block. */
  .nav-disclosure > .site-nav {
    display: flex;
  }

  .nav-disclosure::details-content {
    content-visibility: visible;
    block-size: auto;
  }

  /* Меню центрируется в своей области, а не липнет к гербу.

     Замерено до правки: 18px между гербом и первым пунктом и 196px пустоты
     справа — вся свобода ряда копилась в одном месте, и герб оказывался
     зажат. Центрирование раздаёт её поровну, по ~107px с каждой стороны.

     Центрировать по середине страницы, а не внутри области, нельзя: меню
     тогда доходит до 761px при кнопках, начинающихся на 774px. */
  .nav-disclosure > .site-nav {
    position: static;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    flex-wrap: nowrap;
    gap: clamp(12px, 1.4vw, 18px);
    background: none;
    border-top: none;
    padding: 0;
    box-shadow: none;
  }

  .nav-disclosure > .site-nav a {
    padding: 5px 0;
    font-size: 13.5px;
    border-bottom: 2px solid transparent;
  }

  .nav-disclosure > .site-nav a[aria-current] {
    color: #fff;
    border-bottom-color: var(--gold);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-burger-bars,
  .nav-burger-bars::before,
  .nav-burger-bars::after {
    transition: none;
  }
}

/* ---------------------------------------------------------------- page head */

.page-head {
  background: var(--navy);
  color: #fff;
  padding: var(--sp-md) 0;
  position: relative;
  overflow: hidden;
  /* No closing rule: a colour band ends with the canvas change itself. */
  border-bottom: none;
}

/* The seal as a watermark on the plate — the stamp on the record.

   No cropping: --logo-img in theme-niu.css is NOT the same asset as
   /assets/niu-logo.png in the header. The header file is 612x408 and carries
   the wordmark beside the shield; the token is a 500x500 shield alone, ink
   filling 12.6-86.8% of the frame. Anything that clips it is cutting empty
   margin and hiding the crest.

   It is drawn navy-and-gold on a navy field, so it reads as a texture rather
   than as an image, and the opacity is the whole of its presence. */
.page-head .hero-seal {
  width: 460px;
  height: 460px;
  left: auto;
  right: -110px;
  transform: translateY(-50%);
  opacity: 0.10;
}

.page-head .wrap {
  position: relative;
  z-index: 1;
}

/* Weight 600 at line-height 1.05, not 700 at 1.0. Zero leading is a poster
   setting; across 72 pages of it the site shouts. The optical shift that used
   to compensate for it is gone with it. */
.page-head h1 {
  color: #fff;
  font-size: clamp(32px, 4.6vw, 56px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  transform: none;
  max-width: 16em;
}

/* The lede is the first place the serif appears — a deck under a headline gets
   the same long-form voice as the article it introduces. */
/* Лид короткий не по CSS, а по разметке: генератор печатает сюда первое
   предложение описания (ledeOf в build.mjs). Обрезка строками жила здесь и
   была убрана — line-clamp рвёт на середине слова, и «…предоставить
   студентам…» на главной читалось как поломка. */
.page-head .page-lede {
  margin: 0.7em 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(18px, 1.5vw, 21px);
  line-height: 1.5;
  letter-spacing: 0;
  max-width: 40em;
  color: rgba(255, 255, 255, 0.86);
}

/* Нижний предел высоты: после обрезки лида плашка на большинстве страниц
   совпадает сама с собой, и min-height подтягивает к ней те, где заголовок в
   одну строку. Длинному заголовку расти по-прежнему можно — обрезать название
   статьи ради ровного канта было бы хуже прыжка. */
.page-head {
  min-height: 268px;
}

@media (max-width: 700px) {
  .page-head {
    min-height: 330px;
  }
}

/* Длинный заголовок набирается мельче.

   Заголовок на 100 знаков в 56px занимает четыре строки и растит плашку до
   499px там, где у большинства страниц 268 — это и есть главный остаток
   «прыжка» после того, как лид стал коротким. Но дело не только в прыжке:
   публикации давно набирают длинные заголовки мельче коротких, потому что
   плакатный кегль на длинной фразе мешает её прочесть.

   Порог — 60 знаков, за ним 19 страниц из 68. Резать сам заголовок нельзя:
   название статьи важнее ровного канта. */
.page-head--long h1 {
  font-size: clamp(26px, 3.1vw, 38px);
  line-height: 1.12;
  max-width: 22em;
}

/* Герб рядом с заголовком главной.

   Знак строчный (inline-block по базовой линии), а НЕ ячейка флексбокса.
   Флексбокс тут и был сначала, и на телефоне он ломался: заголовок переносится
   на две строки, знак уезжает в собственный ряд и толкает лид на 23px вниз.
   Строчный элемент просто идёт за последним словом последней строки, где бы
   она ни оказалась.

   Отрицательный нижний отступ — суть правила, а не подгонка. Он опускает знак
   ниже базовой линии и при этом уменьшает его вклад в высоту строки, поэтому
   знак ложится в просвет над лидом, опираясь на него, и ничего не двигает.
   Величина в em, поэтому на уменьшенном кегле длинного заголовка пропорция
   сохраняется.

   Сам файл — 612×408 с прозрачностью, тот же, что в шапке: фотография под
   знаком просвечивает, подложки ему не нужно. */
.page-head h1 .hero-mark {
  display: none;
}

/* На телефоне знак не показывается, и это не упущение, а измерение.

   На 375px русскому заголовку остаётся 24px свободных, английскому на 320px —
   43px, а знаку нужно 68 вместе с отбивкой. Он не помещается, вызывает перенос
   строки и толкает лид на 35px вниз — ровно то, чего быть не должно. Сделать
   его меньше 24px значит показать нечитаемое пятно.

   При этом герб не пропадает: он стоит в липкой шапке прямо над плашкой, в
   паре сантиметров выше. Дублировать его там, где для этого нет места, незачем.

   Порог 700px — уже существующий в этом файле: на нём же переключается
   градиент вуали и кроп фотографии. */
@media (min-width: 700px) {
  .page-head h1 .hero-mark {
    display: inline-block;
    height: 1.15em;
    width: auto;
    margin-left: 0.4em;
    margin-bottom: -0.22em;
    vertical-align: baseline;
  }
}

.page-meta {
  margin-top: 20px;
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  font-family: var(--font-ui);
  font-size: 13px;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.7);
}

/* Publication data is not something to celebrate in the accent colour. */
.page-meta strong {
  color: #fff;
  font-weight: 500;
}

/* Фотография на плашке главной.

   Четвёртой сущности с фоном не появляется: снимок ложится внутрь .page-head,
   уже объявленного холста `navy`, и меняет не структуру, а то, чем этот холст
   закрыт. Плашка и так `position: relative; overflow: hidden`, поэтому фото не
   потребовало ни новых свойств, ни обёрток.

   Вуаль — не украшение, а средство читаемости, и это именованное исключение в
   системе: белый текст поверх фотографии без неё не проходит по контрасту.
   Числа измерены на самом тёмном пикселе под текстом (снимок сумеречный, левая
   часть — тёмные склоны): лид 8.6:1 при норме 4.5, h1 13:1 при норме 3.
   Поэтому вуаль плотная слева, где стоит текст, и сходит на нет справа, где
   остаётся видна панорама. На телефоне градиент вертикальный — текст там во всю
   ширину, и боковой градиент оставил бы половину строки на светлом небе.

   Золота здесь нет ни в каком виде: на фотографии оно было бы декоративным, а
   в системе оно геральдическое. По той же причине на странице с фото не
   рисуется герб. */

.page-head--photo {
  background: var(--navy-deep);
}

.hero-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-photo picture,
.hero-photo img {
  display: block;
  width: 100%;
  height: 100%;
}

.hero-photo img {
  object-fit: cover;
  /* Горизонт снимка выше середины: при обрезке по высоте держим горы, а не
     передний план. */
  object-position: 50% 35%;
}

/* Вуаль отдельным слоем, а не фильтром на картинке: фильтр пришлось бы
   пересчитывать при каждой смене снимка, а градиент работает с любым. */
.hero-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(6, 27, 54, 0.62) 0%, rgba(6, 27, 54, 0.88) 100%);
}

/* Герб поверх фотографии — украшение. См. шапку блока. */
.page-head--photo .hero-seal {
  display: none;
}

/* Плашка с фотографией выше обычной: снимку нужна высота, чтобы быть снимком,
   а не полоской. Но не во весь экран — это страница-документ, а не афиша. */
.page-head--photo {
  padding: calc(var(--sp-md) * 1.4) 0 calc(var(--sp-md) * 1.2);
}

/* Служебная строка на плашке с фото светлее обычной. Она стоит ниже и правее
   всего остального, то есть там, где вуаль слабее всего: при штатных 0.7 белого
   замер дал 3.79:1 против нормы 4.5. */
.page-head--photo .page-meta {
  color: rgba(255, 255, 255, 0.88);
}

@media (min-width: 701px) {
  .hero-photo::after {
    background: linear-gradient(
      90deg,
      rgba(6, 27, 54, 0.93) 0%,
      rgba(6, 27, 54, 0.89) 42%,
      rgba(6, 27, 54, 0.62) 100%
    );
  }

  .page-head--photo {
    padding: calc(var(--sp-md) * 1.6) 0 calc(var(--sp-md) * 1.4);
  }
}

/* ---------------------------------------------------------------- breadcrumbs */

/* Крошки прилипают под шапкой, когда плашка заголовка уходит вверх: иначе по
   мере чтения длинной страницы человек теряет, где он находится, а до меню
   надо возвращаться наверх.

   top считается от --header-h, которую ставит инлайн-скрипт из build.mjs:
   высота шапки зависит от языка (на 375px русская 186px, английская 137px), и
   захардкоженное значение одному из языков соврёт. Соврав в меньшую сторону,
   оно спрячет прилипшие крошки под шапку — навигация исчезла бы ровно там, где
   её добавляли. Значения ниже — запасные, на случай выключенного JS.

   z-index 40 против 50 у шапки: крошки наезжают на контент, но уходят под
   шапку, а не поверх неё. Фон обязателен — без него текст страницы просвечивал
   бы сквозь прилипшую полосу. */
.breadcrumbs {
  position: sticky;
  top: var(--header-h, 186px);
  z-index: 40;
  background: var(--paper);
  padding: 12px 0;
  border-bottom: 1px solid var(--hairline);
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
}

@media (min-width: 480px) {
  .breadcrumbs {
    top: var(--header-h, 137px);
  }
}

@media (min-width: 900px) {
  .breadcrumbs {
    top: var(--header-h, 148px);
  }
}

@media (min-width: 1120px) {
  .breadcrumbs {
    top: var(--header-h, 87px);
  }
}

.breadcrumbs ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.breadcrumbs a {
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--hairline-strong);
}

.breadcrumbs a:hover {
  color: var(--navy-lit);
  text-decoration-color: var(--navy-lit);
}

.breadcrumbs li + li::before {
  content: "/";
  margin-right: 8px;
  color: var(--hairline-strong);
}

/* -------------------------------------------------- навигация по разделу

   Полоса академического центра — третий липкий слой под шапкой и крошками.

   Тон здесь НЕ шкала. В .about ступени --navy-1…4 кодируют позицию в ряду из
   четырёх; тут пунктов шесть, ряд по смыслу не упорядочен, а пятой ступени в
   системе нет сознательно. Поэтому поле одно — самая глубокая ступень, а
   активный пункт на ступень светлее плюс золотая ленточка сверху: та же
   механика, что у активной закладки слайдера, и тот же маркер текущего раздела,
   что в главном меню. Глубже шапки специально: два прилипших навью-слоя одного
   тона слились бы в одну полосу.

   Ниже 900px полоса НЕ липнет. Счёт: на 375px русская шапка 186px + крошки ~42 +
   полоса ~44 = 272 из 667, то есть 41% экрана под навигацией, а на статье крошек
   четыре и они переносятся на две-три строки. На 1120px сумма 87 + 42 + 44 = 173
   из 900 — 19%, это уже плата за дело. Полоса при этом никуда не девается: она
   стоит сразу под крошками и видна при входе на страницу. */

/* Нижний предел высоты плашки на страницах раздела.

   Под плашкой стоит липкая полоса, и её место на экране складывается из высоты
   плашки. Плашка же росла от длины заголовка: на 1440 «Аналитика цифровой
   экономики» давала 268px, двухстрочные подразделы 299, хаб 309. Полоса
   оказывалась на 41px ниже или выше — и прыгала под курсором при переходе ПО
   НЕЙ ЖЕ, то есть ровно в тот момент, когда по ней целятся дважды подряд.

   Значения измерены по всем 13 страницам раздела на обоих языках, берётся
   максимум интервала. Ступени, а не формула: до 900px высота падает с шириной
   (переносы уходят), выше — растёт (кегль заголовка и поля идут по vw), одной
   зависимости здесь нет.

   Ниже 700px предела нет намеренно. Там полоса и так не липнет, а выравнивание
   обошлось бы в 214px пустого навью на 375: плашка под коротким заголовком
   раздувалась бы вдвое. Остаточный разброс на телефоне даёт не плашка, а
   крошки — на узком экране они переносятся на разное число строк, и лечится
   это уже резервом высоты под три строки крошек на всех 68 страницах сайта.

   Перемерять при смене заголовков раздела: удлинившийся h1 снова вылезет за
   предел, и полоса снова начнёт прыгать — молча, потому что страница при этом
   выглядит целой. Приём не новый, у .page-head уже есть свой min-height. */
@media (min-width: 700px) {
  .page-head--section {
    min-height: 245px;
  }
}

@media (min-width: 900px) {
  .page-head--section {
    min-height: 275px;
  }
}

@media (min-width: 1120px) {
  .page-head--section {
    min-height: 292px;
  }
}

/* Выше 1280 ступени кончаются: дальше высота растёт только от вертикальных
   полей плашки, а они идут по тому же --sp-md. Формула вместо ступеней
   доводит предел до 2240px, где clamp упирается в потолок и рост прекращается
   сам. +239, а не +237: на 1399px ровный расчёт недобирал пиксель. */
@media (min-width: 1280px) {
  .page-head--section {
    min-height: calc(2 * var(--sp-md) + 239px);
  }
}

.section-nav {
  background: var(--navy-1);
  /* z-index 39: полоса уходит под крошки (40) и шапку (50), а не наезжает. */
  z-index: 39;
}

.section-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: stretch;
  /* Шесть подписей в ряд на телефоне не помещаются. Полоса прокручивается, а не
     переносится: перенос ломает чтение «это один ряд» и на каждом языке рвётся
     в своём месте. */
  overflow-x: auto;
  scrollbar-width: none;
}

.section-nav ul::-webkit-scrollbar {
  display: none;
}

.section-nav a {
  display: flex;
  align-items: center;
  gap: 6px;
  /* 0.7 белого — та же нижняя граница, что у закладок слайдера: ниже подпись
     перестаёт проходить норму на светлых ступенях навью. */
  color: rgba(255, 255, 255, 0.7);
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  padding: 12px 14px 11px;
  min-height: 44px;
  white-space: nowrap;
  transition: color 0.15s, background-color 0.15s;
}

.section-nav a:hover {
  color: #fff;
}

.section-nav a[aria-current='page'] {
  color: #fff;
  background: var(--navy-2);
  /* Ленточка сверху, а не подчёркивание: подчёркивание в полосе ссылок читается
     как оформление ссылки, а не как «вы здесь». */
  box-shadow: inset 0 3px 0 var(--gold);
}

.section-nav a:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* Знак оглавления. Гаснет и разгорается вместе с подписями — он часть строки, а
   не самостоятельная картинка, поэтому currentColor и никакого своего цвета. */
.section-nav-home a {
  padding-left: 16px;
  padding-right: 16px;
}

.section-nav-home svg {
  display: block;
}

/* Выход из раздела («Преподаватели» ведут в «Команду»). Отделён волосяной
   линией и небольшим отступом — пункт, уводящий со страницы раздела, не должен
   читаться как ещё один его подраздел.

   Раньше здесь стоял margin-left:auto, и пункт улетал к правому краю: на
   широком экране он оказывался в полусотне пикселей от остальных, вне ряда, и
   читался как чужой элемент чужой полосы, а не как выход из этой. Отступ должен
   отделять, а не изгонять. */
.section-nav-exit a {
  margin-left: 14px;
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.6);
}

@media (min-width: 900px) {
  .section-nav {
    position: sticky;
    /* Запасные значения на случай выключенного JS — по образцу .breadcrumbs.
       Соврав в меньшую сторону, top спрятал бы полосу под крошки. */
    top: calc(var(--header-h, 148px) + var(--crumbs-h, 46px));
  }

  .section-nav a {
    font-size: 15px;
    padding: 13px 18px 12px;
  }
}

@media (min-width: 1120px) {
  .section-nav {
    top: calc(var(--header-h, 87px) + var(--crumbs-h, 46px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .section-nav a {
    transition: none;
  }
}

/* ------------------------------------------------------- публикации раздела

   Список статей: на хабе — подразделы со своими статьями, на подразделе — его
   статьи. До его появления ни одна из семи статей академического центра не имела
   ни одной входящей ссылки; check_links молчал, потому что засчитывал ссылку на
   языкового близнеца из переключателя языка.

   Заливку не берёт: держится на линейках, как .catalog и .stories. Линейка
   2px --navy сверху — та же, что отделяет карточку истории и преподавателя:
   это перечень свидетельств, жанр один. */

.pub-list {
  max-width: var(--measure-wide);
  margin: var(--sp-md) 0 var(--sp-md);
  border-top: 2px solid var(--navy);
  padding-top: var(--sp-sm);
}

.pub-list h2 {
  margin: 0 0 0.8em;
  font-family: var(--font-ui);
  font-size: clamp(20px, 2vw, 25px);
  font-weight: 600;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--ink);
}

.pub-group + .pub-group {
  margin-top: var(--sp-sm);
}

.pub-group h3 {
  margin: 0 0 0.5em;
  font-family: var(--font-ui);
  font-size: clamp(17px, 1.4vw, 20px);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}

.pub-group h3 a {
  color: var(--navy-lit);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
}

.pub-group h3 a:hover {
  border-bottom-color: var(--navy-lit);
}

.pub-list ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.pub-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding: 11px 0;
  border-top: 1px solid var(--hairline);
}

.pub-list li:first-child {
  border-top: 0;
}

.pub-list li a {
  flex: 1 1 18em;
  font-family: var(--font-serif);
  font-size: clamp(16px, 1.2vw, 18px);
  line-height: 1.45;
  color: var(--navy-lit);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.pub-list li a:hover {
  border-bottom-color: var(--navy-lit);
}

/* Дата служебная, поэтому Golos с табличными цифрами: в столбик дат разной
   ширины читается хуже. */
.pub-list li span {
  flex: none;
  font-family: var(--font-ui);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- registry

   The one loud element, and the reason this system is not transferable to some
   other site: it is the shape of the product. Two institutions side by side
   because the degree is a pair; then the facts a sceptical reader came to
   check, set in tabular figures.

   Named .registry and not .ledger because site-core.css already owns .ledger
   for the landing vocabulary.

   Data comes from data/programs.json in the generator repo, not from the page
   markdown — content/*.md is regenerated by extract_content.mjs and anything
   added there is overwritten on the next extraction.
   -------------------------------------------------------------------------- */

.registry {
  background: var(--stock);
  max-width: var(--measure-wide);
  margin: var(--sp-md) 0 0;
  overflow: hidden;
}

.registry-parties {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.registry-party {
  padding: 20px var(--sp-sm);
  font-family: var(--font-ui);
}

/* The only line inside the block, and it carries the meaning "two separate
   institutions" rather than decorating the box. */
.registry-party + .registry-party {
  border-left: 1px solid rgba(36, 31, 27, 0.16);
}

.registry-party b {
  display: block;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.registry-party span {
  display: block;
  margin-top: 3px;
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-soft);
}

.registry-facts {
  margin: 0;
  border-top: 2px solid var(--navy);
  font-family: var(--font-ui);
  font-size: 15px;
  /* Credits and levels are numbers to be compared, so the figures line up. */
  font-variant-numeric: tabular-nums;
}

.registry-facts > div {
  display: grid;
  grid-template-columns: 13em 1fr;
  gap: var(--sp-sm);
  padding: 11px var(--sp-sm);
}

.registry-facts > div + div {
  border-top: 1px solid rgba(36, 31, 27, 0.1);
}

.registry-facts dt {
  color: var(--ink-soft);
  font-weight: 400;
}

.registry-facts dd {
  margin: 0;
  font-weight: 500;
}

/* ---------------------------------------------------------------- article body

   The article is not a card: no frame, no panel, no tinted background. The text
   IS the page, set left against a generous outer margin, with the measure alone
   defining the column.
   -------------------------------------------------------------------------- */

/* Длинные русские слова в заголовках шире 320px: «ПРЕДПРИНИМАТЕЛЬСТВА» в h2
   статьи Академического центра вылезало за экран и тянуло за собой всю
   страницу. break-word ломает слово только когда иначе никак, поэтому обычный
   текст переносится как прежде. */
.prose,
.prose h2,
.prose h3,
.prose h4,
.prose h5,
.page-head h1,
.page-lede {
  overflow-wrap: break-word;
}


.page-body {
  padding: 0 0 var(--sp-lg);
}

.prose {
  background: none;
  border: none;
  padding: var(--sp-md) 0 0;
  margin: 0;
  max-width: var(--measure);
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: inherit;
  line-height: 1.62;
  color: var(--ink);
}

.prose > :first-child {
  margin-top: 0;
}

.prose > :last-child {
  margin-bottom: 0;
}

/* Sans headings over serif body is what makes the page read as a publication
   rather than as a reprint. Margins are asymmetric — the space goes above,
   because a heading belongs to the text under it. That is also why no heading
   carries a rule: the gap does the separating. */
.prose h2,
.prose h3,
.prose h4,
.prose h5 {
  color: var(--ink);
  letter-spacing: -0.02em;
  transform: none;
  border-bottom: none;
  padding-bottom: 0;
}

.prose h2 {
  font-size: clamp(25px, 2.4vw, 32px);
  font-weight: 600;
  line-height: 1.15;
  margin: 1.35em 0 0.4em;
}

.prose h3 {
  font-size: clamp(20px, 1.7vw, 24px);
  font-weight: 500;
  line-height: 1.25;
  margin: 1.4em 0 0.3em;
}

.prose h4 {
  font-size: clamp(17px, 1.4vw, 20px);
  font-weight: 500;
  line-height: 1.3;
  margin: 1.5em 0 0.25em;
}

/* h5 occurs in the extracted content (o-niu among others) and used to fall
   through to the browser default. */
.prose h5 {
  font-size: 17px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.01em;
  margin: 1.5em 0 0.25em;
}

.prose p {
  margin: 0 0 1em;
}

/* Inline accent — this is the role --navy-lit exists for. */
.prose a {
  color: var(--navy-lit);
  border-bottom: none;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(23, 82, 155, 0.4);
}

.prose a:hover {
  background: none;
  color: var(--navy-lit-deep);
  text-decoration-color: currentColor;
}

.prose strong {
  color: inherit;
  font-weight: 600;
}

.prose ol {
  margin: 0 0 1.2em;
  padding-left: 22px;
}

.prose li {
  margin-bottom: 0.4em;
}

.prose ul {
  list-style: none;
  margin: 0 0 1.2em;
  padding-left: 0;
}

.prose ul li {
  padding-left: 26px;
  position: relative;
}

/* A rule rather than a dot, positioned in em because the body size is
   clamped — a pixel offset drifts off the first line as the type scales. */
.prose ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.78em;
  width: 12px;
  height: 1px;
  background: var(--navy-lit);
}

.prose blockquote {
  margin: 1.5em 0;
  padding: 0 0 0 24px;
  border-left: 2px solid var(--navy-lit);
  font-style: normal;
  line-height: 1.55;
  color: var(--ink-soft);
}

.prose hr {
  border: none;
  border-top: 1px solid var(--hairline);
  margin: var(--sp-md) 0;
}

.prose img {
  display: block;
  border: none;
  max-width: min(100%, var(--measure-wide));
  height: auto;
  margin: 1.6em 0;
}

/* Course and tuition tables are common on the program pages. Wrapped in
   .table-scroll so a wide table scrolls itself instead of the page. */
.table-scroll {
  overflow-x: auto;
  max-width: var(--measure-wide);
  margin: 1.6em 0;
}

/* Tabular data returns to the sans: numbers in a 19px serif read as prose. */
.prose table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-ui);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

.prose th,
.prose td {
  text-align: left;
  padding: 10px 16px 10px 0;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
}

.prose th {
  background: none;
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
  border-bottom: 2px solid var(--navy);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- card grids

   NOTE: still unused — no generated page emits .card-grid, including /avtory
   and /nasha-komanda where author cards are the obvious fit. Kept because those
   pages are the next thing to build, but it has never been rendered, so treat
   it as unverified.
   -------------------------------------------------------------------------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
  margin: var(--sp-md) 0 0;
}

.content-card {
  background: var(--paper);
  border: 1px solid var(--hairline);
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-decoration: none;
  transition: border-color 0.15s;
}

/* No lift and no shadow: nothing else in this system floats. */
.content-card:hover {
  box-shadow: none;
  border-color: var(--navy-lit);
}

.content-card h3 {
  font-family: var(--font-ui);
  font-size: 20px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.02em;
  margin: 0;
  text-transform: none;
}

.content-card p {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.content-card .card-meta {
  margin-top: auto;
  padding-top: 10px;
  font-family: var(--font-ui);
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  font-weight: 400;
}

/* Author cards carry a portrait; the mirror's images are inconsistent in ratio,
   so the frame is fixed and the image cropped to it. */
.author-card .author-photo {
  aspect-ratio: 4 / 5;
  object-fit: cover;
  margin: -28px -28px 10px;
  width: calc(100% + 56px);
  display: block;
  border: none;
  border-radius: 3px 3px 0 0;
}

.author-card .author-role {
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- recovered blocks

   Q&A recovered from SP Page Builder accordions (see the extraction report).
   Rendered as <details>, not the landing's div + .open class: site.js is not
   loaded here, and with the landing markup every answer stayed display:none —
   present in the HTML and unreadable.

   The source content numbers these 01/02/03. The numbering is dropped in the
   generator: an FAQ is not a sequence, and numbered markers on content that is
   not ordered is decoration pretending to be structure.
   -------------------------------------------------------------------------- */

.qa-section {
  background: none;
  border: none;
  padding: 0;
  margin: var(--sp-md) 0 0;
  /* Cut to 40em rather than the prose measure: the questions are sans and the
     answers serif, and the mixed column takes a little more width before it
     reads as cramped. */
  max-width: 40em;
}

.qa-section > h2 {
  /* theme-niu.css colours h2 navy; in this system headings are ink and only
     fields are navy. */
  color: var(--ink);
  font-size: clamp(25px, 2.4vw, 32px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  transform: none;
  margin: 0 0 0.6em;
}

.qa-section .faq-item {
  max-width: none;
  margin: 0 0 6px;
  padding: 0;
  border: none;
  border-radius: 3px;
  background: var(--stock);
}

.qa-section .faq-q {
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 17px;
  letter-spacing: 0;
  line-height: 1.35;
  color: var(--ink);
  padding: 14px var(--sp-sm);
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.qa-section .faq-q:hover {
  color: var(--navy-lit);
}

/* Both are needed: WebKit uses ::-webkit-details-marker, others list-style. */
.qa-section .faq-q::-webkit-details-marker {
  display: none;
}

/* Core draws a '+' through content on ::after. Replaced by a chevron that
   rotates on open — motion that answers the reader's own action, which is the
   only motion in this system. */
.qa-section .faq-q::after {
  content: "";
  flex: none;
  width: 11px;
  height: 11px;
  margin: 5px 0 0 auto;
  border-right: 1.5px solid var(--navy-lit);
  border-bottom: 1.5px solid var(--navy-lit);
  transform: rotate(45deg);
  transition: transform 0.14s ease;
}

.qa-section .faq-item[open] > .faq-q::after {
  content: "";
  transform: rotate(-135deg);
  margin-top: 9px;
}

.qa-section .faq-a {
  display: block;
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.6;
  padding: 0 var(--sp-sm) 16px;
}

.qa-section .faq-q:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- notices */

/* The noindex test-stand banner. An accent bar on the left edge rather than a
   centred gold band — still conspicuous, but it no longer competes with the
   page title directly beneath it. Gold as a marker, which is the one role it
   keeps on a light surface. */
.stand-notice {
  background: none;
  border: none;
  border-bottom: 1px solid var(--hairline);
  border-left: 4px solid var(--gold);
  text-align: left;
  padding: 12px 0;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
}

.stand-notice .wrap {
  padding-left: 20px;
}

.stand-notice a {
  color: var(--navy-lit);
  font-weight: 500;
}

/* ---------------------------------------------------------------- footer additions */

.site-footer,
.site-footer .footer-brand,
.site-footer .footer-links {
  font-family: var(--font-ui);
}

.site-footer .footer-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 24px;
  padding-bottom: 22px;
  margin-bottom: 18px;
  border-bottom: 1px solid rgba(232, 184, 106, 0.18);
}

/* The footer column headings are the one surviving small-caps label, and they
   survive because they name navigation groups rather than decorate content. */
.site-footer .footer-nav h4 {
  font-family: var(--font-ui);
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gold);
  margin: 0 0 10px;
  font-weight: 600;
}

.site-footer .footer-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-footer .footer-nav li {
  margin-bottom: 7px;
}

.site-footer .footer-nav a {
  color: rgba(255, 255, 255, 0.72);
  text-decoration: none;
  font-size: 14px;
}

.site-footer .footer-nav a:hover {
  color: var(--gold);
}

/* Соцсети в подвале.

   Второй заголовок внутри колонки контактов, поэтому ему нужен отступ сверху —
   у первого h4 колонки его нет, он стоит вплотную к верху столбца.

   Глифы монохромные и наследуют цвет ссылки (fill="currentColor" в разметке):
   брендовые синий Facebook и красный YouTube были бы четвёртой и пятой
   заливкой на странице, а DESIGN.md держит палитру закрытой. Подпись рядом с
   иконкой оставлена намеренно — ряд голых глифов опознаётся не всеми, а место
   в колонке есть. */
.site-footer .footer-socials-h {
  margin-top: 18px;
}

.site-footer .footer-socials {
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-footer .footer-socials li {
  margin-bottom: 7px;
}

.site-footer .footer-socials a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.72);
  text-decoration: none;
  font-size: 14px;
}

.site-footer .footer-socials a:hover {
  color: var(--gold);
}

.site-footer .footer-socials svg {
  flex: none;
}

/* Герб в подвале — белым силуэтом, а не золотом по синему.

   Токен --logo-img из theme-niu.css рисует щит навью и золотом на прозрачном
   фоне. В шапке он идёт 38px и читается, а в подвале сжат до 20px: мелкая
   золотая гравировка на --navy-deep превращается в пятно, и знак пропадает.

   brightness(0) гасит все непрозрачные пиксели в чёрный, invert(1) делает их
   белыми; прозрачность не трогается, поэтому получается ровный белый силуэт
   щита. На 20px силуэт читается лучше любой гравировки.

   Правка живёт ЗДЕСЬ, а не в theme-niu.css: тот слой общий с лендингом
   master-niu.html, и знак в его подвале трогать незачем. Это не про запрет
   золота на светлом из инвариантов — фон тут тёмный; это про размер, на
   котором детализация перестаёт работать. */
.site-footer .footer-brand .brand-mark {
  filter: brightness(0) invert(1);
}

.site-footer .footer-legal {
  font-size: 12px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.45);
  max-width: 70ch;
}

/* ---------------------------------------------------------------- responsive */

/* Below this the outer margin is gone, so the measure caps stop helping and
   only get in the way of the narrower viewport. */
@media (max-width: 900px) {
  .prose,
  .qa-section {
    max-width: none;
  }

  .registry-parties {
    grid-template-columns: 1fr;
  }

  .registry-party + .registry-party {
    border-left: none;
    border-top: 1px solid rgba(36, 31, 27, 0.16);
  }

  .registry-facts > div {
    grid-template-columns: 1fr;
    gap: 2px;
  }

  .page-head .hero-seal {
    width: 380px;
    height: 380px;
    right: -120px;
  }
}

/* The two-row nav rule that used to live here (max-width: 1320px) is gone with
   the menu it was built for. Eight sentence-case links plus the crest and two
   buttons could not share a row below 1320px, so navigation dropped to a second
   row; six shorter items fit to the burger threshold, and below it the menu is
   a disclosure rather than a wrap. Measured at 1024: the row ends with ~150px
   to spare. */

@media (max-width: 768px) {
  .site-header .brand-logo {
    height: 44px;
  }

  /* Two CTAs, the switcher and the crest cannot share 375px: measured, the row
     needs ~336px against 327px of usable width, so the consultation button was
     cut off at the edge. Actions take a row of their own and the buttons split
     it. */
  .header-actions {
    width: 100%;
    margin-left: 0;
    flex-wrap: wrap;
    gap: 8px;
  }

  .header-actions .btn {
    flex: 1 1 auto;
    text-align: center;
    padding: 9px 10px;
    font-size: 12.5px;
  }

  .page-head .hero-seal {
    width: 300px;
    height: 300px;
    right: -110px;
  }

  .prose {
    padding-top: var(--sp-sm);
  }

  .author-card .author-photo {
    aspect-ratio: 3 / 2;
  }
}

@media (prefers-reduced-motion: reduce) {
  .qa-section .faq-q::after {
    transition: none;
  }
}

/* ---------------------------------------------------------------- каталог

   196 программ на одной странице. Список принципиально НЕ берёт --stock: этот
   фон принадлежит .registry и Q&A, и второй вид карточек на нём превратил бы
   систему в тот самый набор одинаковых плашек, от которого она уходила
   (DESIGN.md → инварианты). Каталог поэтому строится на бумаге и линейках:
   разделяет строки хэйрлайн, а не заливка.
   -------------------------------------------------------------------------- */

.catalog {
  margin: var(--sp-lg) 0 0;
  max-width: var(--measure-wide);
}
.cat-totals {
  font-family: var(--font-ui);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-md);
  padding-bottom: 10px;
  border-bottom: 2px solid var(--navy);
}
.cat-h2 {
  font-family: var(--font-ui);
  font-size: clamp(21px, 2.4vw, 27px);
  font-weight: 600;
  color: var(--navy);
  margin: var(--sp-md) 0 6px;
  /* theme-niu.css задаёт h2/h3 uppercase 900 литералами — как и прочие свои
     заголовки, сайт это снимает поимённо. */
  text-transform: none;
  letter-spacing: -0.01em;
  border-bottom: none;
  padding-bottom: 0;
}
.cat-lede {
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-sm);
}

/* Рубрикатор. Плитка — это ссылка-якорь, поэтому подчёркивания нет, а роль
   ссылки несёт рамка; активное направление помечается линией слева. */
.cat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px;
  margin: 0 0 var(--sp-md);
}
.cat-tile {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 13px 15px;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--hairline-strong);
  border-radius: 3px;
  text-decoration: none;
  background: var(--paper);
}
.cat-tile:hover {
  border-left-color: var(--navy-lit);
}
.cat-tile.is-active {
  border-left-color: var(--navy);
  background: rgba(23, 82, 155, 0.05);
}
.cat-tile-name {
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  color: var(--navy-lit);
}
.cat-tile-count {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* Панель фильтров приезжает из генератора с hidden и раскрывается только
   скриптом: без JS фильтры не работали бы, а показанный неработающий фильтр
   хуже отсутствующего. */
.cat-filters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px var(--sp-sm);
  align-items: end;
  padding: var(--sp-sm) 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  margin: 0 0 var(--sp-sm);
}
.cat-filters[hidden] {
  display: none;
}
.cat-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
}
.cat-field-label {
  /* Видимая подпись дублировала бы плейсхолдер и первый пункт списка; она
     нужна скринридеру, а не глазу. */
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.cat-field input,
.cat-field select {
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--hairline-strong);
  border-radius: 3px;
  padding: 9px 11px;
  width: 100%;
}
.cat-field input:focus-visible,
.cat-field select:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 1px;
}
.cat-found {
  grid-column: 1 / -1;
  margin: 0;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.cat-found b {
  color: var(--ink);
}
.cat-empty {
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--ink-soft);
  margin: var(--sp-sm) 0;
}
.cat-reset {
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--navy-lit);
  background: none;
  border: none;
  padding: 0 0 0 6px;
  text-decoration: underline;
  cursor: pointer;
}

.cat-group {
  margin: var(--sp-md) 0 0;
  scroll-margin-top: var(--sp-sm);
}
.cat-group[hidden] {
  display: none;
}
.cat-group-title {
  font-family: var(--font-ui);
  font-size: 17px;
  font-weight: 600;
  color: var(--navy);
  text-transform: none;
  letter-spacing: 0;
  margin: 0 0 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--hairline-strong);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-sm);
  align-items: baseline;
}
.cat-group-count {
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Программа — нативный <details>, как и восстановленные Q&A: раскрытие без JS,
   с клавиатуры и при выключенном CSS. */
.cat-item {
  border-bottom: 1px solid var(--hairline);
}
.cat-item[hidden] {
  display: none;
}
.cat-sum {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px var(--sp-sm);
  padding: 12px 26px 12px 0;
  cursor: pointer;
  position: relative;
  list-style: none;
}
.cat-sum::-webkit-details-marker {
  display: none;
}
.cat-sum::after {
  content: "";
  position: absolute;
  right: 4px;
  top: 19px;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--hairline-strong);
  border-bottom: 1.5px solid var(--hairline-strong);
  transform: rotate(45deg);
}
.cat-item[open] > .cat-sum::after {
  transform: rotate(-135deg);
  top: 22px;
}
.cat-sum:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 2px;
}
.cat-name {
  font-family: var(--font-ui);
  font-size: 16px;
  font-weight: 500;
  color: var(--navy-lit);
  grid-column: 1;
}
.cat-provider {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  grid-column: 1;
}
.cat-level {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.cat-body {
  padding: 0 0 16px;
}
.cat-facts {
  margin: 0 0 12px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}
.cat-facts > div {
  display: grid;
  grid-template-columns: 13em 1fr;
  gap: var(--sp-sm);
  padding: 7px 0;
  border-top: 1px solid rgba(36, 31, 27, 0.1);
}
.cat-facts dt {
  color: var(--ink-soft);
}
.cat-facts dd {
  margin: 0;
  font-weight: 500;
}
.cat-pswv,
.cat-links {
  font-family: var(--font-ui);
  font-size: 14px;
  margin: 0 0 8px;
}
.cat-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px var(--sp-sm);
  align-items: baseline;
}
.cat-fine {
  color: var(--ink-soft);
  font-size: 13px;
}


/* ---------------------------------------------------------------- главная

   Витрина двух программ. На бумаге и волосяных линиях: заливка --stock
   принадлежит .registry и блоку вопросов, и четвёртой сущности с фоном здесь не
   появляется.

   Списки определений (<dl>) тут были и убраны: marked их не поддерживает, и
   разметка `Термин\n: значение` уезжала в текст вместе с двоеточием. Три факта
   на главной — обычная проза с выделенным зачином.

   Mobile-first: базовые правила — телефон, колонки добавляются с 700px. */

.programs {
  display: grid;
  gap: 18px;
  margin: 0 0 var(--sp-md);
  max-width: var(--measure-wide);
}

.program-card {
  padding: 18px 20px;
  border: 1px solid var(--hairline-strong);
  border-radius: 3px;
}

.program-card h3 {
  font-family: var(--font-ui);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  margin: 0;
}

.program-card h3 a {
  color: inherit;
  text-decoration: none;
  border-bottom: 2px solid var(--gold);
}

.program-card h3 a:hover {
  color: var(--navy-lit);
}

/* Английское название программы — не заголовок и не подпись: это то, что будет
   написано в дипломе, поэтому сериф, как у остального текста-свидетельства. */
.program-name {
  font-family: var(--font-serif);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin: 6px 0 14px;
}

.program-facts {
  margin: 0;
  display: grid;
  gap: 8px;
}

.program-facts > div {
  display: grid;
  grid-template-columns: 10em 1fr;
  gap: 10px;
  font-family: var(--font-ui);
  font-size: 14px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
}

.program-facts dt {
  color: var(--ink-soft);
  margin: 0;
}

.program-facts dd {
  color: var(--ink);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 700px) {
  .programs {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 420px) {
  .program-facts > div {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* ------------------------------------------------------------------- подбор

   Квиз на главной. Заливку --stock не берёт: она принадлежит .registry и блоку
   вопросов, и четвёртой сущности с фоном в системе не появляется. Варианты
   выбора — рамка и волосяная линия, как плитки направлений в каталоге.

   Mobile-first: базовые правила — телефон, колонки добавляются с 600px. */

.quiz {
  max-width: var(--measure-wide);
  margin: 0 0 var(--sp-md);
  /* Под шапкой и прилипшими крошками, иначе переход по /#podbor прячет
     заголовок секции под ними. */
  scroll-margin-top: calc(var(--header-h, 148px) + 60px);
}

.quiz h2 {
  font-family: var(--font-ui);
  font-size: clamp(22px, 2.4vw, 28px);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  margin: 0 0 0.35em;
}

.quiz-lede {
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-sm);
  max-width: var(--measure);
}

.quiz-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline-strong);
  margin-bottom: 16px;
}

.quiz-step {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* Шаг получает фокус при смене экрана, чтобы с клавиатуры было видно, что
   экран сменился. Обводку по умолчанию при этом не рисуем: фокус программный,
   а не от нажатия Tab. */
.quiz-step:focus,
.quiz-q:focus {
  outline: none;
}

.quiz-back,
.quiz-more {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--navy-lit);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(23, 82, 155, 0.4);
}

.quiz-back:hover,
.quiz-more:hover {
  text-decoration-color: currentColor;
}

.quiz-q {
  font-family: var(--font-ui);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  margin: 0 0 14px;
}

.quiz-opts {
  display: grid;
  gap: 8px;
}

.quiz-opt {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 4px 14px;
  width: 100%;
  min-height: 44px;
  text-align: left;
  font-family: var(--font-ui);
  background: var(--paper);
  border: 1px solid var(--hairline-strong);
  border-radius: 3px;
  padding: 12px 14px;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}

.quiz-opt:hover:not([disabled]) {
  border-color: var(--navy-lit);
}

.quiz-opt:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 2px;
}

/* Вариант, ведущий в ноль, гасится, а не прячется: исчезающий на глазах список
   вариантов читается как сбой, а видимый ноль объясняет, почему выбора нет. */
.quiz-opt[disabled] {
  cursor: default;
  opacity: 0.45;
}

.quiz-opt-t {
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
}

.quiz-opt-n {
  grid-column: 1;
  font-size: 13px;
  color: var(--ink-soft);
}

.quiz-opt-c {
  grid-row: 1;
  grid-column: 2;
  font-size: 13px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.quiz-cards {
  display: grid;
  gap: 14px;
}

.quiz-card {
  padding: 14px 16px;
  border: 1px solid var(--hairline-strong);
  border-radius: 3px;
}

.quiz-card-name {
  font-family: var(--font-ui);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
  margin: 0;
}

.quiz-card-prov {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  margin: 4px 0 10px;
}

.quiz-card-facts {
  margin: 0 0 10px;
  display: grid;
  gap: 6px;
}

.quiz-card-facts > div {
  display: grid;
  grid-template-columns: 9em 1fr;
  gap: 10px;
  font-family: var(--font-ui);
  font-size: 13.5px;
  padding-top: 6px;
  border-top: 1px solid var(--hairline);
}

.quiz-card-facts dt {
  color: var(--ink-soft);
  margin: 0;
}

.quiz-card-facts dd {
  color: var(--ink);
  margin: 0;
}

.quiz-card-link,
.quiz-all a {
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--navy-lit);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(23, 82, 155, 0.4);
}

.quiz-all {
  margin: 16px 0 0;
}

.quiz-none {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  margin: 0;
  padding: 12px 14px;
  border-left: 3px solid var(--navy-lit);
  background: var(--stock);
}

.quiz-more {
  margin-top: 14px;
}

.quiz-cta {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 2px solid var(--navy);
}

.quiz-cta .btn {
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  padding: 13px 26px;
}

.quiz-cta-note {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 10px 0 0;
}

@media (min-width: 600px) {
  .quiz-opts {
    grid-template-columns: 1fr 1fr;
  }

  .quiz-cards {
    grid-template-columns: 1fr 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .quiz-opt {
    transition: none;
  }
}

/* ------------------------------------------------------------ об университете

   Четыре раздела закладками, и тон плашки меняется вместе с разделом.

   Тон здесь ЗНАЧИТ, а не украшает. Четыре раздела идут от заверенной записи к
   заявленному намерению: основан в 2019 (проверяемый факт) → как учит → во что
   верит → куда идёт. Твёрдость убывает, устремление растёт — и плашка вдоль
   этой оси светлеет. Метафора системы это ровно и есть: запись тёмная и
   закреплённая, намерение — открытое. Заодно тон отвечает на единственный
   вопрос, который самолистающийся блок от читателя прячет: где я из четырёх.

   Полоса закладок — сама эта шкала, показанная целиком: каждая закладка
   покрашена тоном своего раздела. Активная совпадает с плашкой под собой и
   сливается с ней без шва — закладка в буквальном смысле. Золото сидит
   ленточкой по ВЕРХНЕМУ краю активной: снизу шва быть не должно, а сверху это
   тот же маркер текущего раздела, что и в меню.

   Контр-цвет к холодному полю — тёплый, и он в системе уже есть: проза набрана
   тоном --stock, тем же тёплым листом, на котором стоит реестр, только здесь он
   краска, а не поверхность. Четвёртой сущности с фоном при этом не появляется —
   ровно потому, что поверхностью он тут не работает. Заголовок остаётся белым:
   различие тёплого и холодного внутри плашки и держит иерархию.

   Базовое состояние — БЕЗ JS: четыре панели обычным потоком, каждая красит
   себя сама, и шкала видна вся сразу. .is-enhanced ставит niu-about.js, и
   только тогда панели складываются в одну ячейку, а тон уезжает на .about-stage.

   Mobile-first: базовые правила — телефон. */

.about {
  /* Плашка шириной с колонку прозы, а не с таблицу: текст внутри заполняет её
     целиком и встаёт в одну линию с остальным текстом страницы. Раньше плашка
     шла по --measure-wide, а проза внутри имела свой кап по --measure, и справа
     оставалось 273px пустого цветного поля — на белой странице недобор меры
     невиден, а на заливке читается как дефект.

     Кегль объявлен здесь намеренно: `em` в --measure резолвится по месту
     использования, и без этой строки мера считалась бы от кегля body, а текст
     панели набран своим. Сложение с полями даёт плашку, у которой внутренняя
     колонка ровно равна мере. */
  font-size: clamp(16px, 1.2vw, 18px);
  max-width: calc(var(--measure) + 40px);
  margin: 0 0 var(--sp-md);
  border-radius: 3px;
  overflow: hidden;
}

.about-tabs {
  display: flex;
  align-items: stretch;
  /* Ниже ~560px четыре подписи в ряд не помещаются. Полоса прокручивается, а не
     переносится в три этажа: перенос ломает чтение «это один ряд» и на каждом
     языке рвётся в своём месте. */
  overflow-x: auto;
  scrollbar-width: none;
}

.about-tabs::-webkit-scrollbar {
  display: none;
}

/* Атрибут hidden даёт display:none только правилом браузера — объявленный выше
   display:flex его перебивает по специфичности. Без этой строки полоса закладок
   оставалась бы видимой и мёртвой на странице без JS. */
.about-tabs[hidden] {
  display: none;
}

.about-tabs [role='tab'] {
  flex: none;
  appearance: none;
  border: 0;
  background: transparent;
  /* 0.7 белого — нижняя рабочая граница: на светлейшей ступени 0.62 даёт 4.02,
     то есть подпись перестаёт проходить норму ровно там, где поле ярче всего. */
  color: rgba(255, 255, 255, 0.7);
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: none;
  padding: 13px 16px 12px;
  min-height: 44px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s;
}

.about-tabs [role='tab'][data-tone='1'] { background: var(--navy-1); }
.about-tabs [role='tab'][data-tone='2'] { background: var(--navy-2); }
.about-tabs [role='tab'][data-tone='3'] { background: var(--navy-3); }
.about-tabs [role='tab'][data-tone='4'] { background: var(--navy-4); }

.about-tabs [role='tab']:hover {
  color: #fff;
}

.about-tabs [role='tab'][aria-selected='true'] {
  color: #fff;
  /* Ленточка сверху, а не линия снизу: снизу закладка должна сливаться с
     плашкой. inset-тень не двигает содержимое, в отличие от border-top.
     3px, а не 2: контраст золота падает от 9.44 на первой ступени до 4.23 на
     четвёртой, и на двух пикселях маркер текущего раздела на светлом краю
     шкалы переставал читаться — то есть работал через раз. */
  box-shadow: inset 0 3px 0 var(--gold);
}

.about-tabs [role='tab']:focus-visible,
.about-toggle:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* Сцена берёт тон активного раздела. Без JS атрибута нет, сцена прозрачна, и
   каждая панель красит себя сама — шкала при этом видна вся сразу. */
.about-stage {
  transition: background-color 0.45s ease;
}

.about[data-tone='1'] .about-stage { background: var(--navy-1); }
.about[data-tone='2'] .about-stage { background: var(--navy-2); }
.about[data-tone='3'] .about-stage { background: var(--navy-3); }
.about[data-tone='4'] .about-stage { background: var(--navy-4); }

.about-panel {
  padding: var(--sp-sm) 20px calc(var(--sp-sm) + 2px);
}

.about-panel[data-tone='1'] { background: var(--navy-1); }
.about-panel[data-tone='2'] { background: var(--navy-2); }
.about-panel[data-tone='3'] { background: var(--navy-3); }
.about-panel[data-tone='4'] { background: var(--navy-4); }

.about-panel h3 {
  margin: 0 0 0.5em;
  font-family: var(--font-ui);
  font-size: clamp(19px, 1.7vw, 23px);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-transform: none;
  color: #fff;
}

.about-panel p {
  margin: 0;
  /* Своего капа нет: ширину задаёт сама плашка (см. .about). */
  font-family: var(--font-serif);
  font-size: clamp(16px, 1.2vw, 18px);
  font-weight: 300;
  line-height: 1.6;
  /* Тёплый лист как краска на холодном поле — см. шапку секции. */
  color: var(--stock);
}

.about-foot {
  margin: 0;
  padding: 0 20px calc(var(--sp-sm) - 4px);
  text-align: right;
}

.about-toggle {
  appearance: none;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.72);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  padding: 6px 0;
  cursor: pointer;
  transition: color 0.15s;
}

.about-toggle:hover {
  color: #fff;
}

/* Включается скриптом. Панели ложатся в одну ячейку — плашка становится высотой
   с самый длинный раздел и не дёргается при переключении, без единого замера в
   JS. Заливку в этом режиме несёт сцена, иначе тон менялся бы рывком по краю
   панели, а не всей плашкой. visibility:hidden оставляет текст в DOM
   (индексируется) и убирает панель из дерева доступности — как и положено
   неактивному табу. */
.about.is-enhanced .about-panels {
  display: grid;
  grid-template-areas: 'stack';
}

.about.is-enhanced .about-panel {
  grid-area: stack;
  background: transparent;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s;
}

.about.is-enhanced .about-panel.is-active {
  visibility: visible;
  opacity: 1;
}

@media (min-width: 600px) {
  /* Закладки равной ширины: полоса читается как шкала, а не как меню. */
  .about-tabs [role='tab'] {
    flex: 1 1 0;
    font-size: 16px;
    padding: 15px 18px 14px;
  }

  .about {
    max-width: calc(var(--measure) + 56px);
  }

  .about-panel {
    padding: var(--sp-sm) 28px calc(var(--sp-sm) + 4px);
  }

  .about-foot {
    padding: 0 28px calc(var(--sp-sm) - 2px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .about-tabs [role='tab'],
  .about-toggle,
  .about-stage,
  .about.is-enhanced .about-panel {
    transition: none;
  }
}

/* ------------------------------------------------------------------ заявка

   Форма следует правилу «никакой четвёртой сущности с фоном»: заливка --stock
   принадлежит .registry и блоку вопросов, а здесь — только волосяные линии,
   ровно как в .catalog. Страница из подкрашенных карточек — тот самый провал,
   который DESIGN.md называет по имени.

   .form-group из theme-niu.css переиспользовать НЕЛЬЗЯ: там
   `border: 1px solid var(--gold)`, а золото на светлом даёт контраст 1.83 и по
   инварианту дизайн-системы остаётся геральдическим. Образец здесь — поля
   фильтра каталога (.cat-field), у которых граница уже правильная.

   Mobile-first: базовые правила — телефон, две колонки появляются с 600px. */

.lead-form {
  max-width: var(--measure-wide);
  margin: var(--sp-lg) 0 0;
  padding-top: var(--sp-md);
  border-top: 1px solid var(--hairline-strong);
  scroll-margin-top: calc(var(--header-h, 148px) + 60px);
}

.lead-form h2 {
  font-family: var(--font-ui);
  font-size: clamp(22px, 2.4vw, 28px);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  margin: 0 0 0.35em;
}

.lead-form-lede {
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-md);
  max-width: var(--measure);
}

.lead-form-body {
  display: grid;
  gap: 16px;
}

/* Атрибут hidden — это `display: none` из UA-таблицы, и авторский display его
   перебивает: без этого правила `form.hidden = true` на успехе не скрывало
   ничего, потому что выше стоит display:grid. */
.lead-form-body[hidden] {
  display: none;
}

/* Ловушка: position вместо display:none — скрытое через display поле часть
   ботов просто пропускает, а смысл ловушки в том, чтобы его заполнили. */
.lf-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.lf-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* Подписи видимые и настоящие: плейсхолдер вместо подписи исчезает ровно
   тогда, когда он нужен — при заполнении. */
.lf-field label {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
}

.lf-field input,
.lf-field select {
  font-family: var(--font-ui);
  font-size: 16px; /* меньше 16px — iOS Safari зумит страницу на фокусе */
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--hairline-strong);
  border-radius: 3px;
  padding: 11px 12px;
  width: 100%;
}

.lf-field input:focus-visible,
.lf-field select:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 1px;
}

.lf-field input:user-invalid {
  border-color: #B23A2E;
}

.lf-hint {
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--ink-soft);
}

.lead-form-body .btn {
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  padding: 13px 26px;
  justify-self: start;
}

.lead-form-body .btn[disabled] {
  opacity: 0.6;
  cursor: progress;
}

.lead-form-consent,
.lead-form-alt {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0;
}

.lead-form-alt {
  margin-top: 14px;
}

.lead-form-consent a,
.lead-form-alt a,
.lead-form-err a {
  color: var(--navy-lit);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Отказ отправки и успех — на бумаге, а не на заливке; красный только в
   линии слева, как метка состояния. */
.lead-form-err,
.lead-form-ok {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.6;
  margin: 0;
  padding: 12px 14px;
  border-left: 3px solid var(--navy-lit);
  background: var(--stock);
}

.lead-form-err {
  border-left-color: #B23A2E;
  color: var(--ink);
}

/* Экран «отправлено».

   Заголовок формы, вводка и строка «или напишите напрямую» на нём скрываются:
   «оставьте контакты — свяжемся» над «спасибо, мы с вами свяжемся» читается как
   просьба сделать только что сделанное, то есть как признак, что заявка не
   ушла. Скрытие живёт в CSS, а не в JS: состояние секции одно (класс is-sent),
   и перечислять в скрипте, что именно спрятать, значит завести второй список
   частей формы, который разойдётся с разметкой.

   Галочка — --navy-lit, не золото: золото на светлом даёт контраст 1.83 и по
   инварианту дизайн-системы остаётся геральдическим, а это знак состояния. */
.lead-form.is-sent > h2,
.lead-form.is-sent > .lead-form-lede,
.lead-form.is-sent > .lead-form-alt {
  display: none;
}

.lead-form-ok[hidden] {
  display: none;
}

.lf-ok-check {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-bottom: 10px;
  border-radius: 50%;
  border: 1px solid var(--navy-lit);
  color: var(--navy-lit);
}

.lf-ok-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 6px;
}

.lf-ok-text {
  margin: 0;
  color: var(--ink-soft);
}

/* Кнопка в Telegram — во всю ширину на телефоне и по содержимому дальше:
   растянутая на 560px модалки, она выглядит полосой, а не кнопкой. */
.lf-ok-tg {
  display: block;
  margin-top: 14px;
  text-align: center;
}

@media (min-width: 480px) {
  .lf-ok-tg {
    display: inline-block;
  }
}

@media (min-width: 600px) {
  .lead-form-body {
    grid-template-columns: 1fr 1fr;
    column-gap: 18px;
  }

  /* Имя и почта делят строку, телефон с подсказкой берёт свою: подсказка про
     код страны под половинным полем вставала в три строки. Кнопка и тексты —
     во всю ширину. */
  .lead-form-body > *:not(.lf-field),
  .lead-form-body .lf-field:nth-of-type(3) {
    grid-column: 1 / -1;
  }
}

/* ------------------------------------------------- модалка «Консультация»

   Та же форма, что на странице, в <dialog>. Отсюда и приём: внутри лежит
   обычный .lead-form, и все правила выше действуют без единого дубля — иначе
   два набора правил разъехались бы при первой же правке полей.

   Снимается ровно то, что принадлежит форме КАК СЕКЦИИ СТРАНИЦЫ: верхняя
   линейка (в модалке она отделяла бы форму от её же заголовка), внешний отступ
   и scroll-margin (прокручивать к якорю здесь нечего).

   Ширину ведёт min(): 560px — рабочий предел для двух колонок полей, дальше
   растёт разрыв между подписью и полем; 100vw-32px не даёт модалке упереться в
   края на телефоне. max-height + overflow — потому что при открытой экранной
   клавиатуре на 667px-экране кнопка отправки иначе оказывается за пределами
   видимой области, и форму невозможно отправить, не закрыв клавиатуру. */
.consult-modal {
  width: min(560px, 100vw - 32px);
  max-height: min(88vh, 900px);
  padding: 0;
  border: none;
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 24px 60px rgba(11, 31, 59, 0.28);
  overflow: auto;
  overscroll-behavior: contain;
}

.consult-modal::backdrop {
  background: rgba(11, 31, 59, 0.55);
}

.consult-modal .lead-form {
  margin: 0;
  padding: var(--sp-md);
  border-top: none;
  scroll-margin-top: 0;
  max-width: none;
}

/* Крестик не уезжает при прокрутке длинной формы: sticky относительно
   прокручиваемого <dialog>. position:absolute здесь уводил бы его вверх за
   пределы видимой части. */
.consult-modal-close {
  position: sticky;
  top: 0;
  float: right;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: calc(var(--sp-md) * -1 + 4px) calc(var(--sp-md) * -1 + 4px) 0 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.consult-modal-close:hover {
  background: var(--stock);
  color: var(--ink);
}

.consult-modal-close:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- отзывы

   Цитата — Literata (это длинный текст и прямая речь), подписи и служебное —
   Golos Text. Фон снова не берётся: карточка истории держится на портрете и
   линейке сверху.
   -------------------------------------------------------------------------- */

.stories {
  list-style: none;
  margin: var(--sp-md) 0 0;
  padding: 0;
  max-width: var(--measure-wide);
  display: grid;
  gap: var(--sp-md);
}
.story {
  border-top: 2px solid var(--navy);
  padding-top: var(--sp-sm);
}
.story-head {
  display: flex;
  gap: var(--sp-sm);
  align-items: center;
  margin-bottom: 10px;
}
.story-photo {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--stock);
}
.story-name {
  font-family: var(--font-ui);
  font-size: 19px;
  font-weight: 600;
  color: var(--navy);
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
}
.story-context {
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink-soft);
  margin: 2px 0 0;
}
.story-meta {
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink-soft);
  margin: 0 0 12px;
  line-height: 1.5;
}
.story-meta b {
  color: var(--ink);
  font-weight: 500;
}
.story-quote {
  margin: 0;
  padding: 0 0 0 var(--sp-sm);
  border-left: 2px solid var(--navy-lit);
}
.story-quote p {
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.65;
  margin: 0;
}
.story-note {
  display: block;
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--ink-soft);
  margin: 6px 0 0 calc(var(--sp-sm) + 2px);
}
.story-cta {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  margin-top: 12px;
}

@media (max-width: 640px) {
  .cat-filters {
    grid-template-columns: 1fr;
  }
  .cat-facts > div {
    grid-template-columns: 1fr;
    gap: 2px;
  }
  .cat-sum {
    grid-template-columns: 1fr;
  }
  .cat-level {
    grid-column: 1;
    grid-row: auto;
    justify-self: start;
    margin-top: 4px;
  }
  .story-head {
    align-items: flex-start;
  }
  .story-photo {
    width: 64px;
    height: 64px;
  }
}

/* ------------------------------------------------- преподаватели и авторы

   Две формы одних и тех же данных: сетка карточек на /avtory и шапка на
   персональной странице. Обе держатся на портрете и линейке сверху, фона не
   берут — ровно как .story, потому что это тот же жанр: свидетельство о
   человеке, а не рекламная плитка.

   Портрет квадратный со скруглением, а не круг отзывов: у половины снимков
   это документное фото с плечами, и круг срезает их до подбородка.
   -------------------------------------------------------------------------- */

.people-count {
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink-soft);
  margin: var(--sp-md) 0 var(--sp-sm);
}
.people {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: var(--measure-wide);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--sp-md) var(--sp-sm);
}
.person {
  border-top: 2px solid var(--navy);
  padding-top: var(--sp-sm);
  display: flex;
  flex-direction: column;
}
.person-head {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-bottom: 10px;
}
.person-photo,
.person-card-photo {
  width: 84px;
  height: 84px;
  border-radius: 4px;
  object-fit: cover;
  /* Точка кадрирования по умолчанию; у большинства портретов она переопределена
     из data/authors.json — см. build.mjs. */
  object-position: center 15%;
  flex-shrink: 0;
  background: var(--stock);
}
.person-card-photo {
  width: 128px;
  height: 128px;
}
/* Монограмма вместо портрета — см. build.mjs: у двоих фотографии нет, и
   безликий силуэт в ряду живых лиц читался бы как «человек ненастоящий». */
.person-photo-mono,
.person-card-photo-mono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--navy);
  letter-spacing: 0.02em;
  background: var(--stock);
}
.person-photo-mono {
  font-size: 28px;
}
.person-card-photo-mono {
  font-size: 40px;
}
.person-name {
  font-family: var(--font-ui);
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
}
/* Подчёркивание стоит сразу, а не появляется по наведению: на телефоне
   наведения нет, и имя-ссылка ничем не отличалось от обычного заголовка. */
.person-name a {
  color: var(--navy);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(11, 46, 92, 0.3);
}
.person-name a:hover,
.person-name a:focus-visible {
  color: var(--navy-lit);
  text-decoration-color: currentColor;
}
.person-credential,
.person-role,
.person-affil,
.person-focus,
.person-teaches {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.5;
  margin: 0 0 6px;
}
.person-credential {
  color: var(--ink-soft);
  margin: 4px 0 0;
}
.person-role {
  color: var(--ink);
  font-weight: 500;
}
.person-affil,
.person-focus {
  color: var(--ink-soft);
}
.person-teaches {
  color: var(--ink);
}
.person-teaches b {
  font-weight: 500;
  color: var(--ink-soft);
}
/* Ссылки-действия («Профиль →», «Смотреть отзыв», «← Все преподаватели»)
   набирались цветом текста и без подчёркивания — то есть выглядели подписью, а
   не переходом. На странице команды это значило, что провалиться в преподавателя
   вроде бы некуда, хотя ссылка была и имя тоже было ссылкой. Берут тот же вид,
   что ссылки в прозе: navy-lit и подчёркивание с отбивкой. */
.person-cta,
.story-cta {
  color: var(--navy-lit);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(23, 82, 155, 0.4);
}

.person-cta:hover,
.story-cta:hover {
  text-decoration-color: currentColor;
}

.person-cta:focus-visible,
.story-cta:focus-visible {
  outline: 2px solid var(--navy-lit);
  outline-offset: 3px;
}

.person-cta {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  margin-top: auto;
  padding-top: 10px;
  align-self: start;
}

/* Пальцем — 44px по высоте (замерено 33). Только на сенсорных указателях:
   мышью 33px попадаются без труда, и трогать ради этого вид на десктопе
   незачем. */
@media (pointer: coarse) {
  .person-cta,
  .story-cta {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* Шапка персональной страницы. Имени здесь нет: оно уже стоит в h1. */
.person-card {
  display: flex;
  gap: var(--sp-sm);
  align-items: flex-start;
  max-width: var(--measure-wide);
  margin: var(--sp-md) 0 0;
  padding-top: var(--sp-sm);
  border-top: 2px solid var(--navy);
}
.person-card-body {
  min-width: 0;
}
.person-card .person-credential {
  margin-top: 0;
  font-size: 15px;
}
.person-card .person-cta {
  display: inline-block;
  margin-top: 0;
}

@media (max-width: 640px) {
  .people {
    grid-template-columns: 1fr;
  }
  .person-card {
    flex-direction: column;
  }
  .person-card-photo {
    width: 96px;
    height: 96px;
  }
}
