/* ═══ КНОПКИ ══════════════════════════════════════════════════════════
   Три уровня, четвёртого не существует. Плотных заливок --ink на экране
   ровно одна: именно её дефицит делает кнопку заметной, а не яркость.   */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2); min-height: var(--tap); padding: 0 var(--s-5);
  border: 0; border-radius: var(--radius); background: none;
  font: 500 16px/1 var(--font-text); text-decoration: none;
  text-align: center; cursor: pointer;
  transition: background var(--dur-ui) var(--ease),
              color var(--dur-ui) var(--ease),
              border-color var(--dur-ui) var(--ease);
}
.btn--primary { background: var(--ink); color: var(--paper); }
.btn--primary:hover { background: var(--ink-hover); }
.btn--secondary { color: var(--ink); border: 1px solid var(--ink); }
.btn--secondary:hover { background: var(--ink); color: var(--paper); }
/* Область нажатия 44px: сам текст мелкий, но палец промахиваться
   не должен. mobile first — это в том числе про попадание пальцем.  */
.btn--quiet {
  display: inline-flex; align-items: center; min-height: 44px;
  /* min-width тоже: «Выйти» давало 42px по ширине */
  min-width: 44px; padding: 0; color: var(--ink);
  font-size: var(--fs-small); line-height: 1.4; text-decoration: underline;
  text-decoration-color: var(--gold); text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.btn--quiet:hover { text-decoration-color: var(--ink); }
.btn--block { width: 100%; }
.btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.btn--ext::after { content: "↗"; font-size: .85em; opacity: .65; }

/* Согласие на аналитические cookies: без согласия Google Analytics не
   загружается. Панель остаётся компактной и не перекрывает весь экран. */
.cookie-consent {
  position: fixed; right: var(--s-4); bottom: var(--s-4); z-index: 80;
  width: min(440px, calc(100vw - var(--s-6))); padding: var(--s-5);
  background: var(--paper); border: var(--border); border-radius: var(--radius);
  box-shadow: 0 12px 36px rgba(29, 39, 61, .16);
  color: var(--ink); font-size: var(--fs-small); line-height: 1.5;
}
.cookie-consent p { margin: 0; }
.cookie-consent__title { font-weight: 600; font-size: 16px; margin-bottom: var(--s-2) !important; }
.cookie-consent a { color: inherit; text-decoration-color: var(--gold); text-underline-offset: 3px; }
.cookie-consent__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
.cookie-consent__actions .btn { min-height: 40px; padding: 0 var(--s-4); font-size: var(--fs-small); }
@media (max-width: 480px) {
  .cookie-consent { right: var(--s-3); bottom: var(--s-3); width: calc(100vw - var(--s-6)); }
  .cookie-consent__actions .btn { flex: 1 1 150px; }
}

/* Сессия покупателя — отдельна от админки: в шапке только вход или
   профиль, без email и без раскрытия личных данных на общем экране. */
.hdr__account { display: inline-flex; align-items: center; min-height: 44px;
                padding: 0 4px; color: var(--ink); font-size: var(--fs-small);
                text-decoration: none; white-space: nowrap; }
.hdr__account:hover { text-decoration: underline; text-decoration-color: var(--gold); }
@media (max-width: 760px) { .hdr__account { display: none; } }

/* ═══ МЕТКИ ═══════════════════════════════════════════════════════════
   Метка — отдельный элемент в фиксированном слоте, НИКОГДА не приставка
   к заголовку. Ответ на «SOLD OUT - …» у saraauster.com.
   Единственное место на сайте, где разрешён капс с разрядкой.          */
.chip {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px;
  border: 1px solid transparent; border-radius: var(--radius);
  font: 600 var(--fs-label)/1 var(--font-text);
  letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
}
.chip--next  { color: var(--gold-ink); border-color: var(--gold); }
.chip--sold  { color: var(--rose); border-color: var(--rose);
               background: var(--rose-tint); }
.chip--muted { color: var(--ink-soft); border-color: var(--line); }
.chip--soon  { color: var(--sage); border-color: var(--sage);
               background: var(--sage-tint); }
.chip--free  { color: var(--sage); border-color: var(--sage);
               background: var(--sage-tint); }
.chip--online{ color: var(--ink-soft); border-color: var(--line); }

/* ═══ НАВИГАЦИЯ ═══════════════════════════════════════════════════════ */
.hdr {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper); border-bottom: var(--border);
}
.hdr__in { display: flex; align-items: center; gap: var(--s-3);
           min-height: var(--hdr-h); }
.logo { display: block; text-decoration: none; margin-right: auto;
        padding: var(--s-2) 0; }
/* На 375px «CRYSTAL SOUND THERAPY» в 13px с трекингом .1em переносилось
   на две строки, и хедер вырастал до трёх текстовых строк. Кегль
   и трекинг уменьшены до 400px. */
.logo__name { display: block; font: 600 11px/1.25 var(--font-text);
              letter-spacing: .06em; text-transform: uppercase;
              white-space: nowrap; }
@media (min-width: 400px) {
  .logo__name { font-size: 13px; letter-spacing: .1em; }
}
.logo__person { display: block; font-family: var(--font-display);
                font-style: italic; font-size: 15px; line-height: 1.3;
                color: var(--ink-soft); }

/* Переключатель языка СНАРУЖИ бургера: англоязычная посетительница
   не должна искать его внутри меню на незнакомом языке.                */
.lang { display: flex; align-items: center; }
.lang { flex: none; }
.lang__btn {
  min-width: 44px; min-height: 44px; padding: 0 var(--s-2);
  background: none; border: 0;
  font: 400 14px/1 var(--font-text); color: var(--ink-soft);
  cursor: pointer; letter-spacing: .04em;
}
.lang__btn[aria-pressed="true"] { color: var(--ink); font-weight: 600; }
.lang__sep { color: var(--line); }

/* flex: none — иначе на 375px бургер сжимался до 40px, ниже
   обязательной тап-зоны 44px. */
.burger { flex: none; width: 44px; height: 44px; display: grid;
          place-content: center; gap: 5px; cursor: pointer; }
.burger span:not(.vh) { display: block; width: 18px; height: 1px;
               background: var(--ink); transition: transform var(--dur-ui); }
/* nth-of-type, а не last-child: последний ребёнок — скрытая подпись
   для скринридера, и крест собирался из одной диагонали
   и одной горизонтальной полоски. Сдвиг ровно 3px при gap 5px
   сводит полоски в одну точку. */
.burger[aria-expanded="true"] span:nth-of-type(1) { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-of-type(2) { transform: translateY(-3px) rotate(-45deg); }

/* Верх меню считается от переменной, а не от литерала 60px:
   фактическая высота хедера другая и меняется с кеглем лого. */
.menu {
  position: fixed; inset: var(--hdr-h) 0 0; z-index: 39; background: var(--paper);
  padding: var(--s-6) var(--pad-x) var(--s-8); overflow-y: auto;
  display: none;
}
.menu.is-open { display: block; }
.menu__list > li + li { margin-top: var(--s-5); }
.menu__link {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--tap); font-family: var(--font-display);
  font-size: 27px; line-height: 1.2; text-decoration: none;
}
.menu__link[aria-current="page"] {
  text-decoration: underline; text-decoration-color: var(--gold);
  text-decoration-thickness: 1px; text-underline-offset: 6px; font-weight: 600;
}
.menu__foot { margin-top: var(--s-7); padding-top: var(--s-5);
              border-top: var(--border); font-size: 15px; }
.menu__foot a { display: block; min-height: 40px; line-height: 40px;
                text-decoration: none; }

/* Десктоп: хедер в ДВЕ строки. Восемь пунктов полными названиями
   («Что такое звуковая терапия» — 26 знаков) в одну строку с лого
   и переключателем языка не влезают ни при 1280px, ни при 1440px.
   Сжимать кегль до нечитаемого или сокращать названия — хуже:
   состав и формулировки меню зафиксированы.                          */
@media (min-width: 1100px) {
  .burger { display: none; }
  .hdr__in { flex-wrap: wrap; align-items: center; padding-bottom: 0; }
  .logo { margin-right: auto; }
  .lang { order: 2; }
  .menu {
    order: 3; flex: 1 1 100%; position: static; inset: auto; display: block;
    background: none; padding: 0; overflow: visible;
    border-top: var(--border); margin-top: var(--s-2);
  }
  .menu__list { display: flex; align-items: center; gap: var(--s-5);
                flex-wrap: wrap; }
  .menu__list > li + li { margin-top: 0; }
  .menu__link { font-family: var(--font-text); font-size: 15px;
                font-weight: 400; min-height: 44px; white-space: nowrap; }
  .menu__foot { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   КАРТОЧКА СОБЫТИЯ — главный компонент сайта
   Порядок: когда → что → где → сколько длится → сколько стоит → действие
   ═══════════════════════════════════════════════════════════════════════ */
.ev {
  position: relative; display: flex; flex-direction: column;
  background: var(--paper-2); border: var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.ev__media { position: relative; flex: none; }
.ev__media img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.ev__body { padding: var(--s-5); display: flex; flex-direction: column;
            flex: 1 1 auto; }

/* Слот меток фиксирован по высоте — карточки не прыгают друг относительно
   друга, когда у одной метка есть, а у другой нет.                     */
.ev__flags { display: flex; gap: var(--s-2); min-height: 20px;
             flex-wrap: wrap; }

/* КОГДА — выше названия: человек выбирает не «что», а «смогу ли я
   в этот вечер». День недели первым — планируют неделями.              */
.ev__when { margin-top: var(--s-3); font: 500 var(--fs-data)/var(--lh-data)
            var(--font-text); font-variant-numeric: tabular-nums; }
.ev__title { margin-top: var(--s-2); }
/* Ссылка-заголовок карточки: перекрытие ::after делает кликабельной
   всю карточку, но сама ссылка тоже должна быть тап-зоной 44px —
   ею пользуются с клавиатуры и её видит проверка доступности. */
.ev__title a { text-decoration: none; display: inline-block;
  padding: 8px 0; margin: -8px 0; }
.ev__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }

.ev__where, .ev__facts {
  font-size: var(--fs-small); line-height: var(--lh-small);
  color: var(--ink-soft);
}
.ev__where { margin-top: var(--s-3); display: flex; align-items: baseline;
             gap: 6px; }
.ev__where svg { flex: none; width: 12px; height: 12px; opacity: .7;
                 transform: translateY(1px); }
/* СКОЛЬКО ДЛИТСЯ — параметры убивают страх лучше прилагательных.
   Главный страх темы: «полтора часа лежать с закрытыми глазами».      */
.ev__facts { margin-top: var(--s-1); }

.ev__stock { margin-top: var(--s-3); font: 500 var(--fs-small)/1.4
             var(--font-text); color: var(--gold-ink); }

.ev__dates { margin-top: var(--s-3); display: flex; flex-wrap: wrap;
             gap: var(--s-2); }
.ev__date {
  position: relative; z-index: 2; display: inline-flex; align-items: center;
  justify-content: center; min-width: 44px;
  min-height: 44px; padding: 0 10px; border: var(--border);
  border-radius: var(--radius); font: 500 var(--fs-small)/1 var(--font-text);
  font-variant-numeric: tabular-nums; text-decoration: none;
}
.ev__date:hover { border-color: var(--ink); }
.ev__date--theme { border-color: var(--rose); color: var(--rose); }

.ev__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); margin-top: auto; padding-top: var(--s-5);
  border-top: var(--border); flex-wrap: wrap;
}
/* Цена и кнопка в одной строке: связка «25 € → Забронировать» должна
   читаться одним движением глаза. Кнопка НЕ на всю ширину.            */
/* nowrap: иначе «28 €» ломается на «28» и «€», когда рядом длинная
   кнопка вроде «Сообщить, если освободится место».                   */
.ev__price { flex: none; white-space: nowrap;
             font: 500 var(--fs-price)/1.2 var(--font-text);
             font-variant-numeric: tabular-nums; }
.ev__cta, .ev__first, .ev__nextlink { position: relative; z-index: 2; }
.ev__first { margin-top: var(--s-4); align-self: flex-start; }
.ev__nextlink { margin-top: var(--s-3); font-size: var(--fs-small);
                color: var(--ink-soft); }
.ev__nextlink a { text-decoration-color: var(--line); }

/* ── СОСТОЯНИЯ ─────────────────────────────────────────────────────────
   Приходят из sale_status / event_status Fienta. Числа мест не нужно.  */
.ev[data-sale="soldOut"] .ev__media img,
.ev[data-sale="salesEnded"] .ev__media img,
.ev[data-event="cancelled"] .ev__media img { filter: saturate(.45); }
.ev[data-sale="soldOut"] .ev__media::after,
.ev[data-sale="salesEnded"] .ev__media::after,
.ev[data-event="cancelled"] .ev__media::after {
  content: ""; position: absolute; inset: 0;
  background: var(--paper); opacity: .40; pointer-events: none;
}
/* Цена НЕ зачёркивается: она информативна, а не отменена. */
.ev[data-sale="soldOut"] .ev__price,
.ev[data-sale="salesEnded"] .ev__price { color: var(--ink-soft); }
.ev__cancelled { font: 500 var(--fs-data)/1.3 var(--font-text);
                 color: var(--rose); }

/* Ближайшее событие баннером — на страницах списка */
.ev--hero .ev__media img { aspect-ratio: 16/9; }
@media (min-width: 700px) {
  .ev--hero { flex-direction: row; }
  .ev--hero .ev__media { width: 52%; }
  .ev--hero .ev__media img,
  .ev--hero .ev__media .ph { height: 100%; aspect-ratio: auto;
                             min-height: 280px; }
  .ev--hero .ev__body { padding: var(--s-6); }
  .ev--hero .ev__title { font-size: 32px; }
}

/* ═══ ПУСТОЕ СОСТОЯНИЕ БЛОКА СОБЫТИЙ ═════════════════════════════════
   Слов «событий нет», «зайдите позже» не существует в текстах сайта.  */
.empty { display: grid; gap: var(--gap-cards); }
.empty__card {
  background: var(--paper-2); border: var(--border);
  border-radius: var(--radius); padding: var(--s-5);
}
.empty__card--wide { padding: 0; overflow: hidden; }
.empty__card--wide .empty__inner { padding: var(--s-5); }
.empty__card h3 { margin-bottom: var(--s-3); }
.empty__card p { font-size: var(--fs-small); line-height: var(--lh-small);
                 color: var(--ink-soft); margin-bottom: var(--s-4); }
@media (min-width: 900px) { .empty--three { grid-template-columns: repeat(3,1fr); } }

/* ═══ ПРОШЕДШИЕ СОБЫТИЯ ═══════════════════════════════════════════════
   Прошедшие события — доказательство, а не мусор. Пустой список будущих
   рядом с плотным списком прошедших читается как «практика между
   сериями»; рядом с пустой страницей — как «сайт заброшен».            */
.past { margin-top: var(--s-7); padding-top: var(--s-5);
        border-top: var(--border); }
.past__count { font-family: var(--font-display); font-style: italic;
               font-size: 21px; margin-bottom: var(--s-4); }
.past__row {
  display: flex; gap: var(--s-3); align-items: baseline;
  min-height: 44px; padding: var(--s-2) 0; border-bottom: 1px solid
  color-mix(in srgb, var(--line) 55%, transparent);
  font-size: var(--fs-small); text-decoration: none;
}
.past__date { flex: none; width: 108px; color: var(--ink-soft);
              font-variant-numeric: tabular-nums; }
.past__venue { margin-left: auto; color: var(--ink-soft); display: none; }
@media (min-width: 600px) { .past__venue { display: block; } }

/* ═══ КАРТОЧКА АЛЬБОМА ════════════════════════════════════════════════ */
.alb { background: var(--paper-2); border: var(--border);
       border-radius: var(--radius); overflow: hidden;
       display: flex; flex-direction: column; }
.alb__cover img, .alb__cover .ph { aspect-ratio: 1/1; object-fit: cover; }
.alb__body { padding: var(--s-5); display: flex; flex-direction: column;
             flex: 1; }
/* У карточки события вся площадь кликабельна через ::after, у альбома
   заголовок — отдельная ссылка. Добираем область нажатия до 42px.    */
/* 44px по вертикали при сохранённом визуальном размере строки:
   отрицательный внешний отступ компенсирует внутренний. */
.alb__body h3 a { display: inline-block; padding: 11px 0; margin: -11px 0; }
.alb__meta { margin-top: var(--s-2); font-size: var(--fs-small);
             color: var(--ink-soft); }
.alb__foot { display: flex; align-items: center; justify-content: space-between;
             gap: var(--s-4); margin-top: auto; padding-top: var(--s-5); }
.alb__price { font: 500 var(--fs-price)/1.2 var(--font-text); }
.alb__price--small { font-size: var(--fs-small); font-weight: 400;
                     color: var(--ink-soft); max-width: 12em; }

/* ═══ СПИСОК ДОРОЖЕК МАГАЗИНА ═════════════════════════════════════════
   У preview нет ни перемотки, ни громкости: это короткое знакомство со
   звучанием. Название занимает гибкую колонку и переносится, поэтому
   длинные названия не раздавливают действия справа. */
.music-track { display: grid; grid-template-columns: minmax(0, 1fr) auto;
               gap: var(--s-4); align-items: center; padding: var(--s-4) 0;
               border-bottom: var(--border); }
.music-track:first-child { border-top: var(--border); }
.music-track__about { min-width: 0; display: flex; align-items: baseline;
                      gap: var(--s-3); }
.music-track__title { min-width: 0; overflow-wrap: anywhere; }
.music-track__duration { flex: none; color: var(--ink-soft);
                         font-variant-numeric: tabular-nums; white-space: nowrap; }
.music-track__actions { display: flex; align-items: center; justify-content: flex-end;
                        gap: var(--s-3); }
.music-track__player { grid-column: 1 / -1; min-width: 0; }
.music-track__player audio { display: block; width: min(100%, 720px); height: 42px; }
.music-track__play { display: inline-flex; align-items: center; justify-content: center;
                     gap: 9px; min-width: 148px; min-height: 44px; padding: 0 var(--s-4);
                     border: 1px solid var(--ink); border-radius: var(--radius);
                     background: transparent; color: var(--ink); font: 500 15px/1 var(--font-text);
                     cursor: pointer; white-space: nowrap; }
.music-track__play:hover, .music-track__play[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
.music-track__icon { width: 12px; text-align: center; font-size: 12px; }
.music-track__note { min-width: 114px; color: var(--ink-soft); font-size: var(--fs-small); white-space: nowrap; }
.music-track__actions audio { display: none; }
@media (max-width: 640px) {
  .music-track { grid-template-columns: 1fr; gap: var(--s-3); }
  .music-track__actions { justify-content: flex-start; flex-wrap: wrap; }
  .music-track__player { grid-column: auto; }
  .music-track__player audio { width: 100%; }
  .music-track__play { min-width: 0; }
  .music-track__note { min-width: 0; }
}

/* ═══ АУДИОПЛЕЕР ══════════════════════════════════════════════════════
   Ядро продукта — картинкой не показывается. Один <audio> на страницу.  */
.pl { background: var(--paper-2); border: var(--border);
      border-radius: var(--radius); padding: var(--s-4);
      display: flex; align-items: center; gap: var(--s-4); }
.pl__play {
  flex: none; width: 48px; height: 48px; border-radius: 50%;
  /* Кольцо — граница контрола, а не украшение: --gold даёт 2.55:1
     на карточке, кнопку play не видно. Отдельный токен, потому что
     текстовое золото и золото рамок — разные роли. */
  border: 1px solid var(--gold-ring); background: transparent;
  display: grid; place-content: center; cursor: pointer;
  transition: background var(--dur-ui) var(--ease);
}
.pl__play svg { width: 14px; height: 16px; fill: var(--ink); }
.pl.is-playing .pl__play { background: var(--teal); border-color: var(--teal); }
.pl.is-playing .pl__play svg { fill: var(--paper); }
.pl__main { flex: 1; min-width: 0; }
.pl__title { font: 500 var(--fs-data)/1.3 var(--font-text);
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl__under { display: flex; align-items: center; gap: var(--s-3);
             margin-top: var(--s-2); }
.pl__time { flex: none; font-size: var(--fs-small); color: var(--ink-soft);
            font-variant-numeric: tabular-nums; }

/* Полоса: визуально 3px, тап-зона 44px через прозрачный padding */
.bar { position: relative; flex: 1; min-width: 60px; height: 44px;
       display: flex; align-items: center; cursor: pointer; touch-action: none; }
.bar__track { position: relative; width: 100%; height: 3px;
              background: var(--line); border-radius: 2px; }
.bar__fill { position: absolute; inset: 0 auto 0 0; width: 0;
             background: var(--ink); border-radius: 2px; }
.bar__knob {
  position: absolute; top: 50%; left: 0; width: 12px; height: 12px;
  margin-left: -6px; border-radius: 50%; background: var(--ink);
  transform: translateY(-50%) scale(0); transition: transform var(--dur-ui);
}
.bar:hover .bar__knob, .bar:focus-visible .bar__knob,
.is-playing .bar__knob { transform: translateY(-50%) scale(1); }

/* Каталожная строка */
.pl--row { background: none; border: 0; border-bottom: var(--border);
           border-radius: 0; padding: var(--s-3) 0; align-items: flex-start;
           gap: var(--s-3); }
.pl--row .pl__play { width: 44px; height: 44px; }
.pl--row .pl__play svg { width: 12px; height: 14px; }
/* На 375px в одну строку не влезает: название обрезалось многоточием.
   Метка и длительность переносятся на вторую строку.                  */
.pl--row .pl__head { display: flex; align-items: baseline; gap: var(--s-3);
                     row-gap: var(--s-1); min-height: 44px; flex-wrap: wrap; }
.pl--row .pl__title { flex: 1 1 55%; white-space: normal;
                      overflow: visible; text-overflow: clip; }
.pl--row .pl__n { flex: none; width: 20px; color: var(--ink-soft);
                  font-size: var(--fs-small); font-variant-numeric: tabular-nums; }
.pl--row .pl__dur { margin-left: auto; flex: none; font-size: var(--fs-small);
                    color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.pl--row .pl__under { display: none; }
.pl--row.is-playing .pl__under { display: flex; }
.pl--row.is-playing { border-left: 2px solid var(--teal);
                      padding-left: var(--s-3); }
.pl--row.is-playing .pl__title { color: var(--teal); }
.pl__previewend { display: none; align-items: center; gap: var(--s-4);
                  margin-top: var(--s-3); font-size: var(--fs-small);
                  color: var(--ink-soft); flex-wrap: wrap; }
.pl--row.is-previewend .pl__previewend { display: flex; }
.pl--row.is-previewend .pl__under { display: none; }

/* ═══ ФОРМЫ ═══════════════════════════════════════════════════════════
   В подписке и ожидании — РОВНО одно поле. Имя не спрашиваем.          */
.form { max-width: 34em; }
.form__row { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.inp {
  flex: 1 1 200px; min-height: var(--tap); padding: 0 var(--s-4);
  /* --border-ctrl, а не --border: линейка разделителей даёт 1.35:1
     на карточке — границы поля ввода буквально не видно. */
  background: var(--paper); border: var(--border-ctrl);
  border-radius: var(--radius);
  /* 16px обязательно: при меньшем iOS Safari зумит страницу при фокусе */
  font: 400 16px/1 var(--font-text);
}
.inp:focus { border-color: var(--ink); }
textarea.inp { min-height: 120px; padding: var(--s-3) var(--s-4);
               line-height: 1.5; resize: vertical; }
.form__note { margin-top: var(--s-3); font-size: 13px; line-height: 1.5;
              color: var(--ink-soft); }
.form__ok { font-size: var(--fs-small); color: var(--sage);
            line-height: var(--lh-small); }
.form__err { margin-top: var(--s-2); font-size: 13px; color: var(--rose); }
.form__label { display: block; margin-bottom: var(--s-2);
               font-size: var(--fs-small); color: var(--ink-soft); }
.form__radios { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.form__radio { display: inline-flex; align-items: center; gap: var(--s-2);
               min-height: 44px; font-size: var(--fs-small); cursor: pointer; }
.form__check { display: flex; align-items: flex-start; gap: var(--s-3);
               min-height: 44px; font-size: var(--fs-small); cursor: pointer; }
.code-inp { font-variant-numeric: tabular-nums; letter-spacing: .12em;
            text-transform: uppercase; font-weight: 500; }

/* ═══ ОТЗЫВЫ ══════════════════════════════════════════════════════════
   Имя и город обязательны. Аватарок нет: стоковые лица убивают доверие
   быстрее, чем их отсутствие.                                          */
/* ── Отзывы: лента с прокруткой вбок ──────────────────────────────────
   На 375px одна цитата в ширину со следующей, подглядывающей из-за
   края; на ≥900px две; дальше прокруткой и стрелками.

   overflow-y задан явно: иначе по правилам CSS второй осью становится
   auto, и вертикальный жест телефона начинает прокручивать саму ленту.
   Цитата на телефоне свёрнута, чтобы лента оставалась ниже экрана.
   Это сохраняет обычную вертикальную прокрутку страницы вокруг неё.    */
.tsts {
  display: flex;
  gap: var(--s-5);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin-right: calc(var(--pad-x) * -1);
}
.tsts::-webkit-scrollbar { display: none; }
.tsts > .tst {
  flex: 0 0 86%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  max-width: none;
}
/* После последней карточки нужен реальный хвост. Одного padding у
   карточки недостаточно: box-sizing включает его в её ширину, и край
   последнего snap-пункта останавливался раньше начала карточки. */
.tsts::after {
  content: "";
  flex: 0 0 max(0px, calc(14% - var(--s-5) + 1px));
}
.tsts > .tst:last-child { padding-right: 0; }
.tsts:focus-visible { outline: 2px solid var(--gold-ink); outline-offset: 4px; }

/* Свёрнутая цитата. line-clamp, а не max-height с растворением:
   растворение — это градиент, а их бриф запрещает (§2.2). Клампом
   строка обрывается многоточием, и обрыв виден честно.              */
.tst__text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 9;
  overflow: hidden;
}
.tst.is-full .tst__text {
  -webkit-line-clamp: none;
  height: auto;
  overflow: visible;
}
.tst__more {
  display: inline-flex; align-items: center; min-height: 44px;
  margin-top: var(--s-2); padding: 0;
  font-size: var(--fs-small); color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--gold);
  text-underline-offset: 4px; cursor: pointer;
}
.tst__more:hover { text-decoration-color: var(--ink); }
.tst__more[hidden] { display: none; }

@media (min-width: 900px) {
  .tsts {
    display: flex; gap: var(--s-6); margin-right: 0;
    overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .tsts::-webkit-scrollbar { display: none; }
  .tsts::after { display: none; }
  /* Ровно две в ширину. Половина минус половина зазора. */
  .tsts > .tst { flex: 0 0 calc(50% - var(--s-6) / 2); scroll-snap-align: start; }
  .tsts > .tst:last-child { padding-right: 0; }
  /* На десктопе сохраняем тот же свёрнутый вид, что и на мобильном.
     Фиксированная высота даёт одинаковую линию начала авторства у
     всех карточек; длинные отзывы получают «Читать целиком». */
  .tst__text { height: calc(9 * 1.5em); }
}

/* Стрелки. Прячутся целиком, когда прокручивать нечего: мёртвых
   серых кнопок на сайте не бывает ни в одном состоянии (§11.10). */
.tsts__nav { display: flex; gap: var(--s-2); justify-content: flex-end;
             margin-top: var(--s-4); }
.tsts__nav[hidden] { display: none; }
.tsts__arw {
  width: 44px; height: 44px; display: grid; place-content: center;
  border: var(--border-ctrl); border-radius: var(--radius);
  background: none; color: var(--ink); cursor: pointer;
  transition: background var(--dur-ui) var(--ease),
              color var(--dur-ui) var(--ease);
}
.tsts__arw svg { width: 16px; height: 16px; }
.tsts__arw:hover { background: var(--ink); color: var(--paper); }
/* Стрелка, которой сейчас некуда вести. Место сохраняется, чтобы
   вторая не прыгала. Почему opacity, а не visibility, — в app.js
   рядом с функцией off(): Chrome рисовал вложенный svg вопреки
   visibility: hidden у кнопки. */
.tsts__arw.is-off { opacity: 0; pointer-events: none; }

.tst { padding-left: var(--s-5); border-left: 1px solid var(--line);
       max-width: 34em; }
/* Отступа между карточками нет: они всегда в ленте, бок о бок. */
.tst__text { font-family: var(--font-display); font-style: italic;
             font-size: 21px; line-height: 1.5; }
.tst__text p + p { margin-top: var(--s-4); }
/* Кавычки-ёлочки ставятся здесь, а не в данных: отзыв многоабзацный,
   и обрамлять каждый абзац по отдельности неверно — открывающая
   в начале первого, закрывающая в конце последнего. */
.tst__text p:first-child::before { content: "«"; }
.tst__text p:last-child::after { content: "»"; }
.tst__by { margin-top: var(--s-4); font-size: var(--fs-small);
           color: var(--ink-soft); }
/* Должность отдельной строкой. Спецификация (§2.8) требовала «имя
   и город»; в настоящих отзывах города нет, зато есть профессия —
   «специалист телесных практик», «агент по недвижимости». Для
   доверия это сильнее города, и строка своя, чтобы имя читалось
   именем, а не частью перечисления. */
.tst__role { display: block; margin-top: 2px; }

/* ═══ ХРОНОМЕТРАЖ ═════════════════════════════════════════════════════
   Главный ответ на страх первого раза. Такого нет ни у кого
   из изученных сайтов.                                                 */
.tl { position: relative; }
.tl__i { position: relative; display: flex; gap: var(--s-4);
         padding-bottom: var(--s-5); }
.tl__i:last-child { padding-bottom: 0; }
.tl__i::before {
  content: ""; position: absolute; left: 3px; top: 16px; bottom: 0;
  width: 1px; background: var(--line);
}
.tl__i:last-child::before { display: none; }
.tl__dot { position: absolute; left: 0; top: 9px; width: 7px; height: 7px;
           border-radius: 50%; background: var(--gold); }
.tl__t { flex: none; width: 64px; margin-left: var(--s-5);
         font: 500 var(--fs-data)/1.5 var(--font-text);
         font-variant-numeric: tabular-nums; }
.tl__x { flex: 1; line-height: 1.55; }
@media (min-width: 600px) { .tl__t { width: 84px; } }

/* ═══ «ЧТО ОТ ВАС ПОТРЕБУЕТСЯ» ════════════════════════════════════════ */
.req { max-width: 34em; }
.req li { font-size: 17px; line-height: 1.5; color: var(--ink-soft); }
.req li + li { margin-top: var(--s-3); }
.req li.is-key { color: var(--ink); font-weight: 500; }

/* ═══ АККОРДЕОН ═══════════════════════════════════════════════════════ */
.acc { border-top: var(--border); max-width: 34em; }
.acc__i { border-bottom: var(--border); }
.acc__i summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); min-height: var(--tap); padding: var(--s-3) 0;
  font: 500 16px/1.4 var(--font-text); cursor: pointer; list-style: none;
}
.acc__i summary::-webkit-details-marker { display: none; }
.acc__i summary::after { content: "+"; flex: none; font-size: 20px;
                         font-weight: 300; color: var(--ink-soft); }
.acc__i[open] summary::after { content: "−"; }
.acc__i > div { padding: 0 0 var(--s-5); line-height: var(--lh-body);
                max-width: 34em; }

/* Раскрывающееся описание инструмента внутри карточки. Базовый .acc__i
   рассчитан на список, идущий сплошной лентой: у него линейка снизу
   и своя ширина. Внутри карточки нужна линейка СВЕРХУ — она отделяет
   описание от плеера, — а ширину задаёт сама карточка. */
.inst__more {
  margin-top: var(--s-4);
  border-bottom: 0;
  border-top: var(--border);
}
.inst__more > div { max-width: none; font-size: var(--fs-small);
                    line-height: var(--lh-small); }
.inst__more > div p + p { margin-top: var(--s-3); }

/* ═══ ПАНЕЛЬ ФАКТОВ ═══════════════════════════════════════════════════ */
.facts { display: grid; grid-template-columns: 1fr 1fr;
         border: var(--border); border-radius: var(--radius); }
.facts__i { padding: var(--s-4); border-bottom: var(--border);
            border-right: var(--border); }
.facts__i:nth-child(2n) { border-right: 0; }
.facts__i:nth-last-child(-n+2) { border-bottom: 0; }
.facts__k { font-size: 13px; color: var(--ink-soft); letter-spacing: .02em; }
.facts__v { margin-top: var(--s-1); font: 500 var(--fs-data)/1.35
            var(--font-text); }
@media (min-width: 800px) {
  .facts { grid-template-columns: repeat(4, 1fr); }
  .facts__i { border-bottom: 0; }
  .facts__i:nth-child(2n) { border-right: var(--border); }
  .facts__i:last-child { border-right: 0; }
}

/* ═══ STICKY-ПАНЕЛЬ БРОНИ (страница события, мобильный) ═══════════════ */
.bookbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
  background: var(--paper); border-top: var(--border);
  padding: var(--s-3) var(--pad-x);
  padding-bottom: calc(var(--s-3) + env(safe-area-inset-bottom));
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  transform: translateY(110%); transition: transform 260ms var(--ease);
  /* visibility и inert: иначе кнопка «Забронировать» ловится табом
     за пределами экрана. */
  visibility: hidden;
}
.bookbar.is-on { transform: none; visibility: visible; }
.bookbar__price { font: 500 var(--fs-price)/1 var(--font-text);
                  font-variant-numeric: tabular-nums; }
@media (min-width: 900px) { .bookbar { display: none; } }

/* ═══ ПОЛОСА ПОВТОРНОГО ПРИЗЫВА ═══════════════════════════════════════ */
.cta { background: var(--paper-2); border-top: var(--border);
       border-bottom: var(--border); padding: var(--s-7) 0; }
.cta__h { font-family: var(--font-display); font-size: var(--fs-h2);
          line-height: 1.2; margin-bottom: var(--s-5); }
@media (min-width: 800px) {
  .cta__in { display: flex; align-items: center; justify-content: space-between;
             gap: var(--s-6); }
  .cta__h { margin-bottom: 0; }
}

/* ═══ ФУТЕР ═══════════════════════════════════════════════════════════ */
.ftr { background: var(--paper-2); border-top: var(--border);
       padding: var(--s-8) 0 var(--s-7); }
/* Две колонки по четыре пункта.
   На мобильном: контакты на всю ширину, под ними две колонки меню
   рядом. Восемь пунктов в один столбик — это лишние четыре экрана
   прокрутки в футере.
   Раньше разбивка 4+4 была, но КАЖДАЯ колонка сама была сеткой
   1fr 1fr — получалось четыре узких столбика по два пункта. */
.ftr__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-6); }
.ftr__grid > :first-child { grid-column: 1 / -1; }
.ftr__nav { display: grid; grid-template-columns: 1fr; gap: var(--s-2); }
/* Тап-зона 44px даётся flex-выравниванием и min-height, а НЕ
   line-height: 44px. С line-height длинный пункт «Что такое звуковая
   терапия» переносится на две строки и получает межстрочный интервал
   в 44px — строки расползаются. Здесь интервал нормальный, а высота
   всё равно не меньше 44px. */
.ftr__nav a { display: flex; align-items: center; min-height: 44px;
              padding: 6px 0; line-height: 1.35;
              font-size: 15px; text-decoration: none; }
.ftr__nav a:hover { text-decoration: underline;
                    text-decoration-color: var(--gold); }
.ftr__contacts a { display: flex; align-items: center; min-height: 44px;
                   line-height: 1.35; font-size: 15px; word-break: break-word; }
.ftr__contact-icon { flex: none; width: 17px; height: 17px;
                     margin-right: var(--s-2); color: var(--ink-soft); }
.ftr__legal { margin-top: var(--s-6); padding-top: var(--s-5);
              border-top: var(--border); font-size: 13px;
              color: var(--ink-soft); }
.ftr__legal > * + * { margin-top: var(--s-2); }
/* Единственная ссылка в реквизитах — «Политика конфиденциальности».
   Она давала 247×38 при обязательных 44 (§12.1), и так на всех
   девятнадцати страницах. Замечена только после того, как проверка
   поехала на НАСТОЯЩИХ 375px: до этого headless отдавал 500px,
   и на широком экране строка укладывалась иначе.

   Как и у .btn--quiet: визуальный размер не меняем, растёт только
   область нажатия — padding внутрь строки, отрицательный margin
   возвращает её на место. inline-flex нужен, чтобы padding вообще
   заработал на инлайновом элементе. */
.ftr__legal a {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 11px 0; margin: -11px 0;
}
@media (min-width: 900px) {
  /* На широком экране контакты становятся первой колонкой из трёх
     и на всю ширину больше не растягиваются. */
  .ftr__grid { grid-template-columns: 1.2fr 1fr 1fr; gap: var(--s-8); }
  .ftr__grid > :first-child { grid-column: auto; }
}

/* ── Узкие экраны: 320px ───────────────────────────────────────────────
   При --pad-x: 20px хедер не помещался: 40px полей + логотип +
   две кнопки языка по 44 + бургер 44 давали 338px при доступных 320,
   и бургер выходил за край. Прятать это через overflow-x: hidden
   на body — маскировка, а не решение: кнопка всё равно обрезана.
   Поэтому на узких экранах сжимаются поля и трекинг логотипа,
   а размеры тап-зон (44px) остаются нетронутыми.                      */
@media (max-width: 360px) {
  :root { --pad-x: 12px; }
  .logo__name { font-size: 12px; letter-spacing: .06em; }
  .logo { min-width: 0; }
  .logo__name, .logo__person { overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; display: block; }
  .hdr__in { gap: var(--s-2); }
}

/* Распроданная дата серии. Не ссылка и не «мёртвая серая кнопка»:
   это метка состояния. Зачёркивание, а не только цвет — состояние
   не должно опираться на один цвет. */
.ev__date--sold {
  color: var(--ink-soft);
  border-color: var(--line);
  text-decoration: line-through;
  text-decoration-color: var(--rose);
  cursor: default;
}
/* ПРОШЕДШИЙ вечер серии. Тоже не ссылка: до этой правки чип «5.09»
   вёл на Fienta к вечеру, который уже состоялся. Отличается от
   распроданного НАМЕРЕННО — это разные вещи: распродано значит
   «не досталось», прошло значит «уже было». Поэтому не зачёркивание,
   а приглушение и пунктирная рамка; состояние опирается не только
   на цвет, но и на начертание рамки. */
.ev__date--past {
  color: var(--ink-soft);
  border-style: dashed;
  border-color: var(--line);
  opacity: .75;
  cursor: default;
}

/* Малый остаток на дате: число рядом с датой, тем же золотом,
   что и строка «Последние 2 места» на карточке. */
.ev__date-n {
  margin-left: 4px;
  color: var(--gold-ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Главная фотография страницы события. Пропорции 1600×700 из
   спецификации: object-fit обрезает по центру, поэтому годится
   и вертикальный кадр, если Ирина загрузит свой. */
.ev__hero {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  border-radius: var(--radius);
}
@media (max-width: 700px) {
  /* На телефоне кадр 16:7 слишком узкий — почти полоса. Даём выше. */
  .ev__hero { aspect-ratio: 4 / 3; }
}
