/* ==========================================================================
   DEE MAK — SECTIONS
   Section 11 of the specification. Light/dark rhythm per Section 3.1.
   Hard cuts between sections. No inter-section gradients (Section 3.3).
   ========================================================================== */

/* =============================================================== 01 HERO ==
   LIGHT -> DARK. Photograph with bottom scrim to near-black. Cinematic open. */
.hero {
  background: var(--ink-deep);
  justify-content: flex-end;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 60% 15%; /* Section 10.2 — PH-01 */
  transform: scale(1.06);
  animation: hero-settle var(--dur-cinematic) var(--ease-editorial) 120ms both;
}

@keyframes hero-settle {
  from {
    transform: scale(1.06);
  }
  to {
    transform: scale(1);
  }
}

/* Section 10.4 — the only permitted overlay on photography.
   Двойное затемнение Hero: диагональное (45°, от левого нижнего угла) +
   горизонтальное (от левого края до ~60-75% ширины). Усилено минимум в 2
   раза по правке клиента — пиковая альфа поднята до максимума там, где
   был запас, и площадь покрытия (растянутость градиента) увеличена там,
   где альфа уже была близка к пределу. .video__scrim пока не трогаем —
   работаем по одной странице за раз, Video будет своей правкой позже. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(45deg, rgba(10, 10, 10, 0.97) 0%, rgba(10, 10, 10, 0.8) 45%, rgba(10, 10, 10, 0) 85%),
    linear-gradient(to right, rgba(10, 10, 10, 0.8) 0%, rgba(10, 10, 10, 0) 75%);
}

.video__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* То же затемнение, что и на Hero — правка клиента. */
  background: linear-gradient(45deg, rgba(10, 10, 10, 0.97) 0%, rgba(10, 10, 10, 0.8) 45%, rgba(10, 10, 10, 0) 85%),
    linear-gradient(to right, rgba(10, 10, 10, 0.8) 0%, rgba(10, 10, 10, 0) 75%);
}

.hero__inner {
  padding-bottom: max(clamp(24px, 5vh, var(--space-9)), calc(var(--safe-b) + var(--space-4)));
  justify-content: flex-end;
}

.hero__wordmark {
  color: var(--text-primary-dark);
}

.hero__wordmark-line {
  display: block;
  overflow: hidden;
}

.hero__wordmark-line > span {
  display: block;
  transform: translateY(100%);
  animation: mask-up var(--dur-reveal) var(--ease-editorial) both;
}

.hero__wordmark-line:nth-child(1) > span {
  animation-delay: 200ms;
}

.hero__wordmark-line:nth-child(2) > span {
  animation-delay: 280ms; /* 80ms stagger — Section 14.2 */
}

@keyframes mask-up {
  to {
    transform: translateY(0);
  }
}

/* Section 11.1 — the single largest orange element on the site, and justified:
   it is the one-word answer to "what is this". 5.1:1 over the scrim. */
.hero__role {
  display: block;
  color: var(--accent);
  margin-top: 2px;
  margin-left: -0.03em;
}

.hero__tags {
  margin-top: clamp(8px, 2vh, var(--space-4));
  color: var(--text-primary-dark);
}

.hero__tags-line {
  display: block;
}

.hero__location {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: clamp(6px, 1.4vh, var(--space-3));
  color: var(--text-secondary-dark);
}

.hero__pin {
  flex: none;
  width: 12px;
  height: 12px;
}

.hero__dot {
  color: var(--accent);
}

.hero__cta {
  margin-top: clamp(10px, 3.4vh, var(--space-7));
}

.hero__social {
  margin-top: clamp(4px, 1.2vh, var(--space-7));
}

/* Type reveal for everything below the wordmark. */
.hero__fade {
  opacity: 0;
  animation: hero-fade var(--dur-slow) var(--ease-editorial) both;
}

.hero__fade--1 { animation-delay: 520ms; }
.hero__fade--2 { animation-delay: 600ms; }
.hero__fade--3 { animation-delay: 680ms; }
.hero__fade--4 { animation-delay: 760ms; }

@keyframes hero-fade {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__img {
    animation: none;
    transform: scale(1);
  }
  .hero__wordmark-line > span,
  .hero__fade {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ============================================================== 02 ABOUT ==
   DARK. #121212. Правка клиента: страница делится на левую половину
   (таблица параметров + кнопка, в обычных полях страницы) и правую
   половину (фото, бликует от правого нижнего угла экрана без отступов).
   Фото вынесено за пределы .section__inner, чтобы не зависеть от padding
   страницы и бликовать к истинному краю viewport; position:absolute
   работает относительно .about, которая уже positioned через
   position:sticky (общее правило .section в layout.css). */
.about {
  background: var(--ink);
  overflow: hidden; /* уже задано в .section, дублируем явно для ясности */
  /* Единая переменная для отступов "текст → таблица" и "таблица → кнопка"
     — правка клиента требует их визуального совпадения. Используем ОДНУ
     переменную в обоих местах, а не подогнанные "похожие" числа, иначе
     совпадение будет верным только на одном конкретном размере экрана. */
  --about-gap: clamp(8px, 2vh, 32px);
}

.about__inner {
  padding-top: var(--section-header-pt);
  /* Кнопка поднята выше — отступ снизу увеличен вдвое относительно
     отступа слева (было: равен --pad-x, теперь ×2) — правка клиента.
     margin-top:auto на .about__cta ниже прижимает кнопку к этому
     нижнему полю, поглощая свободное пространство над собой. */
  padding-bottom: calc(var(--pad-x) * 2);
  flex: 1;
  min-height: 0;
  position: relative;
  z-index: 1; /* заголовок и абзац остаются НАД фото, если оно случайно
                 перекрывает верх (на очень узких экранах) */
}

.about__copy {
  color: var(--text-secondary-dark);
  margin-bottom: var(--about-gap);
  /* Расширено по правке клиента. Ограничение всё ещё нужно, чтобы текст
     не заезжал под фото на узких экранах (фото бликует от правого края
     независимо от полей страницы). */
  max-width: min(46ch, 68%);
}

/* Отступ "заголовок → текст" должен визуально совпадать с отступом
   "текст → таблица параметров" — правка клиента. Точечный override только
   для About, чтобы не менять общий .chapter в остальных секциях. */
.about .chapter {
  margin-bottom: clamp(12px, 2.2vh, var(--space-7));
}

/* Левая половина — таблица + кнопка. Сужена, чтобы не заезжать под фото
   (которое бликует от правого края без учёта отступов страницы, поэтому
   доступная ширина текста здесь меньше, чем у заголовка/абзаца выше). */
.about__split {
  display: flex;
}

.about__stats-col {
  width: 100%;
  /* Таблица должна доходить примерно до середины экрана — правка клиента.
     calc() с vw даёт правый край ровно на 50vw независимо от размера
     экрана, а не процент от суженного родителя. */
  max-width: calc(50vw - var(--gutter));
  /* flex + gap вместо margin — иначе margin-bottom таблицы и margin-top
     кнопки схлопываются (margin collapse), беря максимум вместо суммы,
     и добавленная компенсация отступа не работает предсказуемо. */
  display: flex;
  flex-direction: column;
}

.about__stats-col .stats {
  margin-bottom: 0;
}

/* Кнопка теперь вне .about__stats-col (снова во всю ширину секции) —
   отступ до неё задаём через margin-top самого блока кнопки. */
.about__cta {
  /* Прижата к нижнему полю секции (см. .about__inner padding-bottom) —
     правка клиента, отступ снизу = отступ слева. Отменяет прежнюю логику
     "совпадает с отступом текст→таблица", т.к. теперь позиция кнопки
     жёстко привязана к низу экрана, а не к высоте таблицы над ней. */
  margin-top: auto;
}

/* Фото — правая половина, от правого нижнего угла экрана, без отступов.
   object-fit:contain — фотография не обрезается, только уменьшается при
   нехватке места, оставаясь "приклеенной" к правому нижнему углу.

   Увеличено и приподнято относительно первой версии: на маленькой площади
   тёмное фото на тёмном фоне секции читалось как случайный обрезок, а не
   как часть композиции. Сверху добавлен мягкий переход (не резкий обрез)
   в цвет фона секции — фото editorial-приёмом "проступает" из темноты,
   а не обрывается по жёсткой границе. */
.about__photo {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 52vw;
  height: clamp(360px, 78vh, 740px);
  overflow: hidden;
  z-index: 0;
}

/* Лёгкое затемнение — зеркально к Hero (там от левого нижнего угла и левого
   края), здесь от правого нижнего угла и правого края, и значительно
   слабее: единственная цель — чтобы фото визуально не "выбивалось" из
   тёмной композиции секции, а не обеспечить читаемость текста поверх него. */
/* Затемнение вынесено на уровень всей секции (.about__scrim, ниже) —
   правка клиента: не в рамках прямоугольного бокса фото, а поверх и
   контейнера, и самой фотографии, с текстом/таблицей/кнопкой (z-index:1
   у .section__inner) выше этого слоя. */

.about__photo-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 100% 100%;
}

/* Затемнение на уровне всей секции — правка клиента: тот же градиент, что
   был раньше на боксе фото, но теперь растянут на всю секцию (поверх и
   контейнера фото, и самой картинки), а не ограничен рамками маленького
   бокса. section__inner (текст/таблица/кнопка) имеет z-index:1 — выше
   этого слоя, поэтому контент остаётся полностью незатронутым. */
.about__scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* Ослаблено ещё на 20% по правке клиента (было 0.62/0.36/0.36, до этого
     0.78/0.45/0.45). */
  background: linear-gradient(315deg, rgba(10, 10, 10, 0.5) 0%, rgba(10, 10, 10, 0.29) 50%, rgba(10, 10, 10, 0) 88%),
    linear-gradient(to left, rgba(10, 10, 10, 0.29) 0%, rgba(10, 10, 10, 0) 80%);
}

/* ========================================================== 03 PORTFOLIO ==
   LIGHT — cool. #E6E7EC Studio Grey. Gallery wall.

   Redesigned as a single full-screen editorial composition: one strong
   Сетка в стиле Instagram — правка клиента (было: один крупный кадр).
   В наличии только 4 реальных фотографии (не 9) — сетка построена как
   честные 3 колонки на столько рядов, сколько есть кадров (сейчас 3+1),
   без выдумывания/дублирования снимков. Как только появятся ещё фото —
   их нужно просто добавить в PORTFOLIO в content.js, сетка расширится
   сама, без правок разметки. Подписи (категория + название) видны только
   в лайтбоксе — на превью в сетке текста нет вообще, как в Instagram. */
.portfolio {
  background: var(--studio-grey);
}

.portfolio__inner {
  max-width: var(--bleed-max);
  flex: 1;
  min-height: 0;
  padding-top: var(--section-header-pt);
  /* Тот же отступ снизу, что и на About — кнопка на одной высоте на обоих
     экранах (правка клиента). */
  padding-bottom: calc(var(--pad-x) * 2);
}

.portfolio__grid {
  display: grid;
  /* 9 фото, 3 колонки × 3 ряда. Сетка растягивается (flex:1) на доступное
     пространство между заголовком и кнопкой, поэтому плитки естественно
     прямоугольные и страница выглядит заполненной. margin-bottom равен
     той же формуле, что и отступ "заголовок → сетка" (.chapter
     margin-bottom) — правка клиента: отступы сверху и снизу сетки должны
     быть одинаковыми, сетка не должна быть "приклеена" к кнопке. */
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 3px;
  flex: 1;
  margin-bottom: clamp(16px, 3vh, var(--space-6));
  min-height: 0;
}

.portfolio__tile {
  position: relative;
  /* aspect-ratio убран — высота плитки теперь определяется строкой grid
     (1fr от растянутой .portfolio__grid), а не фиксированной пропорцией.
     Это и даёт естественно прямоугольные (не квадратные) плитки. */
  overflow: hidden;
  background: var(--studio-grey-deep); /* reserves space, prevents CLS */
  padding: 0;
  border: 0;
  display: block;
  cursor: pointer;
}

.portfolio__tile-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.js-ready .portfolio__tile-img {
  /* opacity-переход убран по правке клиента — резервный серый фон плитки
     (нужен против CLS до загрузки картинки) просвечивал сквозь неё, пока
     прозрачность ещё нарастала, и читался как "серые полосы" во время
     анимации. Оставлен только эффект масштаба — картинка всегда полностью
     непрозрачна, фон под ней никогда не виден. */
  transform: scale(1.05);
  transition: transform var(--dur-reveal) var(--ease-editorial);
}

.js-ready .portfolio__grid.is-revealed .portfolio__tile-img {
  transform: scale(1);
}

@media (hover: hover) and (pointer: fine) {
  .portfolio__tile:hover .portfolio__tile-img {
    opacity: 0.9;
  }
}

.portfolio__tile:active .portfolio__tile-img {
  opacity: 0.8;
}

.portfolio__cta {
  /* Отступ сверху уже обеспечен margin-bottom сетки — margin-top:auto
     больше не нужен и создавал бы "приклеенный" эффект без него. */
  flex: none;
}

@media (prefers-reduced-motion: reduce) {
  .js-ready .portfolio__tile-img {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Asset-gap disclosure (Section 23: never fabricate photography) — только
   4 реальные фотографии, сетка честно показывает 4 ячейки, не 9. См.
   PORTFOLIO в content.js и README. */

/* ============================================================== 04 VIDEO ==
   DARK — deepest photographic. #0F0F0F + full-bleed poster. Cinema. */
.video {
  background: #0f0f0f;
  overflow: hidden;
}

.video .section__inner {
  padding-top: var(--section-header-pt);
}

.video__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.video__poster-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 52% 22%; /* Section 10.2 — PH-02 */
}


.video__copy {
  color: var(--text-secondary-dark);
  margin-bottom: var(--space-7);
  max-width: 30ch;
}

/* Жирное начертание основного шрифта сайта (не отдельный шрифт) — правка
   клиента: не более трёх шрифтов на сайте, без "диодного" стиля. */
.video__copy--diode {
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--text-primary-dark);
}

.video__stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 140px;
}

/* Один круг с треугольником внутри (было — два накладывающихся круга,
   убрал дублирующий статичный div, оставил только SVG-обводку). Section
   11.4 — a 1px stroked circle, 72px, not a filled icon-library button.
   Tap target extends to 96px. */
/* Круг с треугольником — правка клиента: SVG stroke-dasharray + вращение
   давали рассинхронизацию рендеринга (видимый разрыв в обводке) на
   некоторых устройствах. Заменено на простой CSS-круг (border-radius:50%)
   — фундаментальный примитив, который физически не может отрисоваться
   неправильно ни при каком масштабировании, в отличие от SVG-дуги.
   Section 11.4 — a circle, 72px, not a filled icon-library button. Tap
   target extends to 96px. */
.video__play {
  position: relative;
  width: 96px;
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}

.video__ring {
  position: absolute;
  inset: 12px; /* 96 - 24 = 72px ring */
  border-radius: 50%;
  border: 1px solid var(--text-primary-dark);
  opacity: 0;
  transform: scale(0.85);
}

.video.is-revealed .video__ring {
  animation: ring-reveal 700ms var(--ease-editorial) forwards,
    ring-breathe 4000ms var(--ease-in-out) 900ms infinite;
}

@keyframes ring-reveal {
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes ring-breathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.03);
  }
}

.video__triangle {
  position: relative;
  z-index: 1;
  width: 0;
  height: 0;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-left: 13px solid var(--text-primary-dark);
  margin-left: 4px; /* optical centring inside the ring */
}

.video__play:active .video__ring {
  opacity: 0.85;
}

/* Пульсирующие круги-приглашение — правка клиента: несколько оранжевых
   полупрозрачных колец, регулярно расширяющихся и исчезающих, зовущих
   нажать на кнопку. Три кольца со сдвигом по времени дают непрерывный,
   не резкий эффект. */
.video__pulse {
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  border: 1px solid var(--accent);
  opacity: 0;
}

.video.is-revealed .video__pulse {
  animation: pulse-ring 2800ms ease-out infinite;
}

.video__pulse--1 {
  animation-delay: 900ms;
}

.video__pulse--2 {
  animation-delay: 1833ms;
}

.video__pulse--3 {
  animation-delay: 2766ms;
}

@keyframes pulse-ring {
  0% {
    transform: scale(1);
    opacity: 0.55;
  }
  100% {
    transform: scale(1.65);
    opacity: 0;
  }
}

.video__link {
  margin-top: var(--space-7);
}

@media (prefers-reduced-motion: reduce) {
  .video.is-revealed .video__ring {
    animation: none;
    opacity: 1;
    transform: scale(1);
  }
  .video.is-revealed .video__pulse {
    animation: none !important;
    opacity: 0 !important;
  }
}


/* ==================================================== 05 WHAT I CAN DO ==
   LIGHT — warm. #F4F4F2 Paper. Printed page. Section 3.2 decision:
   the site's only unillustrated section on its only unillustrated ground. */
.capabilities {
  background: var(--paper);
}

.capabilities .section__inner {
  padding-top: var(--section-header-pt);
  /* Тот же отступ снизу, что и на About/Portfolio — кнопка на одной
     высоте на всех страницах (кроме Hero) — правка клиента. */
  padding-bottom: calc(var(--pad-x) * 2);
}

.capabilities__copy {
  color: var(--text-secondary-light);
  margin-bottom: clamp(6px, 0.8vh, var(--space-7));
}

.capabilities__cta {
  /* Прижата к нижнему полю секции — та же механика, что у About. */
  margin-top: auto;
}

/* ============================================================ 06 CONTACT ==
   BLACK. #0A0A0A + scrimmed image. Final, weighted.
   The heaviest, darkest screen on the site. */
.contact {
  background: var(--ink-deep);
  overflow: hidden;
}

.contact__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.contact__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 30%; /* Section 10.2 — PH-04 */
  opacity: 0.55; /* Section 10.4 */
}

.contact__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(10, 10, 10, 0.75) 55%,
    #0a0a0a 100%
  );
}

/* Номер страницы — вынесен из bottom-anchored блока, позиционируется
   так же, как на страницах 2-5 (--section-header-pt), независимо от
   текста закрытия, который остаётся внизу. */
.contact__header {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--pad-x) var(--pad-x-end);
  padding-top: var(--section-header-pt);
  flex: none;
}

.contact__inner {
  justify-content: flex-end;
  padding-bottom: max(var(--space-9), calc(var(--safe-b) + var(--space-6)));
}

.contact__statement {
  color: var(--text-primary-dark);
  margin-top: auto;
}

/* Section 14.2 — line-by-line close, mask up, 90ms stagger. */
.contact__line {
  display: block;
  overflow: hidden;
}

.js-ready .contact__line > span {
  display: block;
  transform: translateY(100%);
  transition: transform 640ms var(--ease-editorial);
}

.contact.is-revealed .contact__line > span {
  transform: translateY(0);
}

.contact.is-revealed .contact__line:nth-child(1) > span { transition-delay: 0ms; }
.contact.is-revealed .contact__line:nth-child(2) > span { transition-delay: 90ms; }
.contact.is-revealed .contact__line:nth-child(3) > span { transition-delay: 180ms; }
.contact.is-revealed .contact__line:nth-child(4) > span { transition-delay: 270ms; }

.contact__copy {
  color: var(--text-secondary-dark);
  margin-bottom: var(--space-7);
  max-width: 34ch;
}

.js-ready .contact__cta {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-editorial) 510ms;
}

.js-ready .contact.is-revealed .contact__cta {
  opacity: 1;
}

/* Сдержанное "мерцание" — правка клиента: диагональный блик, редко и
   плавно проходящий по кнопке, чтобы притягивать взгляд, не отвлекая.
   Долгая пауза между проходами (цикл 6с, сам блик — доля секунды) —
   специально применено только к кнопке Contact, не ко всем primary-кнопкам
   сайта. */
.contact__cta .btn {
  position: relative;
  overflow: hidden;
}

.contact__cta .btn::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Более узкая, контрастная полоса — на насыщенном оранжевом фоне
     широкий мягкий блик почти не читается, нужен более чёткий световой
     штрих, чтобы эффект был заметен, оставаясь коротким и ненавязчивым. */
  background: linear-gradient(
    115deg,
    transparent 44%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 56%
  );
  transform: translateX(-130%);
  pointer-events: none;
}

.js-ready .contact.is-revealed .contact__cta .btn::after {
  /* В 2 раза чаще по правке клиента (было 6000ms). */
  animation: contact-shine 3000ms ease-in-out 2000ms infinite;
}

/* Тот же блик — на основной кнопке Hero ("BOOK ME FOR CASTING"), правка
   клиента. Hero видна сразу при загрузке (не через data-reveal/scroll),
   поэтому анимация запускается по .js-ready, без привязки к is-revealed
   секции. */
.hero__cta .btn--primary {
  position: relative;
  overflow: hidden;
}

.hero__cta .btn--primary::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    115deg,
    transparent 44%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 56%
  );
  transform: translateX(-130%);
  pointer-events: none;
}

.js-ready .hero__cta .btn--primary::after {
  animation: contact-shine 3000ms ease-in-out 2000ms infinite;
}

/* Проценты пересчитаны так, чтобы сам пробег блика оставался ~600ms
   (визуальная скорость как раньше, до укорочения общего цикла) — только
   частота повторения (длина цикла) была сокращена, не скорость движения
   самого блика. При duration:3000ms 20% = 600ms. */
@keyframes contact-shine {
  0%,
  14% {
    transform: translateX(-130%);
  }
  34%,
  100% {
    transform: translateX(130%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .js-ready .contact__line > span {
    transform: none;
    transition: none;
  }
  .js-ready .contact__cta {
    opacity: 1;
    transition: none;
  }
  .contact__cta .btn::after {
    animation: none !important;
    display: none;
  }
  .hero__cta .btn--primary::after {
    animation: none !important;
    display: none;
  }
}

/* ================================================================ FOOTER ==
   Section 11.6 — below a full-width hairline, at roughly 28% of the visual
   weight of the closing block. Legally present and visually silent. */
.footer {
  margin-top: var(--space-9);
  padding-top: var(--space-5);
  border-top: var(--border-width) solid var(--border-dark);
}

.footer__row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-6);
  margin-bottom: var(--space-5);
}

.footer__brand {
  color: var(--text-secondary-dark);
}

.footer__brand span {
  display: block;
}

.footer__links {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-end;
}

.footer__link {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  color: var(--text-secondary-dark);
  transition: color var(--dur-fast) var(--ease-standard);
}

.footer__link[data-pending="true"] {
  color: var(--text-muted-dark);
  cursor: default;
}

@media (hover: hover) and (pointer: fine) {
  .footer__link:not([data-pending="true"]):hover {
    color: var(--accent);
  }
}

.footer__legal {
  color: var(--text-muted-dark);
}

/* ============================================ GLOBAL SECTION-HEADER REVEAL */
/* Section 14.3 — fade + translateY(16px), 480ms, once only. Never replays. */
.js-ready .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 480ms var(--ease-editorial),
    transform 480ms var(--ease-editorial);
}

.js-ready .reveal.is-revealed {
  opacity: 1;
  transform: translateY(0);
}

.reveal--d1 { transition-delay: 60ms; }
.reveal--d2 { transition-delay: 120ms; }
.reveal--d3 { transition-delay: 180ms; }

@media (prefers-reduced-motion: reduce) {
  .js-ready .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Section 14.2 — About: each stat row's 1px border scales 0 -> 100% from left.
   Progressive enhancement: without JavaScript the real border-bottom stays
   visible. Once main.js sets .js-ready the border goes transparent and the
   pseudo-element performs the draw, so the row is never double-ruled. */
.js-ready .stats__label,
.js-ready .stats__value {
  border-bottom-color: transparent;
}

.stats__label::after,
.stats__value::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--border-dark);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-editorial);
}

.stats.is-revealed .stats__label::after,
.stats.is-revealed .stats__value::after {
  transform: scaleX(1);
}

.stats.is-revealed > *:nth-child(-n + 2)::after { transition-delay: 0ms; }
.stats.is-revealed > *:nth-child(n + 3):nth-child(-n + 4)::after { transition-delay: 60ms; }
.stats.is-revealed > *:nth-child(n + 5):nth-child(-n + 6)::after { transition-delay: 120ms; }
.stats.is-revealed > *:nth-child(n + 7):nth-child(-n + 8)::after { transition-delay: 180ms; }
.stats.is-revealed > *:nth-child(n + 9)::after { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  .stats__label::after,
  .stats__value::after {
    transform: scaleX(1);
    transition: none;
  }
}
