/* ═══════════════════════════════════════════════════════════════════════
   ПЯТАЯ ВИТРИНА

   ОТКУДА ВЗЯТЫ ПРАВИЛА. Я открыл пять страниц Apple на телефоне 375×812
   и снял с них числа, а не впечатления:

   * ЗАГОЛОВОК 40px, вес 600, межстрочное 1.1 — и на AirPods, и на iPhone,
     и на Watch, и на MacBook. Не 130 и не 76: гигантская фраза на весь
     экран — приём других сайтов, не этих.
   * ДВИГАЮТ ТОЛЬКО `opacity` И `transform`. На странице iPhone 17 Pro
     124 элемента помечены `will-change: opacity, transform`, 42 —
     `transform`, 25 — `opacity`. Больше ничего. Всё остальное дёргает
     раскладку и роняет кадры на телефоне.
   * ГЛУБИНА — НЕ ТЕНЬ. Теней на всю страницу десять штук. Глубину дают
     два приёма: земля под секцией МЕНЯЕТСЯ (белый, #F5F5F7, #1D1D1F,
     чёрный — четыре-пять разных на страницу) и крупные скруглённые
     карточки (103 элемента с радиусом ≥16px). Экран перестаёт быть
     плоским, потому что следующий стоит на другом полу, а не потому,
     что под ним нарисована тень.

   ЧТО ЗДЕСЬ СВОЁ. Монохром и одна цветная вещь на экране — снимок работы
   салона. Ни одна другая версия витрины так не устроена: там цвет несёт
   оформление, здесь — только фотография мастера.

   ЦВЕТ ХОЗЯИНА. Заливки владельца меняют РОЛИ (--ink, --paper), а не
   раскладку: тема, которая перекраивает сетку, перестаёт быть темой.
   ═══════════════════════════════════════════════════════════════════════ */

@font-face{font-family:"NexoTight";font-weight:400;font-display:swap;
  src:url("/static/fonts/tight-cyr-400.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoTight";font-weight:400;font-display:swap;
  src:url("/static/fonts/tight-lat-400.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoTight";font-weight:500;font-display:swap;
  src:url("/static/fonts/tight-cyr-500.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoTight";font-weight:500;font-display:swap;
  src:url("/static/fonts/tight-lat-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoTight";font-weight:600;font-display:swap;
  src:url("/static/fonts/tight-cyr-600.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoTight";font-weight:600;font-display:swap;
  src:url("/static/fonts/tight-lat-600.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoTight";font-weight:700;font-display:swap;
  src:url("/static/fonts/tight-cyr-700.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoTight";font-weight:700;font-display:swap;
  src:url("/static/fonts/tight-lat-700.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoTight";font-weight:800;font-display:swap;
  src:url("/static/fonts/tight-cyr-800.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoTight";font-weight:800;font-display:swap;
  src:url("/static/fonts/tight-lat-800.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoMono";font-weight:400;font-display:swap;
  src:url("/static/fonts/mono-cyr-400.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoMono";font-weight:400;font-display:swap;
  src:url("/static/fonts/mono-lat-400.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoMono";font-weight:500;font-display:swap;
  src:url("/static/fonts/mono-cyr-500.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoMono";font-weight:500;font-display:swap;
  src:url("/static/fonts/mono-lat-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}

@font-face{font-family:"NexoSerif";font-weight:400;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-cyr-400.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoSerif";font-weight:400;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-lat-400.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoSerif";font-weight:500;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-cyr-500.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoSerif";font-weight:500;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-lat-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoSerif";font-weight:600;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-cyr-600.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoSerif";font-weight:600;font-style:normal;font-display:swap;
  src:url("/static/fonts/serif-lat-600.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoSerif";font-weight:400;font-style:italic;font-display:swap;
  src:url("/static/fonts/serifi-cyr-400.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoSerif";font-weight:400;font-style:italic;font-display:swap;
  src:url("/static/fonts/serifi-lat-400.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoSerif";font-weight:500;font-style:italic;font-display:swap;
  src:url("/static/fonts/serifi-cyr-500.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoSerif";font-weight:500;font-style:italic;font-display:swap;
  src:url("/static/fonts/serifi-lat-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}

/* ── ПАЛИТРА ──────────────────────────────────────────────────────────
   Вино, крем и золото. Три краски и ни одной больше: салон продаёт
   настроение, и нейтральная бумага с чёрным текстом здесь проигрывает
   густому цвету так же, как чёрно-белый снимок проигрывает цветному на
   витрине парфюмерии.

   Экраны чередуются: винный со снимком во весь кадр — кремовый с
   набором. Из-за этого чередования лента дышит; страница, целиком
   залитая одним цветом, глохнет через два экрана.                     */
@font-face{font-family:"NexoGolos";font-weight:400;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-cyr-400.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoGolos";font-weight:400;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-lat-400.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoGolos";font-weight:500;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-cyr-500.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoGolos";font-weight:500;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-lat-500.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoGolos";font-weight:600;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-cyr-600.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoGolos";font-weight:600;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-lat-600.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoGolos";font-weight:700;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-cyr-700.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoGolos";font-weight:700;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-lat-700.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}
@font-face{font-family:"NexoGolos";font-weight:800;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-cyr-800.woff2") format("woff2");
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:"NexoGolos";font-weight:800;font-style:normal;font-display:swap;
  src:url("/static/fonts/golos-lat-800.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+2000-206F,U+2122,U+2191,U+2193,U+2212}

:root{
  /* ── ЗЕМЛЯ. Четыре пола, между которыми ходят экраны. ─────────────── */
  --floor-1:#FFFFFF;
  --floor-2:#F4F4F6;
  --floor-3:#1C1C1E;
  --floor-4:#000000;

  --ink:#101012;
  --ink-soft:rgba(16,16,18,.62);
  --ink-faint:rgba(16,16,18,.38);
  --ink-hair:rgba(16,16,18,.12);

  --lit:#F7F7F9;
  --lit-soft:rgba(247,247,249,.66);
  --lit-faint:rgba(247,247,249,.4);
  --lit-hair:rgba(247,247,249,.16);

  /* Роли. Секция объявляет пол, а всё внутри знает только роли — одна
     кнопка работает и на белом, и на чёрном. */
  --floor:var(--floor-1);
  --on:var(--ink);
  --soft:var(--ink-soft);
  --faint:var(--ink-faint);
  --hair:var(--ink-hair);

  --face:"NexoTight",-apple-system,BlinkMacSystemFont,"SF Pro Text",
    "Helvetica Neue",Arial,sans-serif;
  --quiet:"NexoSerif",Georgia,"Times New Roman",serif;
  --mono:"NexoMono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* Скругления как у них: крупные, одинаковые, без разнобоя. */
  --r-card:28px;
  --r-pill:980px;
  --r-chip:14px;

  /* Времена — из их же переходов: 100–400 мс и одна кривая. */
  --tap:.15s;
  --move:.4s;
  --long:.6s;
  --ease:cubic-bezier(.4,0,.2,1);
}

/* Тёмный пол переворачивает роли целиком, а не по одному цвету:
   недокрашенная роль — это чёрный текст на чёрном, и находится он
   всегда у клиента, а не у нас. */
[data-floor="paper"]{--floor:var(--floor-2)}
[data-floor="dusk"],[data-floor="night"]{
  --on:var(--lit);--soft:var(--lit-soft);--faint:var(--lit-faint);
  --hair:var(--lit-hair);
}
/* Внутри тёмного прохода своя глубина: чернее всего там, где живёт
   спектр (услуги и мастера), а к выходу земля светлеет — свет уже
   начинает собираться обратно. */
[data-floor="dusk"]{--floor:var(--floor-3)}
[data-floor="night"]{--floor:var(--floor-4)}

*,*::before,*::after{box-sizing:border-box}
/* Держим обе: `clip` только на body не мешает документу считать свою
   ширину по вылезающему свету, и полоса прокрутки всё равно
   появляется. */
html{-webkit-text-size-adjust:100%;overflow-x:clip}
/* `clip`, А НЕ `hidden`.
   Свет на экране записи шире кадра нарочно — иначе у него появляется
   край. Держать его должен САМЫЙ ВЕРХНИЙ слой: `hidden` завёл бы здесь
   прокручиваемую область и сломал бы `position:sticky` внутри, а `clip`
   просто не даёт странице ехать вбок. */
body{margin:0;overflow-x:clip;background:var(--floor-1);color:var(--ink);
  font-family:var(--face);font-size:17px;line-height:1.47;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
img{max-width:100%;display:block}
[hidden]{display:none!important}
:focus-visible{outline:2px solid currentColor;outline-offset:3px;border-radius:4px}

/* ── ЭКРАН ────────────────────────────────────────────────────────────
   Каждый объявляет свой пол. Отступы по краям одни на всю витрину:
   разнобой в полях читается как съехавшая вёрстка быстрее, чем как
   замысел. */
.act{
  position:relative;background:var(--floor);color:var(--on);
  /* ВОЗДУХА БОЛЬШЕ, ЧЕМ КАЖЕТСЯ НУЖНЫМ.
     У Apple на телефоне 375 секция берёт 96px сверху и 96–196px снизу —
     замерено, не на глаз. У меня стояло 28, и экраны слипались в одну
     ленту: смена пола не читалась как новый экран, потому что между
     ними не было паузы. Пауза и есть половина глубины. */
  padding:clamp(88px,24vw,140px) clamp(20px,5.4vw,64px)
          clamp(88px,24vw,140px);
  transition:background-color var(--long) var(--ease);
}
/* `width:100%` здесь обязателен, а не для красоты. У элемента сетки с
   автополями (`margin:0 auto`) растягивание выключается, и ширину ему
   задаёт самое широкое содержимое — строка плиток по своей полной
   длине. Экран уезжал вбок ровно на её хвост. */
.wrap{width:100%;max-width:1120px;margin:0 auto;min-width:0}

/* ── ТИПОГРАФИКА ──────────────────────────────────────────────────────
   Кегли сняты с их страниц: 40/600/1.1 на телефоне, 48 на широком.
   Трекинг отрицательный и небольшой — крупный текст без него выглядит
   разреженным, а с большим начинает слипаться на кириллице. */
/* ── КОНТРАСТ, А НЕ ЛЕСЕНКА ───────────────────────────────────────────
   Между надписью и фразой должен быть ОБРЫВ, а не ступенька. У них 17 и
   40 — разница вдвое, и она делает фразу событием. У меня было 12 и 40,
   но между ними стояли ещё три размера, и лесенка съедала контраст:
   глаз шёл по ней плавно и нигде не останавливался.

   Надпись крупнее и спокойнее — не капслок вразрядку, а просто слово.
   Капслок кричит на каждом экране, а кричать должна фраза. */
.kick{margin:0 0 12px;font-size:16px;font-weight:500;letter-spacing:0;
  color:var(--faint)}
.say{margin:0;font-size:clamp(40px,11.4vw,64px);font-weight:600;
  line-height:1.05;letter-spacing:-.03em;text-wrap:balance}
.say b{font-weight:600}
.said{margin:14px 0 0;font-size:17px;line-height:1.47;color:var(--soft);
  max-width:34ch}
.small{font-size:13px;line-height:1.45;color:var(--faint)}

/* ── КНОПКИ ───────────────────────────────────────────────────────────
   Таблетка как у них: высота под палец, радиус во всю высоту. 44 пикселя
   — это не рекомендация, а размер подушечки пальца. */
.go{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:48px;padding:0 24px;border:0;border-radius:var(--r-pill);
  background:var(--on);color:var(--floor);
  font:inherit;font-size:16px;font-weight:500;cursor:pointer;
  text-decoration:none;
  transition:opacity var(--tap) var(--ease),transform var(--tap) var(--ease);
}
.go:hover{opacity:.86}
.go:active{transform:scale(.97)}
.go.ghost{background:transparent;color:var(--on);
  box-shadow:inset 0 0 0 1px var(--hair)}

.link{
  display:inline-flex;align-items:center;gap:6px;min-height:44px;
  color:var(--on);text-decoration:none;font-size:16px;
  /* Сброс обязателен: у <button> своя рамка и свой фон от браузера, и
     без него ссылка в подвале выглядела серым прямоугольником. */
  appearance:none;border:0;background:none;padding:0;cursor:pointer;
  font-family:inherit;font-weight:inherit;
  transition:opacity var(--tap) var(--ease);
}
.link:hover{opacity:.6}
.link::after{content:"›";font-size:1.15em;line-height:1;translate:0 -.04em}

/* ── ПОЯВЛЕНИЕ ────────────────────────────────────────────────────────
   Ровно то, что двигают они: прозрачность и сдвиг. Ни высоты, ни
   отступов — эти два роняют кадры на телефоне, потому что заставляют
   браузер пересчитывать раскладку каждый кадр.

   Стартовое состояние ставит СКРИПТ, а не эта таблица: если он не
   выполнится, текст должен остаться видимым. Экран, спрятанный CSS-ом в
   ожидании JS, который не пришёл, — это пустая страница. */
/* ── ПОЯВЛЕНИЕ ────────────────────────────────────────────────────────
   БЫСТРЕЕ, ЧЕМ БЫЛО. Стояло 600 мс и срабатывало, когда блок уже на
   12% зашёл в кадр: человек долистывал до пустого места и ждал. Теперь
   420 мс и старт до входа в кадр — движение успевает закончиться к
   тому моменту, когда взгляд доходит до текста.

   РАЗНОЕ, НО НЕ ЦИРК. Каждый экран входит по-своему, и это работает,
   только пока приёмов немного и все они тихие: сдвиг снизу, проявление
   с масштабом, лёгкий заход сбоку. Больше трёх — уже аттракцион, а не
   витрина. Ни один сдвиг не больше 24 пикселей и ни один масштаб не
   дальше 1.04: движение должно быть замечено краем глаза, а не
   рассмотрено. */
.rise{transition:opacity var(--move) var(--ease),transform var(--move) var(--ease)}
.rise[data-wait]{opacity:0;transform:translate3d(0,20px,0)}
/* Тёмные экраны — колода услуг и мастера. Здесь предмет проявляется и
   встаёт на место, а не подъезжает снизу: снизу подъезжают строки
   списка, а это не список. */
[data-floor="night"] .rise[data-wait],
[data-floor="dusk"] .rise[data-wait]{transform:scale(.985)}
/* Прайс — единственный экран-список, и он заходит сбоку: так видно, что
   строки пришли вместе, а не выросли каждая сама по себе. */
.price .rise[data-wait]{transform:translate3d(-14px,0,0)}
/* Медиа въезжает масштабом, а не сдвигом: снимок, который «подъезжает
   снизу», читается как элемент списка; снимок, который проявляется и
   встаёт на место, — как предмет. У них так же. */
.rise-in{transition:opacity var(--long) var(--ease),transform var(--long) var(--ease)}
.rise-in[data-wait]{opacity:0;transform:scale(.96)}
@media (prefers-reduced-motion:reduce){
  .rise-in[data-wait]{opacity:1;transform:none}
}

/* ОБОИ ЕДУТ МЕДЛЕННЕЕ СТРАНИЦЫ.
   Сдвиг маленький и только transform — композитор считает его на карте.
   Это единственное, что здесь привязано к прокрутке: всё остальное
   движение разовое, по появлению. */


@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;transition-duration:.01ms!important;
  }
  .rise[data-wait]{opacity:1;transform:none}
}

/* ── 1. ОБЛОЖКА ───────────────────────────────────────────────────────
   Слова сверху, снимок крупной карточкой под ними. Порядок телефонный и
   на широком экране не переставляется: слова первыми — правильно на
   любой ширине, потому что за фотографией человек и пришёл, но понять,
   куда он попал, должен раньше. */
/* Колонка одна и она ОГРАНИЧЕНА. У сетки без явной колонки ширина
   считается по самому широкому ребёнку — одна плитка с длинным словом
   утаскивала вбок весь экран. */
/* Содержимое стоит ПО ЦЕНТРУ, а не прижато к низу. Прижатое к низу
   оставляло сверху треть пустого экрана — не воздух, а дыра: воздух
   окружает предмет, а дыра висит над ним. */
.cover{min-height:100svh;overflow:hidden;
  display:grid;grid-template-columns:minmax(0,1fr);
  align-content:center;gap:clamp(20px,4.5vh,40px);
  /* У обложки свой ритм: сверху её поджимает шапка, снизу — строка
     фактов, и общий отступ секции здесь дал бы пустой экран. */
  padding-top:clamp(28px,7vh,56px);
  padding-bottom:clamp(20px,4vh,40px)}
/* ТЕКСТ ПО ЦЕНТРУ. У них герой устроен так: снимок во весь кадр, а
   надпись, заголовок и кнопки — по центру под ним. Слева выровненный
   заголовок это приём других сайтов, не этих. */
.cover .lead{display:grid;justify-items:center;text-align:center}

.cover .acts{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:center;gap:10px 18px;margin-top:22px}
/* Ряд ссылок обязан иметь промежутки: без них «Открыть на карте ›Telegram
   ›TikTok» читается одной строкой без пробелов, потому что стрелка —
   часть предыдущей ссылки, а не разделитель. */
.acts{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;
  margin-top:22px}

/* ── ОБОИ ВО ВЕСЬ ЭКРАН ───────────────────────────────────────────────
   Два слоя, каждый решает свою половину. РАЗМЫТАЯ КОПИЯ заполняет кадр
   целиком (`cover`): поэтому нет ни полей, ни полоски в пустоте, какой
   бы формы ни был снимок. РЕЗКАЯ лежит поверх неё в своей пропорции
   (`contain`): поэтому виден весь снимок, а не кусок чужой буквы во
   весь экран.

   Одним слоем это не решается: `contain` даёт полоску среди пустоты,
   `cover` режет плакат до неузнаваемости. Салоны грузят именно плакаты
   — со своим логотипом, шрифтом и ценой. */
.cover-wall{position:absolute;inset:0;overflow:hidden;z-index:0}
.cover-wall img{position:absolute;inset:0;width:100%;height:100%}
.cover-wall .blur{object-fit:cover;filter:blur(26px);transform:scale(1.12)}
.cover-wall .real{object-fit:contain;opacity:0;
  transition:opacity var(--long) var(--ease)}
.cover-wall .real.on{opacity:1}
/* ВУАЛЬ. Текст обязан читаться на ЛЮБОМ снимке — светлом, пёстром,
   тёмном. Проверять надо на худшем кадре салона, а не на удачном,
   поэтому это не дымка, а честный градиент: сильнее там, где лежат
   слова. */
.cover-wall::after{
  content:"";position:absolute;inset:0;
  background:
    radial-gradient(120% 78% at 50% 62%, rgb(0 0 0 / .74) 0%,
      rgb(0 0 0 / .5) 42%, rgb(0 0 0 / .28) 72%, transparent 100%),
    linear-gradient(180deg, rgb(0 0 0 / .42) 0%, rgb(0 0 0 / .1) 26%,
      rgb(0 0 0 / .42) 70%, rgb(0 0 0 / .74) 100%);
}
/* С обоями роли переворачиваются целиком, а не по одному цвету:
   недокрашенная роль — это тёмный текст на тёмном снимке, и находится он
   всегда у клиента, а не у нас. */
.cover[data-wall="on"]{
  --on:var(--lit);--soft:var(--lit-soft);--faint:var(--lit-faint);
  --hair:var(--lit-hair);
}
.cover[data-wall="on"] .lead{position:relative;z-index:1}
/* КНОПКА НА СНИМКЕ. Поле у неё всегда светлое (`--lit`) — она лежит на
   фотографии и обязана быть заметной. А текст брался «чернилами», и это
   держалось на молчаливом допущении, что чернила тёмные.
   У земли «Тушь» светлых полов нет вовсе, поэтому светлы ОБЕ краски:
   --ink и --lit там один и тот же #F5F5F7. Кнопка выходила белой с белой
   надписью — на живой витрине BARBERHØOD «Записаться» не читалось вовсе,
   пустая пилюля. Берём самый тёмный пол набора: он тёмный у всех восьми
   земель по построению, а не по совпадению. */
.cover[data-wall="on"] .go{background:var(--lit);color:var(--floor-4)}
.cover[data-wall="on"] .fact{
  background:rgb(255 255 255 / .16);color:var(--lit);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}
.cover[data-wall="on"] .fact span{color:var(--lit-faint)}

/* ФАКТЫ. Плитки под снимком: только те, что сервер действительно
   прислал. Пустых не рисуем — «0 мастеров» это не сдержанность. */
/* ЦЕНТРИРОВАНИЕ, КОТОРОЕ НЕ СЪЕДАЕТ КРАЯ.
   Обычный `center` во flex с прокруткой обрезает НАЧАЛО: когда строка
   шире контейнера, она вылезает в обе стороны, а прокрутить влево от
   нуля нельзя — первая плитка недостижима. `safe` переключается на
   выравнивание по началу ровно тогда, когда содержимое не помещается. */
.facts{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;
  margin:22px 0 0;padding:2px 0;width:100%}
.facts:empty{display:none}
/* ФАКТ, КОТОРЫЙ НЕЛЬЗЯ ПРОЧИТАТЬ, — НЕ ФАКТ.
   Четыре плитки в 375 пикселях ужимались до «ЗАВ… 11…» и «6 поз…».
   Сжимать до многоточия здесь нечего: смысл плитки в одном коротком
   слове и одном числе, и обрезанное слово не значит ничего. Поэтому они
   переносятся на вторую строку, а не жмутся.

   ПЛИТКИ ПОМЕЩАЮТСЯ, А НЕ ЕЗДЯТ.
   Три штуки по 126 пикселей плюс промежутки не влезали в 375, строка
   становилась прокручиваемой — и перехватывала косые движения пальца:
   человек листает вниз, а у него едет вбок. Пусть жмутся: три коротких
   факта читаются и в 100 пикселях. */
/* ДВЕ В РЯД НА ТЕЛЕФОНЕ, А НЕ ТРИ И ОДНА.
   Четыре плитки при свободном переносе ложатся 3+1, и одинокая
   четвёртая посреди пустой строки читается как забытая. Ровные пары
   выглядят решением, а не остатком. */
.fact{flex:1 1 calc(50% - 4px);max-width:calc(50% - 4px);min-width:0;
  display:grid;gap:2px;padding:11px 15px;border-radius:var(--r-chip);
  background:var(--floor-2);color:var(--ink);justify-items:center}
@media (min-width:620px){
  .fact{flex:0 1 auto;max-width:none}
}
.fact span,.fact b{white-space:nowrap}
.fact span{font-size:11px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-faint)}
.fact b{font-size:17px;font-weight:600;letter-spacing:-.015em;
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* ── 2. УСЛУГИ. КОЛОДА С РАДУГОЙ ──────────────────────────────────────
   Единственное, что пережило пересборку, и не случайно: услуга здесь не
   строка в списке, а предмет. Карточку бросают рукой, она наклоняется по
   броску и даёт по ведущему краю спектр — тем шире, чем быстрее бросок.

   Пол под ней чёрный: спектр — это свет, и на белом его почти не видно.
   Это не вкус, а физика того, что рисует шейдер. */
.svc{min-height:100svh;display:grid;grid-template-rows:auto minmax(0,1fr) auto;
  gap:clamp(16px,3.4vh,30px)}
/* СЦЕНЕ НУЖНА ВЫСОТА. Она стоит в строке `minmax(0,1fr)`, и когда под
   ней много текста — имя услуги в две строки, описание, прайс мастера —
   строка сжимается, а вместе с ней и холст: колода превращалась в
   марку. Нижняя граница держит кадр, верхняя не даёт ему съесть подпись. */
.svc .stage{position:relative;display:grid;place-items:center;
  height:min(48svh,440px)}
.svc canvas{width:100%;height:100%;display:block;touch-action:pan-y;cursor:grab}
.svc canvas:active{cursor:grabbing}

/* Лента имён. Текущее имя стоит по центру и оно единственное яркое:
   так видно, что листается именно она, а не экран. */
.rail{position:relative;height:44px;overflow:hidden;
  mask-image:linear-gradient(90deg,transparent,#000 16%,#000 84%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 16%,#000 84%,transparent)}
.rail .row{position:absolute;left:50%;top:0;display:flex;align-items:baseline;
  gap:28px;white-space:nowrap;will-change:transform}
.rail button{appearance:none;border:0;background:transparent;cursor:pointer;
  font:inherit;font-size:clamp(20px,5vw,30px);font-weight:500;
  letter-spacing:-.015em;color:var(--faint);padding:0;
  transition:color var(--move) var(--ease);
  /* ИМЯ ЧИТАЕТСЯ С НАЧАЛА, А НЕ С СЕРЕДИНЫ.
     У живого салона попадаются названия в 56 знаков. Даже на нижнем
     кегле такое не влезает, и растушёвка по краям ленты съедала ПЕРВЫЕ
     буквы: человек читал «е без последующего покрытия» и не понимал, о
     чём речь. Обрез с конца многоточием оставляет начало. */
  max-width:calc(100vw - 48px);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.rail button[aria-selected="true"]{color:var(--on)}

.line{display:flex;justify-content:space-between;align-items:flex-end;
  gap:18px;padding-bottom:env(safe-area-inset-bottom)}
.line .what{display:grid;gap:4px;min-width:0}
.line .what p{margin:0}
.sum{font-size:clamp(22px,5vw,30px);font-weight:600;letter-spacing:-.02em;
  white-space:nowrap;font-variant-numeric:tabular-nums}
@media (max-width:600px){
  .line{flex-direction:column;align-items:stretch;gap:10px}
}

main{padding-top:0}

/* ── МОИ ЗАПИСИ ───────────────────────────────────────────────────────
   Список карточек, а не строк: у записи есть что показать — время, услуга,
   мастер, деньги — и в строку это не складывается. */
.mine-list{display:grid;gap:12px;margin-top:22px}
/* Запись — строка с линейкой, а не карточка: карточками устроена первая
   версия, и вторая такая же читалась бы как она. */
.visit{padding:18px 0;border-top:1px solid var(--hair);display:grid;gap:6px}
.mine-list > .visit:first-child{border-top:0}
.visit b{font-size:19px;font-weight:600;letter-spacing:-.02em}
.visit p{margin:0;font-size:15px;color:var(--soft)}
.visit .row{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}

/* ── УСЛУГИ: подпись под колодой ──────────────────────────────────── */
.line-go{display:flex;align-items:center;gap:14px;flex-shrink:0}
.ladder{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.ladder button{appearance:none;border:0;cursor:pointer;font:inherit;
  font-size:13px;padding:7px 12px;border-radius:var(--r-pill);
  background:color-mix(in srgb, var(--on) 12%, transparent);color:var(--on)}
.ladder button[aria-pressed="true"]{background:var(--on);color:var(--floor)}

/* ── МАСТЕРА ──────────────────────────────────────────────────────────
   Лента вбок: мастеров редко больше пяти, и сетка из двух ради трёх
   карточек выглядит недоделанной. */
.crew{min-height:100svh;display:grid;
  grid-template-rows:auto minmax(0,1fr) auto;gap:clamp(16px,3.4vh,30px)}
/* .crew-intro больше не существует: описание студии стояло под
   мастером и в «О нас» одновременно, читая одно и то же поле.
   Правило убрано вместе с элементом, чтобы следующий, кто станет
   искать его в разметке, не решил, что тот просто спрятан. */
.crew .stage{position:relative;display:grid;place-items:center;
  height:min(48svh,440px)}
.crew canvas{width:100%;height:100%;display:block;touch-action:pan-y;cursor:grab;
  min-height:0;min-width:0}
.crew canvas:active{cursor:grabbing}
/* СВОИ ЦЕНЫ МАСТЕРА. У салона с ценами по мастерам это главный вопрос
   выбора: без них человек открывает одного, возвращается, открывает
   второго. */
/* Список цен прокручивается внутри себя, а не растягивает экран: у
   мастера бывает пятнадцать позиций, и тогда всё под ним уезжает вниз. */
.crew-prices{display:grid;gap:0;margin-top:14px;max-height:34vh;
  overflow-y:auto;scrollbar-width:none}
.crew-prices::-webkit-scrollbar{display:none}
.crew-prices > div{display:flex;align-items:baseline;gap:10px;padding:10px 0;
  border-top:1px solid var(--hair);font-size:15px}
.crew-prices > div:first-child{border-top:0}
.crew-prices .n{flex:1 1 auto;min-width:0}
.crew-prices .v{flex:0 0 auto;font-weight:600;font-variant-numeric:tabular-nums}
/* Хвост обрезанного списка. Не строка прайса — сноска о ней: тот же
   ряд, но приглушённый и без цены справа. */
.crew-prices .more .n{opacity:.52;font-size:.92em}
.crew-rail{display:flex;justify-content:safe center;gap:12px;
  overflow-x:auto;scroll-snap-type:x mandatory;
  padding:22px clamp(20px,5.4vw,64px);scrollbar-width:none}
.crew-rail::-webkit-scrollbar{display:none}
/* НЕ КАРТОЧКА. Коробка со скруглением и заливкой — приём первой версии,
   и повторять его здесь значит быть на неё похожим. У мастера снимок во
   всю ширину колонки, подпись под ним на голом полу. */
.face{flex:0 0 74%;max-width:320px;scroll-snap-align:center;
  display:grid;grid-template-rows:auto 1fr;gap:12px}
@media (min-width:760px){.face{flex:0 0 300px}}
.face img{width:100%;aspect-ratio:4/5;object-fit:cover;background:var(--floor-1);
  border-radius:var(--r-chip)}
.face .in{display:grid;gap:4px;align-content:start}
.face b{font-size:19px;font-weight:600;letter-spacing:-.02em}
.face p{margin:0;font-size:14px;color:var(--soft)}
.face .go{margin-top:10px;justify-self:start}

/* На телефоне услуги и мастера должны читаться одной главой, а не двумя
   независимыми полноэкранными заставками. Оставляем воздух вокруг колод,
   но убираем двойной отступ в стыке: после цены сразу начинается знакомство
   с командой. */
@media (max-width:600px){
  .svc{min-height:86svh;padding-bottom:clamp(40px,11vw,56px)}
  .svc + .crew{min-height:92svh;padding-top:clamp(44px,12vw,60px)}
}

/* ── АКЦИИ И АБОНЕМЕНТЫ ───────────────────────────────────────────── */
.deal-grid{display:grid;gap:12px;margin-top:22px}
@media (min-width:760px){.deal-grid{grid-template-columns:1fr 1fr}}
.deal{padding:20px 0;border-top:1px solid var(--hair);
  display:grid;gap:6px;align-content:start}
.deal-grid > .deal:first-child{border-top:0}
@media (min-width:760px){.deal-grid > .deal:nth-child(2){border-top:0}}
.deal b{font-size:19px;font-weight:600;letter-spacing:-.02em}
.deal p{margin:0;font-size:15px;color:var(--soft)}
.deal .go{margin-top:10px;justify-self:start}

/* ── ЦЕНЫ ─────────────────────────────────────────────────────────────
   Рубрика — заголовок, позиции под ней строками с отточием. Так прайс
   читают на бумаге, и так его ищут глазами. */
.price-list{margin-top:22px;display:grid;gap:26px}
.price-cat > b{display:block;font-size:12px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--faint);margin-bottom:10px}
/* СТРОКА ПРАЙСА — ЭТО И ЕСТЬ ВЫБОР. Отдельный список услуг в записи был
   третьей копией одного и того же; здесь выбирают там, где смотрят. */
.price-row{display:flex;align-items:baseline;gap:10px;padding:14px 2px;
  border-top:1px solid var(--hair);width:100%;text-align:left;
  appearance:none;background:transparent;border-left:0;border-right:0;
  border-bottom:0;color:inherit;font:inherit;cursor:pointer;min-height:52px;
  transition:opacity var(--tap) var(--ease)}
.price-row:hover{opacity:.62}
.price-row[aria-pressed="true"]{font-weight:600}
.price-row[aria-pressed="true"] .n::before{content:"✓ ";font-weight:600}
.price-cat > .price-row:first-of-type{border-top:0}
.price-row .n{flex:1 1 auto;min-width:0;font-size:16px}
.price-row .n span{display:block;font-size:13px;color:var(--faint)}
.price-row .v{flex:0 0 auto;font-size:16px;font-weight:600;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.price-row .old{margin-right:6px;font-weight:400;color:var(--faint);
  text-decoration:line-through}

/* ── ОТЗЫВЫ ───────────────────────────────────────────────────────── */
.word-rail{display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x proximity;
  margin:22px calc(-1 * clamp(20px,5.4vw,64px)) 0;
  padding:0 clamp(20px,5.4vw,64px);scrollbar-width:none}
.word-rail::-webkit-scrollbar{display:none}
/* Отзыв — просто набранный текст в колонке: кавычки и подпись делают его
   отзывом лучше, чем рамка вокруг. */
.word{flex:0 0 78%;max-width:360px;scroll-snap-align:start;
  display:grid;gap:10px;align-content:start;
  padding-left:16px;border-left:2px solid color-mix(in srgb, var(--on) 22%, transparent)}
@media (min-width:760px){.word{flex:0 0 320px}}
.word q{font-size:16px;line-height:1.5;quotes:"«" "»"}
.word cite{font-style:normal;font-size:13px;color:var(--faint)}

/* ── О СТУДИИ ─────────────────────────────────────────────────────── */
.facts-list{margin:22px 0 0;display:grid;gap:0}
.facts-list > div{display:flex;align-items:baseline;gap:14px;padding:13px 0;
  border-top:1px solid var(--hair)}
.facts-list > div:first-child{border-top:0}
.facts-list dt{flex:0 0 34%;max-width:150px;font-size:13px;color:var(--faint)}
.facts-list dd{margin:0;flex:1 1 auto;min-width:0;font-size:16px;
  overflow-wrap:anywhere}

/* ── ПОДВАЛ ───────────────────────────────────────────────────────── */
.tail{background:var(--floor-2);color:var(--ink);
  padding:clamp(28px,7vw,56px) clamp(20px,5.4vw,64px)
          calc(clamp(28px,7vw,56px) + env(safe-area-inset-bottom))}
.tail .wrap{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px}
.tail .legal{flex:1 1 100%;margin:8px 0 0;font-size:12.5px;line-height:1.6;
  color:var(--ink-faint)}
.tail .legal a{color:inherit}

/* «Я у вас уже был» — отдельный блок под списком дней, а не ещё одна
   строка в нём: это не выбор дня, а просьба показать другие дни.
   Отделён линией сверху, чтобы не слипался с кнопками дат. */
.mine{display:grid;gap:10px;margin-top:18px;padding-top:16px;
  border-top:1px solid var(--line,rgb(128 128 128 / .22))}
.mine .mute{opacity:.75}
.fld{display:grid;gap:6px}
/* ПОЛЯ ИДУТ РОЛЯМИ, А НЕ ЦВЕТАМИ.
   Здесь стояли `--ink` и `--floor-1` — светлая половина набора. На
   тёмном полу это давало белый прямоугольник посреди чёрного экрана и
   подпись тёмным по тёмному, то есть невидимую. Роль знает, на чём она
   лежит; жёсткий цвет не знает. */
.fld span{font-size:13px;color:var(--faint)}
.fld input,.fld textarea{
  appearance:none;width:100%;font:inherit;font-size:16px;
  padding:14px 15px;border-radius:var(--r-chip);
  border:1px solid var(--hair);color:var(--on);
  background:color-mix(in srgb, var(--on) 7%, transparent);
}
.fld input::placeholder,.fld textarea::placeholder{color:var(--faint);opacity:1}
.fld input:focus,.fld textarea:focus{outline:none;border-color:var(--on)}
.tick{display:flex;align-items:flex-start;gap:10px;font-size:14px;
  line-height:1.45;color:var(--soft);cursor:pointer}



/* ── УСЛУГИ: ПОДПИСЬ И СТРЕЛКИ ────────────────────────────────────────
   Имя услуги стоит на месте и целиком, а не бежит лентой вбок: читать
   едущий текст неудобно, а живые названия в 56 знаков в такую ленту не
   помещались вовсе и резались с начала. */
/* ── ПОДПИСЬ В ДВА ТОНА ───────────────────────────────────────────────
   У них подпись под снимком — один абзац: имя жирным, продолжение
   серым. Не две строки друг под другом, а одна фраза, в которой видно
   главное. Разнесённые по строкам имя и описание читаются как поля
   карточки товара; слитые — как предложение. */
.svc .name{margin:6px 0 0;font-size:clamp(20px,5.2vw,26px);font-weight:600;
  line-height:1.3;letter-spacing:-.02em;text-wrap:balance}
.svc .name em{font-style:normal;font-weight:400;color:var(--soft)}
.svc .what{display:grid;gap:2px;min-width:0}
/* Круглые стрелки под лентой — их приём: листать пальцем умеют не все, а
   видеть, что здесь листается, должны все. */
/* ── КАПСУЛА С ТОЧКАМИ ────────────────────────────────────────────────
   Их приём: круглые варианты лежат в светлой пилюле, выбранный обведён
   кольцом, а его имя стоит НАД капсулой по центру. Так сделан выбор
   цвета в AirPods Max и переключатель в iPad Pro.

   Голые точки в ряд, как было у меня, читаются как индикатор — «где я
   в списке». Капсула читается как ОРГАН УПРАВЛЕНИЯ: по ней видно, что
   можно нажать, и палец сам туда идёт. */
.arrows{display:flex;align-items:center;justify-content:space-between;
  gap:10px;margin-top:18px}
.pips{
  display:flex;align-items:center;gap:6px;min-width:0;flex-wrap:wrap;
  padding:7px 10px;border-radius:var(--r-pill);
  background:color-mix(in srgb, var(--on) 9%, transparent);
}
.pip{appearance:none;border:0;padding:0;cursor:pointer;
  width:10px;height:10px;border-radius:50%;
  background:color-mix(in srgb, var(--on) 30%, transparent);
  box-shadow:0 0 0 0 var(--on);
  transition:background-color var(--tap) var(--ease),
    box-shadow var(--tap) var(--ease);
}
.pip[aria-selected="true"]{
  background:var(--on);box-shadow:0 0 0 3px color-mix(in srgb, var(--on) 26%, transparent);
}
.arw{
  appearance:none;border:0;cursor:pointer;flex:0 0 auto;
  width:44px;height:44px;border-radius:50%;font:inherit;font-size:20px;
  line-height:1;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb, var(--on) 12%, transparent);color:var(--on);
  transition:background-color var(--tap) var(--ease),transform var(--tap) var(--ease);
}
.arw:hover{background:color-mix(in srgb, var(--on) 20%, transparent)}
.arw:active{transform:scale(.94)}

/* ── ЗАПИСЬ ЭКРАНОМ, А НЕ ЛИСТОМ СНИЗУ ────────────────────────────────
   Шаги стоят друг под другом и появляются по мере выбора: ответил —
   следующий блок возник ниже, и страница сама к нему подъехала. Человек
   не переключает шаги, он листает; так устроены страницы Apple, и так же
   устроен телефон, на котором это открывают. */
.step{margin-top:clamp(30px,8vw,52px)}
.step-n{margin:0 0 12px;font-size:12px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--faint)}
.opts{display:grid;gap:8px}

/* ── ВЫБОР ────────────────────────────────────────────────────────────
   Эти правила однажды уже пропали: я вырезал их вместе со стилями листа,
   и выбор превратился в голые кнопки браузера — прямоугольники с рамкой,
   а имя мастера, должность и цена слиплись в одну строку без пробелов.
   Поэтому они стоят здесь, рядом со своей сеткой, а не в чужом разделе.

   Форма — таблетка, как у всех кнопок этой витрины: острые углы среди
   овалов читаются как чужой элемент. */
.opt{
  appearance:none;border:0;cursor:pointer;font:inherit;text-align:left;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  width:100%;min-height:60px;padding:14px 20px;
  border-radius:var(--r-pill);
  background:color-mix(in srgb, var(--on) 7%, transparent);
  color:var(--on);
  transition:background-color var(--tap) var(--ease),
             transform var(--tap) var(--ease);
}
.opt:hover{background:color-mix(in srgb, var(--on) 13%, transparent)}
.opt:active{transform:scale(.985)}
.opt[aria-pressed="true"]{background:var(--on);color:var(--floor)}
.opt .n{min-width:0;overflow-wrap:anywhere;line-height:1.3}
/* Подпись под названием — своей строкой. Без этого «Али», «Старший
   барбер» и «1 200 ₽» вставали в одну строку без единого пробела. */
.opt .n small{display:block;font-size:13px;opacity:.66;margin-top:3px}
.opt .v{flex:0 0 auto;font-variant-numeric:tabular-nums;opacity:.86;
  white-space:nowrap}
.opts.days{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.opts.times{grid-template-columns:repeat(auto-fill,minmax(92px,1fr))}
.opts.days .opt,.opts.times .opt{justify-content:center;text-align:center;
  padding:14px 10px;min-height:56px;font-variant-numeric:tabular-nums}

/* ── СОГЛАСИЕ ─────────────────────────────────────────────────────────
   Своя галочка, а не браузерная: системная синяя — единственное цветное
   пятно на всей витрине, и она кричит громче кнопки записи. */
.tick input{
  appearance:none;flex:0 0 auto;width:24px;height:24px;margin:0;
  border-radius:8px;cursor:pointer;
  border:1.5px solid color-mix(in srgb, var(--on) 34%, transparent);
  background:transparent;
  transition:background-color var(--tap) var(--ease),
             border-color var(--tap) var(--ease);
}
.tick input:checked{background:var(--on);border-color:var(--on)}
.tick input:checked::after{
  content:"";display:block;width:100%;height:100%;
  background:var(--floor);
  -webkit-mask:no-repeat center/13px 10px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 10'%3E%3Cpath d='M1 5l3.6 3.6L12 1.2' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  mask:no-repeat center/13px 10px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 10'%3E%3Cpath d='M1 5l3.6 3.6L12 1.2' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.tick input:focus-visible{outline:2px solid var(--on);outline-offset:2px}
/* Ссылка на условия — цветом текста, а не синим по умолчанию:
   браузерный синий здесь единственное цветное пятно на экране. */
.tick a{color:var(--on);text-underline-offset:3px}
.form{display:grid;gap:12px;max-width:520px}
.say-no{margin:12px 0 0;font-size:14px;color:#b3261e}
.say-no:empty{display:none}
/* Отступ у кнопки — от ШАГА, а не от экрана записи. Правило стояло на
   `.book`, и на отзыве кнопка «Оставить отзыв» прилипала прямо к полю:
   между ними не было ни пикселя. Шаг один и тот же везде — и правило
   тоже одно. */
.step .go{margin-top:18px;min-width:min(220px,100%);justify-self:start}
.step .fld + .fld{margin-top:12px}
.step .tick{margin-top:14px}
.name{margin:0;font-size:clamp(22px,6vw,30px);font-weight:600;line-height:1.2;
  letter-spacing:-.02em}

/* ── ВСПЛЫВАШКА ──────────────────────────────────────────────────── */
.toast{
  position:fixed;left:50%;bottom:calc(22px + env(safe-area-inset-bottom));
  transform:translateX(-50%);z-index:80;max-width:min(92vw,420px);
  padding:13px 18px;border-radius:var(--r-pill);
  background:var(--floor-4);color:var(--lit);font-size:15px;
  box-shadow:0 10px 30px rgb(0 0 0 / .28);
  animation:toastUp var(--move) var(--ease);
}
.toast.bad{background:#8c1d18}
@keyframes toastUp{from{opacity:0;transform:translate(-50%,14px)}}
@media (prefers-reduced-motion:reduce){.toast{animation:none}}

.yframe{width:100%;height:420px;border:0;border-radius:var(--r-card);
  margin-top:22px;background:var(--floor-2)}
body.boot main{opacity:0}
main{transition:opacity var(--move) var(--ease)}

/* ── СПЕКТРАЛЬНЫЙ СВЕТ ────────────────────────────────────────────────
   У них на странице AirPods заголовок стоит внутри спектрального кольца.
   Я подходил к нему трижды и трижды получал фигуру вместо света:
   конической заливкой — насыщенный бублик; тонкими кольцами — мишень;
   линейной полосой под маской — светлый ПРЯМОУГОЛЬНИК с ровными краями,
   особенно заметный на тёмной земле.

   Ошибка была одна и та же: я рисовал форму и потом пытался спрятать её
   края. Край прямоугольника видно всегда — маска его смягчает, но не
   отменяет, а `overflow:hidden` рубит размытие по прямой.

   Свет не имеет краёв ПО УСТРОЙСТВУ, если он собран радиальными
   пятнами: каждое гаснет к своему краю само, и гасить руками нечего.
   Пять пятен разного цвета, смещённых друг относительно друга, дают
   спектр — и ни одной прямой линии во всей картинке.

   Двигается только `transform`: композитор считает это на карте. */
.glow{position:relative;isolation:isolate;
  margin-left:calc(-1 * clamp(20px,5.4vw,64px));
  margin-right:calc(-1 * clamp(20px,5.4vw,64px));
  padding:clamp(30px,9vw,64px) clamp(20px,5.4vw,64px)}
.glow > *{position:relative;z-index:1}
.glow::before{
  content:"";position:absolute;z-index:0;pointer-events:none;
  top:50%;left:50%;width:150%;aspect-ratio:1.5;translate:-50% -50%;
  background:
    radial-gradient(38% 52% at 26% 42%, rgb(255 150 190 / .42), transparent 68%),
    radial-gradient(34% 46% at 44% 62%, rgb(255 226 130 / .38), transparent 66%),
    radial-gradient(36% 50% at 60% 38%, rgb(150 240 210 / .38), transparent 68%),
    radial-gradient(40% 54% at 76% 58%, rgb(140 200 255 / .40), transparent 70%),
    radial-gradient(32% 44% at 52% 30%, rgb(196 160 255 / .34), transparent 66%);
  filter:blur(38px) saturate(1.05);
  animation:glowDrift 22s ease-in-out infinite alternate;
}
@keyframes glowDrift{
  from{transform:translate3d(-6%,-2%,0) scale(1)}
  to{transform:translate3d(6%,2%,0) scale(1.1)}
}
@media (prefers-reduced-motion:reduce){.glow::before{animation:none}}
.glow .say,.glow .kick{text-align:center}




/* ── ИМЯ САЛОНА НА ОБЛОЖКЕ ────────────────────────────────────────────
   Крупнее всего остального: по ссылке приходят, не зная, куда попали, и
   первый вопрос — «это кто». Обещание про запись отвечает на второй. */
.name-big{margin:0;font-size:clamp(40px,12.4vw,76px);font-weight:600;
  line-height:1.04;letter-spacing:-.035em;text-wrap:balance}
.say-sub{margin:12px 0 0;font-size:clamp(18px,4.8vw,24px);font-weight:500;
  line-height:1.3;letter-spacing:-.015em;color:var(--on);text-wrap:balance}
.cover .said{margin-top:10px;font-size:15px;max-width:32ch}


/* ── СКОЛЬКО ВЫЙДЕТ ───────────────────────────────────────────────────
   Услуг можно выбрать несколько, и главный вопрос сразу после выбора —
   сколько это стоит и сколько займёт. Без ответа человек считает сам по
   прайсу, а половина не считает вовсе и не записывается. */
.total{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 16px;
  margin:16px 0 0;padding:16px 0 0;border-top:1px solid var(--hair)}
.total b{font-size:clamp(22px,6vw,30px);font-weight:600;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.total span{font-size:15px;color:var(--soft)}

/* ── ОЦЕНКА ЗВЁЗДАМИ ──────────────────────────────────────────────────
   Пять кнопок по 44 пикселя: меньше — это «кнопка есть, но не
   нажимается», и промах здесь стоит человеку испорченной оценки. */
.stars{display:flex;gap:4px;margin-bottom:14px}
.star{
  appearance:none;border:0;background:none;cursor:pointer;padding:0;
  width:44px;height:44px;font-size:28px;line-height:1;
  color:color-mix(in srgb, var(--on) 22%, transparent);
  transition:color var(--tap) var(--ease),transform var(--tap) var(--ease);
}
.star[aria-checked="true"]{color:var(--on)}
.star:active{transform:scale(.9)}

/* Блоки, которые видны всегда (отзыв, вопрос, вход), стоят на своих
   экранах и потому не нуждаются в отдельном отступе сверху: его уже дал
   экран. Разделяет их линейка, а не пустота. */
.words .step,.about-us .step,.enter .step,.deals .step{
  border-top:1px solid var(--hair);padding-top:clamp(22px,6vw,34px)}
.enter .step:first-of-type{border-top:0;padding-top:0}
.enter .form,.enter .fld,.words .fld,.about-us .fld{max-width:520px}
.fld small{opacity:.7;font-weight:400}


/* ── ИТОГ ТАМ, ГДЕ ВЫБИРАЮТ ───────────────────────────────────────────
   Сумма и следующий шаг жили на экране записи — в двух тысячах пикселей
   ниже прайса. Человек отмечал услугу, страница улетала вниз, он
   возвращался за второй и улетал снова: «выбираю, и ничего не
   происходит».

   Полоса стоит над экраном, пока что-то выбрано. Она отвечает на месте и
   никуда не везёт без спроса. */
.bar{
  position:fixed;left:0;right:0;bottom:0;z-index:40;
  padding:12px clamp(16px,5vw,64px)
          calc(12px + env(safe-area-inset-bottom));
  background:color-mix(in srgb, var(--floor-1) 86%, transparent);
  -webkit-backdrop-filter:saturate(1.6) blur(18px);
  backdrop-filter:saturate(1.6) blur(18px);
  border-top:1px solid var(--ink-hair);
  animation:barUp var(--move) var(--ease);
}
@keyframes barUp{from{transform:translate3d(0,100%,0)}}
@media (prefers-reduced-motion:reduce){.bar{animation:none}}
.bar-in{display:flex;align-items:center;justify-content:space-between;
  gap:14px;max-width:1120px;margin:0 auto}
.bar-what{display:grid;gap:1px;min-width:0}
.bar-what b{font-size:19px;font-weight:600;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.bar-what span{font-size:13px;color:var(--ink-soft);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar .go{flex:0 0 auto;min-height:46px;padding:0 22px;
  background:var(--ink);color:var(--floor-1)}
/* Полоса закрывает низ страницы — освобождаем под неё место, иначе
   последняя строка подвала окажется под ней навсегда. */
body[data-bar] .tail{padding-bottom:calc(120px + env(safe-area-inset-bottom))}


/* ── «ДАЛЬШЕ ЕСТЬ ЕЩЁ» ────────────────────────────────────────────────
   Экраны здесь во всю высоту, и после первого человек не знает, есть ли
   второй: край экрана ровный, ничего не выглядывает. Тонкая стрелка на
   обложке говорит это одним знаком — и уходит, как только начали
   листать, чтобы не мозолить глаза всю дорогу. */
.more-hint{
  position:absolute;left:50%;bottom:calc(14px + env(safe-area-inset-bottom));
  translate:-50% 0;z-index:2;pointer-events:none;
  font-size:22px;line-height:1;color:var(--on);opacity:.5;
  animation:hintNod 2.4s var(--ease) infinite;
  transition:opacity var(--move) var(--ease);
}
body[data-scrolled] .more-hint{opacity:0}
@keyframes hintNod{
  0%,100%{transform:translate3d(0,0,0)}
  50%{transform:translate3d(0,6px,0)}
}
@media (prefers-reduced-motion:reduce){.more-hint{animation:none}}


/* ── КАРТОЧКА УСЛУГИ: ОДИН СИЛУЭТ ─────────────────────────────────────
   У них на iPad Pro карточка устроена так: сверху имя и фраза, снизу
   медиа, и всё это в общем скруглении. Пара «что это» и «как выглядит»
   читается одним предметом, а не подписью к иллюстрации.

   Здесь снимок рисует WebGL, поэтому текст не внутри холста, а НАД ним —
   но в тех же границах и на том же полу, поэтому граница между ними не
   читается. Ширину задаёт та же доля, что и колоде, иначе подпись
   разъедется с карточкой на широком экране. */
/* Подпись и снимок стоят ОДНОЙ КОЛОНКОЙ, а не наложением: при
   абсолютном позиционировании подпись липла к верху сцены, а карточка
   висела по центру — между ними зияла пустота, и один силуэт
   рассыпался на два предмета. Сетка держит их вместе сама. */
/* ВЫСОТА СЦЕНЫ ОБЯЗАНА БЫТЬ ЗАДАНА ЧИСЛОМ, А НЕ ВЫВЕДЕНА ИЗ СОДЕРЖИМОГО.

   Здесь стояло `min-height:0`, и это молча ломало весь экран услуг в
   Safari. Полотно просит `height:100%` от сцены, а сцена без своей высоты
   меряется по содержимому — то есть по полотну. Круг замкнут, и браузеры
   разрешают его по-разному: Chromium выбирает какое-то число, а Safari
   считает процент неразрешимым и берёт высоту из АТРИБУТА полотна. Атрибут
   же ставит `size()` в пикселях устройства — вдвое-втрое больше кадра, — и
   тут же читает его обратно. Полотно раздувается каждый кадр.

   Со стороны это выглядело как «в пятой версии сайт пустой»: заголовок и
   подпись услуги на месте, а цена, «Записаться», точки и стрелки уехали на
   тысячи пикселей вниз, и под подписью оставалась чёрная пустота во весь
   экран. На соседней сцене мастеров этого нет — там `min-height` уцелел.

   Число возвращаем, чередование подписи (`grid-template-rows`) остаётся. */
.svc .stage{position:relative;display:grid;
  grid-template-rows:auto minmax(0,1fr);justify-items:center;
  height:min(48svh,440px)}
/* И полотну запрещено требовать себе место по содержимому.
   У элемента сетки автоматический минимум равен его собственному размеру, а
   у полотна это число из АТРИБУТА — туда `size()` пишет пиксели устройства,
   вдвое-втрое больше кадра. Строка не могла стать ниже этого числа, сцена
   росла, `size()` удваивал атрибут снова. В WebKit полотно доходило до 936
   точек при окне в 1200: цена оказывалась на 1307, стрелки на 1373 — то
   есть за нижним краем, и под подписью услуги оставалась пустота во весь
   экран. Chromium то же место разрешает иначе, и там всё выглядело целым. */
.svc .stage canvas{align-self:center;min-height:0;min-width:0}
/* ПОДПИСЬ ЧЕРЕДУЕТСЯ: у одной карточки сверху, у следующей снизу.
   Их приём с iPad Pro, и он не украшение: одинаково собранные карточки
   подряд читаются как таблица, и глаз перестаёт их различать. Смена
   стороны заставляет посмотреть на каждую заново — а держится всё на
   двух положениях, не на пяти, поэтому это ритм, а не цирк. */
.svc .stage[data-say="under"]{grid-template-rows:minmax(0,1fr) auto}
.svc .stage[data-say="under"] .card-say{order:2;padding:12px 2px 0}
.card-say{
  width:min(72%,420px);display:grid;gap:6px;
  padding:0 2px 12px;text-align:left;pointer-events:none;
  transition:opacity var(--move) var(--ease);
}
.card-say b{font-size:clamp(19px,5vw,24px);font-weight:600;line-height:1.25;
  letter-spacing:-.02em;color:var(--on);text-wrap:balance}
.card-say span{font-size:14px;line-height:1.45;color:var(--soft);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
/* Во время броска подпись гаснет: имя одной карточки поверх летящей
   другой — это подпись, которая врёт. */
.svc[data-flying] .card-say{opacity:0}
@media (min-width:760px){.card-say{width:min(46%,460px)}}


/* СЧЁТЧИК ВМЕСТО РОССЫПИ ТОЧЕК.
   Точка отвечает на вопрос «где я и много ли осталось». На пяти карточках
   она с этим справляется, на двадцати — это четырнадцать одинаковых кружков,
   по которым нельзя попасть и в которых нечего узнать. Число отвечает на тот
   же вопрос точнее и занимает меньше места, а рядом стоит дверь в полный
   прайс: он разбит по разделам и с ценами, и искать надо там. */
.pip-count{font-size:13px;font-weight:500;letter-spacing:0;color:var(--faint);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.pip-all{appearance:none;border:0;cursor:pointer;font:inherit;font-size:13px;
  font-weight:500;color:var(--on);background:var(--lift);
  padding:7px 13px;border-radius:99px;margin-left:10px;white-space:nowrap;
  transition:opacity var(--move) var(--ease)}
.pip-all:active{opacity:.6}


/* Рубрика над именем услуги: тише имени, чтобы не спорить с ним, и с
   разрядкой — так короткое слово читается как указатель раздела, а не как
   вторая строка названия. */
.card-kind{display:block;font-size:11px;font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint);font-style:normal;margin-bottom:2px}

/* ДВОЙНОЙ ТАП НЕ ДОЛЖЕН УВЕЛИЧИВАТЬ СТРАНИЦУ.
   Браузер ждёт второго касания, чтобы решить «это зум или нажатие», — от
   этого и задержка, и внезапное увеличение при быстрых нажатиях по
   карточкам. `manipulation` убирает именно двойной тап и НЕ трогает
   щипок: увеличить страницу пальцами по-прежнему можно, и это важно для
   тех, кто плохо видит. */
button, a, .opt, .row, .pip, .arw, .pill, .go{touch-action:manipulation}

/* ══ ПОЛКА ═══════════════════════════════════════════════════════════════
   Свои снимки владельца с подписями: линейка длин ногтей, вид кабинета,
   схема проезда.

   СЕТКА, А НЕ ЛЕНТА. Соседние блоки витрины листаются вбок, и первым
   побуждением было повторить это здесь. Но ленту листают только те, кто
   понял, что она листается: у полки нет ни повторяющегося ритма, ни
   счёта, по которым это видно, — а значит половина клиентов увидела бы
   один снимок из шести. Сетка показывает всё сразу.

   ОДНА КОЛОНКА НА ТЕЛЕФОНЕ. Схема проезда и линейка длин — это то, что
   РАССМАТРИВАЮТ; в половину экрана рассмотреть нельзя. */
.shelf-grid{display:grid;gap:14px;grid-template-columns:1fr}
@media (min-width:640px){
  .shelf-grid{grid-template-columns:repeat(2,1fr);gap:18px}
}
@media (min-width:1000px){
  .shelf-grid{grid-template-columns:repeat(3,1fr)}
}
.shelf-card{margin:0;display:flex;flex-direction:column;gap:10px}
/* ВЫСОТА ЗАРЕЗЕРВИРОВАНА ДО ЗАГРУЗКИ.
   Без этого страница прыгает под пальцем, когда доезжает шестой снимок, —
   и человек нажимает не туда, куда целился. Пропорция 4:3, а не квадрат:
   линейка длин и схема проезда почти всегда горизонтальные. */
.shelf-card img{width:100%;aspect-ratio:4/3;object-fit:cover;
  /* 4:3 — только резерв места до загрузки: настоящие пропорции
     ставит скрипт, когда снимок пришёл. Жёсткая рамка резала
     широким кадрам края, а узким добавляла пустоты. */
  border-radius:var(--r-card, 18px);background:var(--floor-2, #eee);display:block}
.shelf-card figcaption{display:flex;flex-direction:column;gap:3px}
.shelf-card figcaption b{font-size:15px;font-weight:600;line-height:1.25}
.shelf-card figcaption span{font-size:13px;line-height:1.4;color:var(--faint)}

/* «ЕЩЁ» У ОПИСАНИЯ МАСТЕРА.
   Не ссылка и не кнопка на вид: это продолжение той же фразы, и рисовать
   вокруг него рамку значит превращать чтение в действие. Подчёркивание —
   единственный знак, что сюда можно нажать. */
.biomore{appearance:none;border:0;background:none;padding:0;margin:0;
  font:inherit;color:inherit;cursor:pointer;opacity:.65;
  text-decoration:underline;text-underline-offset:2px}
.biomore:hover{opacity:1}

/* ══ ПЛАТНОЕ ОКНО ════════════════════════════════════════════════════════
   Мастер открыл субботний вечер и просит за него отдельно. Цена уже стоит
   в подписи кнопки — цвет говорит «это не обычное окно» с одного взгляда,
   до нажатия, а не в чеке после.

   ПОЧЕМУ НЕ КРАСИМ САМ ТЕКСТ. У «Призмы» нет цвета владельца: она набрана
   полами и чернилами, и цветной текст в ней читался бы как посторонний
   элемент. Обводка и лёгкая подложка говорят то же самое и не спорят ни с
   одним из полов. */
.opt.paid{
  box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--on) 42%, transparent);
  background:color-mix(in srgb, var(--on) 11%, transparent);
}
.opt.paid:hover{background:color-mix(in srgb, var(--on) 16%, transparent)}
