/* ═══════════════════════════════════════════════════════════════════════
   ТРЕТЬЯ ВЕРСИЯ ВИТРИНЫ

   Замысел одной фразой: хром молчит, работа мастера говорит.

   Отсюда всё остальное. Фон — холодная бумага без единого фирменного
   цвета, потому что цвет на этом экране приносит фотография услуги, а не
   интерфейс. Единственный акцент бизнеса живёт СВЕТОМ — свечением
   карточки, подсветкой кромки, — а не заливкой: заливка спорит со
   снимком, свет его поддерживает.

   Подпись версии, то, по чему её узнают: страница меняет цвет по мере
   спуска (бумага → оттенок бизнеса → чернила), а числа никогда не
   появляются готовыми — они прикатываются по разрядам.

   ПРАВИЛО ДВИЖЕНИЯ. Анимируем только transform и opacity: всё прочее
   гоняет раскладку каждый кадр, и витрина начинает дёргаться ровно на
   тех телефонах, с которых её и открывают. Тень — это opacity
   псевдоэлемента, размер — scale, положение — translate.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Шрифты ───────────────────────────────────────────────────────────
   Onest переменный: один файл на все веса. Это не экономия байтов, это
   сам приём — в заголовке вес МЕНЯЕТСЯ ВНУТРИ предложения («Мы делаем
   ногти» тонким, «красиво» чёрным), а с обычным семейством это два
   файла и лишняя загрузка ради одного слова.

   Ubuntu — служебная роль: подписи, чипы, разряды. Мелкий капслок с
   разрядкой. Он намеренно другой по характеру: подпись не должна
   выглядеть уменьшенным заголовком. */
@font-face {
  font-family: "Onest";
  src: url("/static/fonts/onest-cyrillic.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0400-04FF, U+0500-052F, U+2DE0-2DFF, U+A640-A69F;
}
@font-face {
  font-family: "Onest";
  src: url("/static/fonts/onest-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2074,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "UbuntuV3";
  src: url("/static/fonts/ubuntu-cyrillic-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}

:root {
  /* Палитра. Шесть значений, каждое со своей работой.
     paper — холодная бумага первого экрана: не белая, потому что белое
             под фотографией читается как незагрузившийся фон;
     ink   — почти чёрный с синевой, текст и нижняя зона страницы;
     hush  — второстепенный текст: не серый «по умолчанию», а на два
             тона теплее фона, иначе подписи выглядят выключенными;
     accent — цвет бизнеса, приходит из оформления;
     line  — единственная линия в макете. */
  --paper: #EFEFF2;
  --ink: #101014;
  /* Цвет, до которого доезжает фон внизу страницы. Отдельно от --ink:
     тот означает цвет ТЕКСТА и на тёмной части сам становится светлым. */
  --deep-page: #101014;
  --hush: #5C5F72;
  --accent: #C9A35B;
  --card: #FFFFFF;
  --line: rgb(16 16 20 / .09);

  /* Фон страницы — переменная, а не константа: она едет по мере спуска.
     Держим её отдельно от --paper, чтобы «бумага» осталась опорным
     цветом для стёкол и кромок, даже когда фон уже ушёл в чернила. */
  --bg: var(--paper);

  /* Скругления. Крупная карточка и пилюля — два разных предмета, и
     радиус здесь несёт смысл, а не вкус. */
  --r-card: 28px;
  --r-tile: 20px;

  /* Время. .15s — отклик на касание, всё остальное длиннее ровно
     настолько, насколько движение обязано быть прочитано. */
  --t: .15s;
  --t-move: .42s;
  --ease: cubic-bezier(.2, 0, 0, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);

  --pad: 20px;
  --anchor-h: 76px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  /* ТИПОГРАФИКА ПО ИЗМЕРЕНИЯМ С САЙТОВ APPLE, А НЕ ПО ПАМЯТИ.

     Снято с apple.com и developer.apple.com:
       текст      — SF Pro Text, 17px, трекинг −0.374px (это −0.022em);
       заголовки  — SF Pro Display, вес 600, интерлиньяж 1.1, трекинг
                    около нуля;
       навигация  — 17px, вес 400, высота строки 44px.

     Что из этого пришлось поменять у себя: базовый кегль был 15–16px
     (мелко), заголовки шли весом 800 с трекингом −0.035em (слишком
     сжато и жирно), подписи — капслоком с разрядкой .18em, чего у Apple
     нет нигде. Вес 800 и сильный минусовой трекинг — это как раз то, что
     выдаёт «почти как у них».

     Из HIG: зона нажатия НЕ МЕНЬШЕ 44×44 pt, у каждой кнопки обязано быть
     состояние нажатия, и заметный стиль — ровно у одного действия в
     видимой части. */
  --lead: 17px;      /* базовый кегль текста */
  --track: -.022em;  /* трекинг текста */

  /* ШРИФТ.

     «Как у Apple» — это SF Pro, и подделать его трекингом нельзя:
     у Onest широкие геометрические формы и высокий рост строчных, у SF —
     узкие апертуры и сужающиеся окончания. Разница видна сразу, даже
     если её не называть.

     Поэтому на устройствах Apple берём НАСТОЯЩИЙ SF Pro: он там уже
     стоит, лицензирован и с кириллицей. Витрину открывают в основном с
     айфонов — там она и будет выглядеть родной, а не похожей.

     Onest остаётся для всего остального: он ближе к SF, чем Roboto, и
     уже лежит у нас самохостом, так что запасной путь не зависит от
     чужого домена. */
  font-family: -apple-system, "SF Pro Text", BlinkMacSystemFont,
               "Onest", "Segoe UI", system-ui, sans-serif;
  font-weight: 400;
  font-size: var(--lead);
  letter-spacing: var(--track);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}

body {
  /* Смена фона со скроллом — подпись версии. Меняем background-color, а
     не слои: это единственное свойство вне transform/opacity, которое мы
     себе позволяем, и оно того стоит — цвет под всей страницей нельзя
     подделать композитным слоем без гигантского перекрашиваемого div. */
  /* Переход по --bg: переменная меняется, а background-color, который её
     читает, доезжает плавно. */
  background-color: var(--bg);
  transition: background-color .6s linear;
  min-height: 100dvh;
  position: relative;
}

/* ФОН — НЕ ПЛОСКАЯ ЗАЛИВКА.

   На референсе за предметом стоит не цвет, а свет: мягкое пятно сверху
   слева и лёгкое затемнение по краям. Разница читается сразу — плоская
   заливка выглядит подложкой в редакторе, а не пространством.

   Делаем это отдельным слоем поверх фона и под содержимым: сам
   background-color при этом остаётся тем, что едет по скроллу, и одно не
   мешает другому. Слой неподвижен и ничего не перерисовывает. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 18% 0%,
      color-mix(in srgb, #fff 26%, transparent), transparent 62%),
    radial-gradient(90% 70% at 100% 100%,
      color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%),
    radial-gradient(140% 100% at 50% 50%,
      transparent 46%, color-mix(in srgb, #000 12%, transparent));
}
/* На тёмном конце светлое пятно превратилось бы в мутную кляксу: там
   свет идёт от акцента, а не от белого. */
body.deep::before {
  background:
    radial-gradient(120% 80% at 18% 0%,
      color-mix(in srgb, #fff 8%, transparent), transparent 60%),
    radial-gradient(90% 70% at 100% 100%,
      color-mix(in srgb, var(--accent) 20%, transparent), transparent 68%);
}

/* Пока не пришли данные — ничего не мигает. */
body.boot .screen { opacity: 0; }

img { max-width: 100%; display: block; }
button { font: inherit; color: inherit; border: none; background: none; cursor: pointer; }

/* Видимый фокус обязателен: по витрине ходят и с клавиатуры. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 6px; }

/* Атрибут hidden обязан прятать.

   Браузерное [hidden]{display:none} — правило нулевой специфичности, и
   ЛЮБОЙ display в классе его перебивает. Раздел, который мы «спрятали»,
   оставался на странице пустой дырой в три четверти экрана — ровно у
   того бизнеса, у которого нет фотографий, то есть у половины.

   Якорь внизу исключён намеренно: он прячется сдвигом вниз, а не
   исчезновением, и display:none оборвал бы ему движение на полпути. */
[hidden]:not(.anchor) { display: none !important; }

/* ── Экраны ─────────────────────────────────────────────────────────── */
.screen {
  display: none;
  min-height: 100dvh;
  padding-bottom: calc(var(--anchor-h) + env(safe-area-inset-bottom, 0px) + 16px);
}
.screen.on { display: block; }

/* ═══ ПЕРВЫЙ ЭКРАН ═══════════════════════════════════════════════════
   Фотография бизнеса во всю высоту. Всё, что поверх неё, обязано
   читаться на ЛЮБОМ снимке — светлом, тёмном, пёстром, — поэтому текст
   лежит на растяжке, а не надеется на удачный кадр. */
.hero {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--pad);
  padding-top: calc(env(safe-area-inset-top, 0px) + 24px);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
  overflow: hidden;
  isolation: isolate;
}

.hero-photo {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: var(--hero-url, none);
  background-size: cover;
  background-position: center;
  background-color: var(--ink);
  /* Медленный наезд на загрузке. Кадр «дышит», а не стоит картинкой —
     но масштаб крошечный: сильный зум на фотографии мастера читается
     как рекламный ролик, а не как салон. */
  transform: scale(1.06);
  animation: heroDrift 18s var(--ease-out) forwards;
}
@keyframes heroDrift { to { transform: scale(1); } }

.hero-veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgb(8 8 11) 0%, rgb(8 8 11 / .62) 34%, rgb(8 8 11 / .06) 74%);
}

.hero-body { color: #fff; }

.hero-eyebrow {
  margin: 0 0 14px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgb(255 255 255 / .72);
}

/* Заголовок. Вес меняется ВНУТРИ предложения — ради этого и взят
   переменный Onest. Размер один, характер разный. */
.hero-title {
  margin: 0;
  font-family: -apple-system, "SF Pro Display", BlinkMacSystemFont,
               "Onest", system-ui, sans-serif;
  font-size: clamp(36px, 9.8vw, 52px);
  line-height: 1.08;
  letter-spacing: -.019em;
  font-weight: 300;
  text-wrap: balance;
}
/* Жирное слово внутри строки — 700, а не 800: у Apple тяжелее
   Semibold/Bold заголовки не идут, и 800 читается как чужой шрифт. */
.hero-title b { font-weight: 700; }

.hero-sub {
  margin: 16px 0 0;
  max-width: 30ch;
  font-size: 17px;
  line-height: 1.47;
  color: rgb(255 255 255 / .84);
}

/* Слово в заголовке до появления. Держим в разметке, чтобы строки не
   перескакивали, когда слова доедут. */
.word { display: inline-block; }

.hero-foot {
  margin-top: 26px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.hero-hint {
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgb(255 255 255 / .5);
}

/* ── Кнопки ──────────────────────────────────────────────────────────
   Две весовые категории намеренно. Стеклянная предлагает, плотная —
   ведёт. Если обе выглядят одинаково важными, не выбирают ни одну. */
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 26px;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  transition: transform var(--t) var(--ease), opacity var(--t) var(--ease);
}
.pill:active { transform: scale(.96); }

/* ── Стекло ───────────────────────────────────────────────────────────
   Стекло у Apple держится на четырёх вещах разом, и без любой из них
   получается «полупрозрачный прямоугольник»:

   1. Размытие с ПОДЪЁМОМ насыщенности. Голый blur обесцвечивает то, что
      под ним, и стекло выглядит грязным; saturate возвращает цвет.
   2. Кромка толщиной в полпикселя, СВЕТЛЕЕ СВЕРХУ. Она изображает
      преломление на скруглении, и именно она читается как толщина.
   3. Блик — узкая светлая полоса по верхней трети.
   4. Тень снаружи. Без неё стекло лежит НА фоне, а не НАД ним.

   Заливка при этом почти никакая: чем её больше, тем меньше стекла. */
.glass-base {
  background: rgb(255 255 255 / .10);
  backdrop-filter: blur(24px) saturate(1.8);
  -webkit-backdrop-filter: blur(24px) saturate(1.8);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .55),
    inset 0 0 0 .5px rgb(255 255 255 / .22),
    inset 0 -.5px 0 rgb(255 255 255 / .10),
    0 1px 2px rgb(0 0 0 / .16),
    0 10px 28px -8px rgb(0 0 0 / .30);
}

/* Тихая ссылка первого экрана. Не пилюля: две одинаково тяжёлые кнопки
   рядом — выбор из двух главных, из которого не выбирают ни одну.

   Подчёркивания нет, есть шеврон: подчёркнутый текст поверх фотографии
   выглядит опечаткой, а стрелка читается как «дальше» на любом фоне. */
.hero-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 22px;
  padding: 10px 2px;
  color: rgb(255 255 255 / .9);
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -.015em;
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease);
}
.hero-link:active { opacity: .6; transform: translate3d(2px, 0, 0); }
.hero-link svg {
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .7;
}

.pill.glass {
  position: relative;
  align-self: flex-start;
  margin-top: 24px;
  color: #fff;
  overflow: hidden;
  background: rgb(255 255 255 / .10);
  backdrop-filter: blur(24px) saturate(1.8);
  -webkit-backdrop-filter: blur(24px) saturate(1.8);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .55),
    inset 0 0 0 .5px rgb(255 255 255 / .22),
    inset 0 -.5px 0 rgb(255 255 255 / .10),
    0 1px 2px rgb(0 0 0 / .16),
    0 10px 28px -8px rgb(0 0 0 / .30);
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* Блик. Отдельным слоем, а не градиентом в фоне: фон под стеклом должен
   оставаться прозрачным, иначе размытие нечего размывать. */
.pill.glass::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 52%;
  background: linear-gradient(to bottom,
    rgb(255 255 255 / .18), rgb(255 255 255 / 0));
  pointer-events: none;
}

/* Плотная кнопка — не стекло, и это намеренно: она ведёт, а не
   предлагает. Тень у неё двойная — короткая контактная и длинная
   мягкая, как у поднятого предмета, а не нарисованного пятна. */
.pill.solid {
  background: #fff;
  color: var(--ink);
  box-shadow:
    0 1px 2px rgb(0 0 0 / .16),
    0 10px 30px -6px rgb(0 0 0 / .28);
}
.pill.wide { width: 100%; }

/* Шов между первым экраном и страницей.

   Первый экран кончается почти чёрным, страница под ним светлая, и на
   стыке выходила прямая линия поперёк экрана — будто картинку обрезали.
   Полоса перехода начинается ровно тем цветом, которым кончается экран,
   и уходит в цвет страницы за высоту, которую глаз читает как расстояние,
   а не как границу.

   Высота в vh, а не в пикселях: на маленьком экране 200 пикселей — это
   четверть первого впечатления, на большом — незаметная полоска. */
.seam {
  height: 26vh;
  min-height: 130px;
  max-height: 240px;
  margin-top: -1px;
  background: linear-gradient(to bottom, rgb(8 8 11) 0%, var(--bg) 92%);
}

/* Вопрос — тонкая, но самостоятельная дверь. Он стоит после первого
   экрана и не спорит с записью за главную кнопку. */
.home-ask { padding: 0 var(--pad); margin-top: -74px; position: relative; z-index: 2; }
.home-ask-go {
  display:flex;align-items:center;justify-content:space-between;gap:14px;width:100%;
  min-height:70px;padding:13px 17px;border-radius:22px;text-align:left;color:#fff;
  background:rgb(20 20 24 / .72);backdrop-filter:blur(18px) saturate(1.5);
  -webkit-backdrop-filter:blur(18px) saturate(1.5);
  box-shadow:inset 0 .5px 0 rgb(255 255 255 / .24),0 12px 26px -15px rgb(0 0 0 / .55);
  transition:transform var(--t) var(--ease);
}
.home-ask-go:active { transform:scale(.985); }
.home-ask-go span { min-width:0; }
.home-ask-go b,.home-ask-go small { display:block; }
.home-ask-go b { font-size:16px;letter-spacing:-.017em; }
.home-ask-go small { margin-top:3px;font-size:13px;color:rgb(255 255 255 / .68); }
.home-ask-go svg { width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;opacity:.72; }

/* ═══ КОЛЛАЖ ═════════════════════════════════════════════════════════
   Фотографии услуг стоят узкой лентой и разлетаются облаком вокруг
   заголовка. Каждая ложится со своим поворотом и своим размером —
   ровная сетка здесь читалась бы как каталог, а нужен ворох работ. */
.collage {
  position: relative;
  min-height: 78vh;
  display: grid;
  place-items: center;
  padding: 64px var(--pad);
  overflow: hidden;
}

.collage-stage {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.shot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--w);
  aspect-ratio: var(--ar, 3 / 4);
  margin: calc(var(--w) / -2) 0 0 calc(var(--w) / -2);
  border-radius: 4px;
  background-size: cover;
  background-position: center;
  background-color: rgb(16 16 20 / .06);
  box-shadow: 0 10px 30px rgb(16 16 20 / .18);
  /* ЗДЕСЬ — КОНЕЧНОЕ ПОЛОЖЕНИЕ, А НЕ НАЧАЛЬНОЕ.
     Раньше снимок лежал тут невидимым, узкой лентой в центре, и разводил
     его по местам только разлёт. То есть «наши работы» существовали при
     условии, что анимация доехала до конца, — а она не доезжает, если
     браузер остановил кадры. Оставался пустой прямоугольник во весь
     экран.
     Начало задаёт скрипт, ему это и положено: положений столько же,
     сколько снимков, и классами их не описать. */
  /* Запасные значения обязательны: невычислимая переменная роняет
     ВСЁ свойство целиком, и снимки сложились бы стопкой в центре. */
  transform: translate3d(var(--x, 0px), var(--y, 0px), 0) rotate(var(--rot, 0deg));
  will-change: transform, opacity;
}

/* Один-три снимка. Не облако, а ровный ряд внахлёст: разлетаться там
   нечему, и попытка изобразить ворох из двух фотографий читается как
   поломка. Блок ниже — заголовку хватает места без подложки. */
.collage.few { min-height: 56vh; }
.collage.few .collage-say { margin-top: 132px; }
.collage.few .collage-say::before { opacity: 0; }

/* Заголовок обязан читаться, даже когда его накрыли снимками. Мягкое
   пятно фона под ним — не подложка-плашка: плашка вырезала бы дыру в
   ворохе работ, а пятно просто гасит то, что за буквами. */
.collage-say::before {
  content: "";
  position: absolute;
  inset: -28px -34px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--bg) 86%, transparent),
    color-mix(in srgb, var(--bg) 0%, transparent));
}

.collage-say {
  position: relative;
  text-align: center;
  /* Заголовок остаётся на месте, снимки ложатся и ПОВЕРХ него — это и
     есть приём: работа важнее подписи к ней. */
  z-index: 1;
  mix-blend-mode: normal;
  pointer-events: none;
}

.collage-kicker {
  margin: 0 0 10px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--hush);
}

.collage-title {
  margin: 0;
  font-family: -apple-system, "SF Pro Display", BlinkMacSystemFont,
               "Onest", system-ui, sans-serif;
  font-size: clamp(30px, 8.4vw, 44px);
  line-height: 1.08;
  letter-spacing: -.019em;
  font-weight: 600;
  text-wrap: balance;
}

/* ═══ ПОРТФОЛИО ТЕКСТОМ ══════════════════════════════════════════════
   Здесь был шаблон: мелкая подпись капслоком, стена текста и
   определительный список с волосяными линейками. Такое выдаёт любой
   генератор — владелец сказал прямо, что «выглядит как ИИ», и был прав.

   Осталось две вещи, каждая со своей работой:

   рассказ — крупным кеглем, без ярлыка «О НАС». Если текст не объясняет
   себя сам, ярлык его не спасёт, а место занимает;

   контакты — сгруппированным списком, где каждая строка НАЖИМАЕТСЯ:
   адрес открывает карты, телефон звонит. Адрес салона человек читает не
   из любопытства, а чтобы доехать. */
.story { padding: 64px var(--pad) 44px; }
.story-in { max-width: 34rem; margin: 0 auto; }

.story-text {
  margin: 0 0 30px;
  font-size: 22px;
  line-height: 1.42;
  letter-spacing: -.022em;
  white-space: pre-line;
  text-wrap: pretty;
}

.label {
  margin: 0 0 14px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--hush);
}

/* Сгруппированный список. Один блок с общим скруглением и разделителями
   ВНУТРИ — так строки читаются как один предмет, а не как три плитки. */
.facts {
  margin: 0;
  padding: 0;
  border-radius: var(--r-tile);
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--line);
  overflow: hidden;
}

/* Подпись СВЕРХУ, значение под ней во всю ширину.

   Разложить это в строку — подпись слева, значение справа — казалось
   аккуратнее, но на телефоне длинный адрес переносился по два слова, а
   номер рвался посередине: «+7 900 000-00-» и «00» на следующей строке.
   Номер, разорванный переносом, нельзя ни прочитать вслух, ни набрать
   глазами, а это единственное, ради чего он тут написан. */
.row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2px 14px;
  min-height: 60px;
  padding: 13px 16px;
  color: inherit;
  text-decoration: none;
  transition: transform var(--t) var(--ease);
}
/* Разделитель начинается там же, где текст: линия во всю ширину режет
   карточку пополам, а не разделяет строки. */
.row + .row { box-shadow: inset 0 1px 0 var(--line); }
.row.go:active { transform: scale(.985); }

.row-k {
  grid-column: 1;
  font-size: 13px;
  letter-spacing: -.005em;
  color: var(--hush);
}
.row-v {
  grid-column: 1;
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -.015em;
  line-height: 1.3;
  /* Слова целиком: разорванный номер телефона нельзя набрать глазами. */
  overflow-wrap: normal;
  word-break: keep-all;
  hyphens: none;
}
.row svg {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: 17px; height: 17px;
  fill: none; stroke: var(--hush); stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .55;
}

/* ═══ КАРТОЧКИ УСЛУГ ═════════════════════════════════════════════════
   Карточка — предмет со своим светом. Свечение берёт цвет из самой
   карточки (--hue), а не общий акцент: восемнадцать одинаково
   подсвеченных плиток — это уже не свет, а фон. */
.deck { padding: 48px var(--pad) 24px; }

.deck-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
  transition: transform var(--t) var(--ease);
}
.shot-big:active { transform: scale(.99); }
.deck-title {
  margin: 0;
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -.019em;
}

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

.card {
  position: relative;
  display: block;
  width: 100%;
  text-align: left;
  padding: 18px;
  min-height: 168px;
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--ink);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--t) var(--ease);
}
.card:active { transform: scale(.985); }

/* Фотография услуги — фон карточки. Без неё карточка не пустая: её
   заливает собственный цвет, и она остаётся полноценной, а не
   пунктирным местом под фото, которого владелец так и не загрузил. */
.card-photo {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-position: center;
  transform: scale(1.02);
  transition: transform .5s var(--ease-out);
}
.card:active .card-photo { transform: scale(1.05); }

.card-wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgb(8 8 11 / .82), rgb(8 8 11 / .12) 62%);
}

/* Свет наружу. Это псевдоэлемент с готовой тенью, и меняется у него
   только opacity — сама тень рисуется один раз. */
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -3;
  border-radius: inherit;
  box-shadow: 0 18px 44px -12px var(--hue, var(--accent));
  opacity: .55;
  pointer-events: none;
  transition: opacity var(--t-move) var(--ease);
}
.card.lit::after { opacity: .8; }

.card.on-photo { color: #fff; }

.card-top {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: auto;
}

/* Чип. Лежит ПОВЕРХ фотографии сверху — так в референсе, и так честнее:
   длительность и цена нужны до того, как человек рассмотрит снимок. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 11px;
  border-radius: 999px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  background: rgb(255 255 255 / .12);
  backdrop-filter: blur(20px) saturate(1.8);
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .5),
    inset 0 0 0 .5px rgb(255 255 255 / .2),
    0 1px 2px rgb(0 0 0 / .14);
  white-space: nowrap;
}

/* КНОПКА ОТМЕНЫ. Выглядит как метка рядом с записью, а не как действие
   первого плана: отменяют реже, чем смотрят, и красная кнопка в списке
   своих визитов пугала бы каждый раз, когда человек просто зашёл
   проверить время. Опасность появляется на втором нажатии, вместе с
   вопросом «точно отменить?». */
.chip.drop {
  appearance: none; border: 0; cursor: pointer; font: inherit;
  color: rgb(255 255 255 / .72);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .18);
  background: transparent;
  transition: color .16s var(--ease), box-shadow .16s var(--ease);
}
.chip.drop[data-sure="1"] {
  color: #ff9b8a;
  box-shadow: inset 0 0 0 1.5px #ff9b8a;
}
.chip.drop:disabled { opacity: .5; cursor: default; }
.card:not(.on-photo) .chip {
  background: rgb(16 16 20 / .05);
  box-shadow: inset 0 0 0 1px rgb(16 16 20 / .08);
  color: var(--hush);
}

.card-body {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
  margin-top: 76px;
}

.card-name {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.22;
}
.card-note {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.4;
  /* На цветной карточке подпись читают так же, как заголовок: в ней
     написано, что входит в услугу. 74% белого на насыщенном фоне уже
     на границе различимости. */
  opacity: .86;
}

/* ── Цена ────────────────────────────────────────────────────────────
   Разряды катятся вертикально. Каждый разряд — окно высотой в строку,
   внутри столбик 0–9, который переезжает трансформом.

   Почему не просто цифра: число, приехавшее на место, читается как
   результат — «вот столько», — а не как надпись. Ровно за этим и
   смотрят на ценник. */
.money {
  display: inline-flex;
  align-items: baseline;
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.money .cur { margin-left: 3px; font-size: .72em; font-weight: 600; opacity: .7; }
.money .sep { width: .26em; }

.roll {
  display: inline-block;
  overflow: hidden;
  height: 1em;
  line-height: 1;
  vertical-align: baseline;
}
.roll-col {
  display: block;
  transform: translateY(var(--pos, 0));
}
/* will-change ставится НА ВРЕМЯ проката, а не навсегда.
   Постоянная подсказка держит отдельный слой на каждый разряд: на карточке
   с ценой их четыре-пять, на экране — два десятка. Слой стоит памяти, и на
   телефоне два десятка лишних слоёв обходятся дороже, чем сам прокат,
   который длится полсекунды и случается раз на появление. */
.roll[data-live] .roll-col { will-change: transform; }
.roll-col span { display: block; height: 1em; line-height: 1; }

.money.old {
  font-size: 13px;
  font-weight: 500;
  opacity: .55;
  text-decoration: line-through;
  margin-right: 8px;
}

/* ═══ ВНУТРЕННИЕ ЭКРАНЫ ══════════════════════════════════════════════ */
.bar {
  position: sticky;
  top: 0;
  z-index: 5;
  padding: calc(env(safe-area-inset-top, 0px) + 10px) var(--pad) 10px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  padding: 0 12px 0 4px;
  margin-left: -4px;
  font-size: 15px;
  font-weight: 600;
  border-radius: 999px;
  transition: transform var(--t) var(--ease);
}
.back:active { transform: scale(.96); }
.back svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

.pane { padding: 8px var(--pad) 40px; }

.shot-big {
  position: relative;
  display: block;
  padding: 0;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-card);
  background-size: cover;
  background-position: center;
  background-color: rgb(16 16 20 / .06);
  margin-bottom: 22px;
}

.pane h1 {
  margin: 0 0 8px;
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -.019em;
  line-height: 1.1;
}
.pane .lead { margin: 0 0 22px; font-size: 17px; line-height: 1.5; color: var(--hush); }

/* ── Вопрос, маршрут и партнёры ───────────────────────────────────── */
.ask-pane { display:flex;flex-direction:column;min-height:calc(100dvh - 80px);padding-bottom:18px; }
.ask-thread { display:flex;flex:1;flex-direction:column;gap:10px;overflow:auto;padding:12px 0 18px; }
/* Приветствие стоит СВЕРХУ, а не по центру. Через margin:auto оно
   висело посреди экрана, оставляя провал и над собой, и под собой:
   человек видел пустоту, а не приглашение спросить. Сверху вниз — как
   читают, а место под ним честно означает «здесь будет разговор». */
.ask-welcome { margin:0; padding:4px 0 8px; }
.ask-welcome h1 { margin-bottom:10px; }
.ask-welcome p { margin:0;color:var(--hush);font-size:17px;line-height:1.5; }
.ask-suggestions { display:flex;flex-wrap:wrap;gap:8px;margin-top:22px; }
.ask-suggestions button,.ask-actions button {
  min-height:40px;padding:0 13px;border-radius:999px;background:var(--card);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--line);font:inherit;font-size:13.5px;font-weight:600;
}
.ask-msg { max-width:86%;padding:13px 15px;border-radius:20px;font-size:16px;line-height:1.42;white-space:pre-wrap; }
.ask-msg.you { align-self:flex-end;border-bottom-right-radius:6px;background:var(--ink);color:#fff; }
.ask-msg.answer { align-self:flex-start;border-bottom-left-radius:6px;background:var(--card);box-shadow:inset 0 0 0 1px var(--line); }
.ask-actions { display:flex;flex-wrap:wrap;gap:7px;margin-top:11px; }
.ask-actions button { min-height:36px;background:color-mix(in srgb,var(--accent) 16%,var(--card)); }
.ask-compose { display:flex;align-items:flex-end;gap:8px;padding:8px;border-radius:24px;background:var(--card);box-shadow:inset 0 0 0 1px var(--line),0 8px 24px rgb(0 0 0 / .08); }
.ask-compose textarea { flex:1;min-width:0;max-height:104px;resize:none;border:0;outline:0;padding:10px 8px;background:transparent;color:var(--ink);font:inherit;font-size:16px;line-height:1.35; }
.ask-compose textarea::placeholder { color:var(--hush); }
.ask-send { display:grid;place-items:center;width:42px;height:42px;flex:none;border-radius:999px;background:var(--ink);color:#fff; }
.ask-send svg { width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round; }
.ask-compose.busy { opacity:.58;pointer-events:none; }

.route-list,.partner-list { display:grid;gap:10px; }
.route-card,.partner-card { display:flex;align-items:center;gap:14px;min-height:78px;padding:14px 16px;border-radius:22px;background:var(--card);color:inherit;text-decoration:none;box-shadow:inset 0 0 0 1px var(--line);transition:transform var(--t) var(--ease); }
.route-card:active,.partner-card:active { transform:scale(.985); }
.route-card span,.partner-copy { display:grid;gap:4px;min-width:0;flex:1; }
.route-card b,.partner-copy b { font-size:16px;letter-spacing:-.017em; }
.route-card small,.partner-copy small { color:var(--hush);font-size:13.5px;line-height:1.35; }
.route-card svg,.partner-card svg { width:18px;height:18px;flex:none;fill:none;stroke:var(--hush);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;opacity:.62; }
.route-phone { display:inline-flex;margin-top:18px;color:inherit;font-size:16px;font-weight:600;text-underline-offset:4px; }
.partner-mark { display:grid;place-items:center;width:44px;height:44px;flex:none;border-radius:50%;background:color-mix(in srgb,var(--accent) 28%,var(--card));font-weight:700; }

.audio-demo { margin:0 0 20px;padding:13px 14px;border-radius:20px;background:var(--card);box-shadow:inset 0 0 0 1px var(--line); }
.audio-demo p { margin:0 0 8px;font-size:13px;color:var(--hush); }
.audio-demo audio { display:block;width:100%;height:38px; }

.rowline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.rowline:last-child { border-bottom: none; }

/* ── Дни и времена ──────────────────────────────────────────────────
   Полоска дней листается горизонтально: месяц целиком на экран не
   влезает, а листать неделю пальцем — то, чем и пользуются. */
.days {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 4px 0 14px;
  margin: 0 calc(var(--pad) * -1);
  padding-left: var(--pad);
  padding-right: var(--pad);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.days::-webkit-scrollbar { display: none; }

.day {
  flex: none;
  width: 62px;
  padding: 12px 0;
  min-height: 66px;
  border-radius: 18px;
  text-align: center;
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--line);
  scroll-snap-align: start;
  transition: transform var(--t) var(--ease), opacity var(--t) var(--ease);
}
.day:active { transform: scale(.95); }
.day.on { background: var(--ink); color: #fff; box-shadow: none; }
.day.off { opacity: .35; }
.day-w {
  display: block;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .65;
}
.day-n { display: block; margin-top: 5px; font-size: 19px; font-weight: 700; }

.slots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 8px;
  margin-top: 18px;
}
.slot {
  min-height: 48px;
  border-radius: 15px;
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--line);
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  transition: transform var(--t) var(--ease);
}
.slot:active { transform: scale(.94); }
.slot.on { background: var(--ink); color: #fff; box-shadow: none; }

/* ВРЕМЯ ПРОСТУПАЕТ СТРОКАМИ.
   Язык этой версии — рассказ: обложка, разделы, текст. Поэтому окна не
   всплывают и не разлетаются, а проступают по очереди сверху вниз, как
   появляются строки. Задержку ставит скрипт по порядковому номеру.

   Порог в 40мс на окно и потолок в 260мс — не украшение: при двадцати
   окнах равномерная лесенка растянулась бы на секунду, и человек, уже
   выбравший время, ждал бы, пока оно доедет. */
@keyframes v3-slot-in {
  from { opacity: 0; transform: translate3d(0, 9px, 0); }
  to   { opacity: 1; transform: none; }
}
.slots .slot {
  animation: v3-slot-in .34s var(--ease) both;
  animation-delay: var(--in, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .slots .slot { animation: none; }
}

/* ── Якорь ────────────────────────────────────────────────────────────
   Здесь был таб-бар из трёх вкладок. У витрины одна работа — привести к
   записи, — и три равноправные вкладки растаскивали внимание ровно там,
   где его надо собрать.

   ЦВЕТА ЯКОРЯ ПОСТОЯННЫ И НЕ СЛЕДУЮТ ЗА ФОНОМ СТРАНИЦЫ.

   Сначала он был собран на переменных (--card, --ink), а они едут по
   мере спуска: кнопка «1 запись» на глазах перекрашивалась из белой в
   тёмную, будто мигает. Постоянная вещь, которая всё время под пальцем,
   меняться не должна — по ней ориентируются, не глядя.

   Поэтому у якоря своя тёмная поверхность с фиксированными значениями.
   Она читается и на бумаге, и на чернилах, и ей всё равно, какой сейчас
   участок страницы. */
.anchor {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 10px;
  margin: 0 var(--pad) calc(env(safe-area-inset-bottom, 0px) + 12px);
  border-radius: 999px;
  background: rgb(18 18 22 / .82);
  /* Радиус — половина прежнего. Это единственное размытие, которое
     ВИСИТ НАД ДВИЖУЩИМСЯ содержимым: якорь закреплён, и браузер обязан
     заново прочитать и размыть фон под ним на каждом кадре прокрутки.
     Двадцать восемь пикселей радиуса и стекло, и цена; четырнадцать —
     то же стекло вдвое дешевле, разницу на глаз не поймать. */
  backdrop-filter: blur(14px) saturate(1.6);
  -webkit-backdrop-filter: blur(14px) saturate(1.6);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .2),
    inset 0 0 0 .5px rgb(255 255 255 / .09),
    0 2px 8px rgb(0 0 0 / .22),
    0 16px 40px -12px rgb(0 0 0 / .45);
  transition: transform var(--t-move) var(--ease-out), opacity var(--t-move) var(--ease);
}
.anchor[hidden] {
  display: flex;
  opacity: 0;
  transform: translate3d(0, 130%, 0);
  pointer-events: none;
}

.anchor-go {
  flex: 1;
  min-height: 48px;
  /* Белая — и остаётся белой: это главное действие страницы. */
  background: #fff;
  color: #101014;
  box-shadow: none;
}

/* Свои записи. Подписанная кнопка, а не кружок с цифрой: иконка
   календаря и «1» рядом — это ребус, который разгадывают вместо того,
   чтобы нажать. Ширина по содержимому: «1 запись» и «12 записей» разной
   длины, и фиксированная либо режет второе, либо оставляет дыру. */
.anchor-mine {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 48px;
  padding: 0 15px;
  border-radius: 999px;
  background: rgb(255 255 255 / .12);
  color: #fff;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -.01em;
  white-space: nowrap;
  box-shadow: inset 0 .5px 0 rgb(255 255 255 / .24);
  transition: transform var(--t) var(--ease);
}
.anchor-mine:active { transform: scale(.95); }
.anchor-mine svg {
  width: 17px; height: 17px;
  flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .72;
}

/* ── Лист разделов ────────────────────────────────────────────────────
   Всё, что не запись, живёт за одной дверью. Лист, а не экран: он не
   уводит со страницы, и закрывается тем же движением, которым открыт.

   Собственные цвета, как у якоря: лист всплывает над любым участком
   страницы, и подстраиваться под то, что под ним, ему незачем. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.sheet[hidden] { display: flex; pointer-events: none; }
.sheet[hidden] .sheet-veil { opacity: 0; }
.sheet[hidden] .sheet-card { transform: translate3d(0, 100%, 0); }

.sheet-veil {
  position: absolute;
  inset: 0;
  background: rgb(6 6 9 / .5);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 1;
  transition: opacity var(--t-move) var(--ease);
}

.sheet-card {
  position: relative;
  width: 100%;
  max-width: 34rem;
  max-height: 82dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  margin: 0 8px calc(env(safe-area-inset-bottom, 0px) + 8px);
  padding: 8px 8px 10px;
  border-radius: 30px;
  background: rgb(20 20 24 / .92);
  backdrop-filter: blur(30px) saturate(1.8);
  -webkit-backdrop-filter: blur(30px) saturate(1.8);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .18),
    0 -6px 40px rgb(0 0 0 / .4);
  color: #F2F2F5;
  transform: translate3d(0, 0, 0);
  transition: transform .34s var(--ease-out);
}

.sheet-grip {
  width: 38px; height: 4px;
  margin: 4px auto 12px;
  border-radius: 999px;
  background: rgb(255 255 255 / .26);
}

.sheet-list { display: grid; gap: 2px; }

.sheet-b {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 2px 12px;
  width: 100%;
  min-height: 60px;
  padding: 12px 16px;
  border-radius: 18px;
  text-align: left;
  color: inherit;
  text-decoration: none;
  background: rgb(255 255 255 / .05);
  transition: transform var(--t) var(--ease);
}
.sheet-b:active { transform: scale(.985); }
.sheet-b b { font-size: 16px; font-weight: 600; letter-spacing: -.015em; }
.sheet-b span {
  grid-column: 1;
  font-size: 13px;
  color: rgb(255 255 255 / .58);
}
.sheet-b svg {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .45;
}

.sheet-close {
  width: 100%;
  min-height: 52px;
  margin-top: 8px;
  border-radius: 18px;
  background: rgb(255 255 255 / .1);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  transition: transform var(--t) var(--ease);
}
.sheet-close:active { transform: scale(.985); }

/* ── Согласие перед первой записью ────────────────────────────────────
   Не отдельный экран, а лист поверх выбранного времени. Экран здесь
   означал бы, что человек ушёл со своего слота и должен вернуться —
   а слот тем временем может занять кто-то другой. */
.consent-text {
  margin: 0 0 6px;
  padding: 0 16px;
  font-size: 14.5px;
  line-height: 1.5;
  color: rgb(255 255 255 / .78);
}
.consent-text a { color: #fff; }

/* Поля в листе подтверждения. Крупные: их заполняют одной рукой, стоя,
   и промах по мелкому полю здесь стоит записи. */
.field { padding: 6px 4px; }
.field label {
  display: block;
  margin: 0 12px 6px;
  font-size: 12.5px;
  color: rgb(255 255 255 / .6);
}
.field input {
  width: 100%;
  min-height: 52px;
  padding: 0 16px;
  border: none;
  border-radius: 16px;
  background: rgb(255 255 255 / .08);
  color: #fff;
  font: inherit;
  font-size: 16px; /* меньше 16 — и iOS зумит страницу при фокусе */
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .1);
}
.field input::placeholder { color: rgb(255 255 255 / .34); }
.field input:focus {
  outline: none;
  box-shadow: inset 0 0 0 2px rgb(255 255 255 / .5);
}

.agree {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  margin: 10px 4px 4px;
  padding: 12px;
  border-radius: 16px;
  background: rgb(255 255 255 / .05);
  font-size: 14px;
  line-height: 1.4;
  cursor: pointer;
}
/* ГАЛОЧКА — СВОЯ, А НЕ СИСТЕМНАЯ. Браузерный квадрат приходит своим
   размером, своим радиусом и своим цветом; на тёмном листе это три чужих
   пятна посреди аккуратной формы. */
.agree input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.agree .box {
  flex: none; width: 22px; height: 22px; margin-top: 1px;
  border-radius: 7px; position: relative;
  box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / .38);
  transition: background .16s var(--ease), box-shadow .16s var(--ease);
}
.agree .box::after {
  content: ""; position: absolute; inset: 0;
  background: no-repeat center / 12px 9px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 9'%3E%3Cpath d='M1 4.4 4.3 7.8 11 1' fill='none' stroke='%23101014' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  opacity: 0; transform: scale(.7);
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.agree input:checked ~ .box {
  background: #fff; box-shadow: inset 0 0 0 1.5px #fff;
}
.agree input:checked ~ .box::after { opacity: 1; transform: none; }
/* Клавиатура должна видеть, где она стоит. */
.agree input:focus-visible ~ .box { box-shadow: inset 0 0 0 2px #fff; }
.agree a { color: #fff; }
.agree.soft { background: rgb(255 255 255 / .03); }
/* Согласие держит кнопку — отделяем его от удобств выше. */
.agree.need { margin-top: 14px; }

@media (prefers-reduced-motion: reduce) {
  .agree .box, .agree .box::after { transition: none; }
}

/* ЧТО ИМЕННО ПОДТВЕРЖДАЮТ. Здесь стояло одно время жирным: человек
   отдавал имя и телефон, не видя ни услуги, ни мастера, ни числа — всего
   того, что выбирал минуту назад. */
.ticket { padding: 4px 16px 14px; }
.ticket-what {
  margin: 0 0 4px;
  font-size: 13px;
  color: rgb(255 255 255 / .6);
}
.ticket-when {
  margin: 0;
  font-size: 26px;
  font-weight: 650;
  letter-spacing: -.02em;
  color: #fff;
}

/* Предоплата объясняется до выбора времени и повторяется после него.
   Это одна спокойная плашка, а не красное предупреждение: условие записи
   должно быть заметным, но не выглядеть как ошибка. */
.booking-note,
.booking-state {
  margin: 10px 16px 16px;
  padding: 12px 14px;
  border-radius: 16px;
  background: rgb(255 255 255 / .09);
  color: rgb(255 255 255 / .76);
  font-size: 14px;
  line-height: 1.42;
}
.booking-note b,
.booking-state b { color: #fff; }
.booking-state {
  display: grid;
  gap: 6px;
}
.booking-state.is-payment { background: rgb(255 255 255 / .13); }
.copy-payment {
  justify-self: start;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  font-weight: 650;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.copy-payment:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ШАГИ ПОДКЛЮЧЕНИЯ. Цифра своя у каждого: сплошной абзац «откройте,
   нажмите, поделитесь» читают по диагонали и делают из трёх действий
   одно. Здесь они строками — язык этой версии повествовательный. */
.steps {
  list-style: none;
  counter-reset: step;
  margin: 4px 16px 14px;
  padding: 0;
}
.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 26px 1fr;
  align-items: baseline;
  gap: 2px 12px;
  padding: 11px 0;
  border-bottom: 1px solid rgb(255 255 255 / .1);
}
.steps li::before {
  content: counter(step);
  grid-row: span 2;
  font-size: 19px;
  font-weight: 650;
  line-height: 1;
  color: rgb(255 255 255 / .42);
}
.steps b { font-size: 15px; font-weight: 600; color: #fff; }
.steps span { font-size: 13px; color: rgb(255 255 255 / .6); }

/* Необязательное — тихой ссылкой, а не полем во всю ширину: полем оно
   читается как ещё одно обязательное. */
.quietlink {
  appearance: none; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 13.5px; color: rgb(255 255 255 / .62);
  padding: 8px 16px; margin: 0;
  text-decoration: underline; text-underline-offset: 3px;
}
.quietlink[hidden] { display: none; }

/* Код подключения. Крупно и в разрядку: его переписывают руками, а
   слипшиеся знаки на телефоне не разобрать. */
.maxcode {
  margin: 4px 12px 10px;
  padding: 16px;
  border-radius: 16px;
  background: rgb(255 255 255 / .08);
  font-family: "UbuntuV3", ui-monospace, monospace;
  font-size: 30px;
  font-weight: 500;
  letter-spacing: .22em;
  text-align: center;
  color: #fff;
}
.agree.soft { background: rgb(255 255 255 / .03); }

/* Код подключения. Крупно и в разрядку: его переписывают руками, а
   слипшиеся знаки на телефоне не разобрать. */
.maxcode {
  margin: 4px 12px 10px;
  padding: 16px;
  border-radius: 16px;
  background: rgb(255 255 255 / .08);
  font-family: "UbuntuV3", ui-monospace, monospace;
  font-size: 30px;
  font-weight: 500;
  letter-spacing: .22em;
  text-align: center;
  color: #fff;
}

.sheet-b.go {
  margin-top: 10px;
  background: #fff;
  color: #101014;
}
.sheet-b.go svg { opacity: .5; }

/* ── Абонемент ────────────────────────────────────────────────────────
   Карточка, а не строка списка: у неё есть цена и действие, и то и
   другое должно быть видно, не открывая ничего. */
.pack {
  padding: 18px;
  margin-bottom: 12px;
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--line);
}
.pack-name { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -.025em; }
.pack-note { margin: 5px 0 0; font-size: 13.5px; color: var(--hush); }
.pack-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 16px;
}
.pack-go { min-height: 46px; padding: 0 20px; font-size: 14.5px; }

/* Абонементы стоят в разделе услуг: это те же услуги, только оптом, и
   сравнивают их с ценой одного визита. Отдельный раздел за кнопкой
   означал, что цену абонемента человек увидит, только если догадается
   пойти её искать. */
.packs { margin-top: 40px; }
.packs-h { margin: 0 0 4px; }
.packs-note { margin: 0 0 18px; font-size: 15px; color: var(--hush); }

/* Оценка звёздами: пять кнопок вместо выпадающего списка — одно
   движение вместо трёх. Размер по правилу 44 pt: промах по звезде
   ставит не ту оценку, и исправить её человек уже не сможет. */
.rate { display: flex; gap: 6px; padding: 4px 12px 10px; }
.rate button {
  width: 48px; height: 48px;
  border-radius: 14px;
  background: rgb(255 255 255 / .06);
  transition: transform var(--t) var(--ease), background-color var(--t) var(--ease);
}
.rate button::after {
  content: "";
  display: block;
  width: 24px; height: 24px;
  margin: auto;
  background: rgb(255 255 255 / .3);
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.rate button.on::after { background: #FFCC00; }
.rate button:active { transform: scale(.92); }

/* ── Мастера и отзывы ─────────────────────────────────────────────── */
.face {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 0;
  text-align: left;
  color: inherit;
  border-bottom: 1px solid var(--line);
  transition: transform var(--t) var(--ease);
}
.face:last-child { border-bottom: none; }
.face:active { transform: scale(.99); }
.face-pic {
  flex: none;
  width: 58px; height: 58px;
  border-radius: 999px;
  background-size: cover;
  background-position: center;
  background-color: color-mix(in srgb, var(--accent) 24%, transparent);
  display: grid;
  place-items: center;
  font-size: 20px;
  font-weight: 700;
  color: var(--accent);
}
.face-txt { flex: 1; min-width: 0; }
.face-txt b { display: block; font-size: 16.5px; font-weight: 600; letter-spacing: -.015em; }
.face-txt span { display: block; margin-top: 2px; font-size: 13.5px; color: var(--hush); }

.stars { display: inline-flex; gap: 2px; vertical-align: middle; }
.stars i {
  width: 13px; height: 13px;
  background: var(--accent);
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  opacity: .3;
}
.stars i.on { opacity: 1; }

.quote {
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}
.quote:last-child { border-bottom: none; }
.quote p { margin: 8px 0 0; font-size: 15.5px; line-height: 1.5; }
.quote-who {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--hush);
}

/* ── Фото во весь экран ───────────────────────────────────────────────
   Работу мастера смотрят, а не разглядывают в почтовой марке.
   Закрывается скроллом: человек с телефона тянет вверх или вниз раньше,
   чем ищет крестик. */
.shots {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgb(6 6 9 / .94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity .26s var(--ease);
}
.shots.in { opacity: 1; }

.shots-strip {
  height: 100%;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.shots-strip::-webkit-scrollbar { display: none; }
.shots-one {
  flex: none;
  width: 100%;
  height: 100%;
  scroll-snap-align: center;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

.shots-x {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  right: 12px;
  z-index: 2;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: rgb(255 255 255 / .14);
  backdrop-filter: blur(18px) saturate(1.6);
  -webkit-backdrop-filter: blur(18px) saturate(1.6);
  box-shadow: inset 0 .5px 0 rgb(255 255 255 / .4);
  color: #fff;
}
.shots-x svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round;
}

.shots-dots {
  position: absolute;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 22px);
  display: flex;
  gap: 7px;
  transform: translateX(-50%);
}
.shots-dots i {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgb(255 255 255 / .34);
  transition: background-color var(--t) var(--ease);
}
.shots-dots i.on { background: #fff; }

/* Пока фото открыто, страница под ним не едет: иначе закрыв просмотр,
   человек оказывается не там, где его открыл. */
body.no-scroll { overflow: hidden; }

/* Снимок на экране услуги — теперь кнопка. */
.shot-count {
  position: absolute;
  left: 14px;
  bottom: 14px;
  padding: 6px 11px;
  border-radius: 999px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: #fff;
  background: rgb(255 255 255 / .16);
  backdrop-filter: blur(16px) saturate(1.6);
  -webkit-backdrop-filter: blur(16px) saturate(1.6);
  box-shadow: inset 0 .5px 0 rgb(255 255 255 / .4);
}

/* ── Сообщение ──────────────────────────────────────────────────────── */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--anchor-h) + 18px);
  z-index: 40;
  max-width: calc(100vw - 40px);
  padding: 13px 20px;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  opacity: 0;
  transform: translate3d(-50%, 12px, 0);
  pointer-events: none;
  transition: opacity var(--t-move) var(--ease), transform var(--t-move) var(--ease-out);
}
.toast.on { opacity: 1; transform: translate3d(-50%, 0, 0); }

/* ── Заставка ───────────────────────────────────────────────────────── */
.veil {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  background: var(--paper);
  transition: opacity .34s var(--ease);
}
.veil.gone { opacity: 0; pointer-events: none; }
.veil-mark {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--line);
  border-top: 2px solid var(--ink);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Подвал ───────────────────────────────────────────────────────────
   Ссылка о персональных данных стоит здесь на ЛЮБОМ тарифе: это закон, а
   не оформление. Подпись «Работает на Nexo» — наоборот, на Business её
   нет. Разделены намеренно, чтобы одно нельзя было снять вместе с
   другим. */
.tail {
  padding: 44px var(--pad) 24px;
  text-align: center;
}
.tail-name {
  margin: 0 0 10px;
  font-family: "UbuntuV3", system-ui, sans-serif;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--hush);
}
.tail-legal {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--hush);
}
.tail-legal a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
/* Разделитель между пунктами — точка, а не запятая: пункты не
   перечисление, они просто соседи. */
.tail-legal i {
  display: inline-block;
  width: 3px; height: 3px;
  margin: 0 9px 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: .5;
}

.empty {
  padding: 44px 0;
  text-align: center;
  font-size: 15px;
  color: var(--hush);
}

/* ── Нижняя треть страницы ────────────────────────────────────────────
   Когда фон доехал до чернил, текст обязан стать светлым — иначе низ
   витрины просто исчезает. Меняем цвет, а не переворачиваем палитру:
   карточки со своим свечением остаются такими же, какими были. */
body.deep {
  /* НИЖНЯЯ ТРЕТЬ СТРАНИЦЫ.

     Здесь была настоящая поломка, а не оттенок: всё, что жёстко брало
     color: var(--ink), оставалось ТЁМНЫМ на тёмном. Подписи подсказок в
     «Задать вопрос» выглядели пустыми пилюлями, а поле ввода — пустой
     рамкой с курсором: человек печатал и не видел собственных букв.

     Поэтому --ink здесь тоже переопределяется. Он означает «цвет текста
     на фоне страницы», и на этой части страницы фон другой. Там, где
     нужен именно тёмный (заливка кнопки, текст на белой плашке), стоит
     отдельная переменная --deep-bg. */
  --ink: #F2F2F5;
  --deep-bg: #101014;
  --hush: #9295A6;
  --line: rgb(255 255 255 / .12);
  --card: #1A1B21;
  color: #F2F2F5;
}
body.deep .facts { background: var(--card); }
body.deep .day, body.deep .slot { color: #F2F2F5; }
body.deep .day.on, body.deep .slot.on { background: #fff; color: var(--deep-bg); }
body.deep .pill.solid { background: #fff; color: #101014; }
body.deep .card:not(.on-photo) { color: var(--deep-bg); }

/* ── Стиль поверхности карточек ───────────────────────────────────────
   Тот же выбор владельца, что и в остальных версиях. Меняется ПОВЕРХНОСТЬ
   и форма — свет, перекат цен и раскладка остаются: они и есть третья
   версия, а не украшение, которое можно отключить.

   «Переливы» (mesh) — состояние по умолчанию, описанное выше. */

/* Стекло: карточка прозрачная, цвет приходит свечением из-за края. */
.cards[data-surface="glass"] .card {
  background: rgb(255 255 255 / .08);
  backdrop-filter: blur(22px) saturate(1.7);
  -webkit-backdrop-filter: blur(22px) saturate(1.7);
  box-shadow:
    inset 0 .5px 0 rgb(255 255 255 / .4),
    inset 0 0 0 .5px rgb(255 255 255 / .18);
}
body.deep .cards[data-surface="glass"] .card { background: rgb(255 255 255 / .06); }

/* Плотный: ровная заливка без градиента — цвет один, без переливов. */
.cards[data-surface="solid"] .card { background-image: none !important; }

/* Контур: цвет уходит в линию, карточка становится лёгкой. */
.cards[data-surface="outline"] .card {
  background: transparent !important;
  background-image: none !important;
  color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--hue);
}
.cards[data-surface="outline"] .card::after { opacity: 0; }
.cards[data-surface="outline"] .card.on-photo:not(:has(.card-photo)) { color: var(--ink); }
body.deep .cards[data-surface="outline"] .card { color: #F2F2F5; }

/* Чистый: ни цвета, ни свечения — только фотография и текст. Для тех,
   кому весь этот свет мешает смотреть на работу. */
.cards[data-surface="clean"] .card {
  background-image: none !important;
  background: var(--card);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line);
}
.cards[data-surface="clean"] .card::after { opacity: 0; }
.cards[data-surface="clean"] .card.on-photo:not(:has(.card-photo)) { color: var(--ink); }

/* Скругление «как у Apple» — это не радиус побольше, а НЕПРЕРЫВНАЯ
   кривая: у обычного border-radius дуга стыкуется с прямой стороной
   изломом, и глаз его видит, даже не называя. Свойство новое, поэтому
   под @supports: где его нет, остаётся привычное скругление. */
@supports (corner-shape: squircle) {
  .card, .shot-big, .day, .slot, .facts, .pill, .chip, .anchor-mine, .toast {
    corner-shape: squircle;
  }
}

/* ── Появление при скролле ────────────────────────────────────────────

   ВИДНО ПО УМОЛЧАНИЮ. Раньше блок лежал здесь с прозрачностью 0, а
   показывала его анимация — то есть текст витрины существовал только
   при условии, что движение доехало до конца. Фоновая вкладка это
   условие ломает: браузер останавливает кадры, и человек возвращается
   к полупрозрачному заголовку. Теперь прячет отдельный класс, который
   ставит скрипт и только тому, что сейчас за пределами экрана: нет
   скрипта или встали кадры — страница просто видна.

   Сторона прихода приезжает переменной: вниз листаешь — блок
   поднимается снизу, вверх — опускается сверху. */
/* Подсказка браузеру — только тому, что действительно вот-вот поедет.
   Раньше она стояла на всех блоках сразу и навсегда: сорок с лишним
   постоянных слоёв на странице, которую открывают с телефона. */
.rise.armed { will-change: transform, opacity; }
.rise.armed {
  opacity: 0;
  transform: translate3d(0, var(--rise-from, 22px), 0);
}
/* Карточка вдобавок чуть меньше — предмет приезжает, а не проявляется.
   Раньше этот масштаб задавала анимация; переходу он даётся так же. */
.card.rise.armed {
  transform: translate3d(0, var(--rise-from, 22px), 0) scale(.955);
}
.card.rise.in {
  transition: opacity .52s var(--ease-out), transform .52s var(--ease-out);
}
/* Доехало. Ставится сторожем по таймеру — на случай, когда переходу
   некому идти: браузер останавливает кадры у фоновой вкладки, и блок,
   уже помеченный показанным, оставался прозрачным. Правило стоит ПОСЛЕ
   .rise.armed намеренно: вес у них одинаковый, и решает порядок. */
/* Второй селектор не для красоты: у .card.rise.in три класса, у
   .rise.settled — два, и отмена перехода ему проигрывала по весу.
   Переход оставался живым и замороженным, а карточка — прозрачной. */
.rise.settled,
.card.rise.settled {
  opacity: 1;
  transform: none;
  transition: none;
}
.rise.in {
  opacity: 1;
  transform: none;
  transition: opacity .5s var(--ease-out), transform .5s var(--ease-out);
}

/* ═══ ДОСТУПНОСТЬ ════════════════════════════════════════════════════
   Уменьшенное движение — не выключатель, а три уровня.

   Убираем целиком то, что двигает большие площади и намекает на
   собственное перемещение: наезд фотографии, разлёт коллажа,
   перекат разрядов. Ослабляем сдвиги до короткого проявления. Оставляем
   цвет, фокус и обратную связь на касание: без них интерфейс не
   успокаивается, а перестаёт отвечать. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .hero-photo { animation: none !important; transform: none !important; }
  .shot { transform: translate3d(var(--x), var(--y), 0) !important; opacity: 1 !important; }
  .roll-col { transition: none !important; }
  .rise { opacity: 1 !important; transform: none !important; }
  /* Третий уровень выживает: цвет и отклик на палец остаются. */
  /* Третий уровень выживает: цвет и отклик на палец остаются. */
  .pill, .card, .day, .slot, .back, .anchor-mine, .row.go {
    transition: opacity .12s linear, background-color .12s linear !important;
  }
  body { transition: background-color .2s linear !important; }
  .anchor { transition: opacity .12s linear !important; }
}

/* ── Широкий экран ──────────────────────────────────────────────────── */
@media (min-width: 720px) {
  :root { --pad: 32px; }
  .cards { grid-template-columns: repeat(2, 1fr); }
  .story-in, .deck-head, .pane { max-width: 44rem; margin-inline: auto; }
  .hero-body { max-width: 40rem; }
  .hero-foot { max-width: 26rem; margin-inline: auto; width: 100%; }
}
\n/* Подсказка вместо пустоты. Экран, на котором нечего читать и не на что
   нажать, человек закрывает — он решает, что дальше ничего нет. */
.hintline {
  margin: 22px 0 0;
  font-size: 16px;
  line-height: 1.45;
  color: var(--hush);
}
