/* GREY'S — мобильная версия по референсу ref.png (макет 440pt, снят с кропов 1:1.94).
   Тёмный панк-лендинг: граффити-заголовки (Rubik Wet Paint / Spray Paint),
   кислотный #c6f21e, горизонтальные ленты работ и услуг.
   Герой-фото и стикер-сердце вырезаны из самого референса:
   - hero_face.png кладётся на почти совпадающий CSS-фон и растворяется
     mask-градиентами по краям (жёсткий край чужого чёрного нельзя);
   - sticker_heart.png несёт чёрную подложку — гасится mix-blend-mode: screen,
     поэтому между ним и <body> не должно появиться stacking context
     (filter/transform/opacity на предках). */

/* == CRITICAL:BEGIN ==
   Всё до парного CRITICAL:END инлайнится в <head> mobile.html (первый экран:
   шрифты, root/reset, topbar, menu, hero, CTA) — mobile.css там грузится
   асинхронно и первую отрисовку не блокирует. После правок внутри блока
   запусти `py tools/inline_critical.py`, иначе инлайн разойдётся с файлом. */

/* шрифт владельца для заголовков (кириллический граффити-тег, ofont.ru).
   woff2 пережат из TTF (fontTools), TTF остаётся фолбэком для древних браузеров */
@font-face {
  font-family: 'TagType';
  src: url('../mobile_assets/fonts/TagType.woff2') format('woff2'),
       url('../mobile_assets/ofont.ru_TagType.ttf') format('truetype');
  font-display: swap;
}

/* Google-шрифты хостим сами (mobile_assets/fonts/): блокирующий CSS
   fonts.googleapis.com держал первую отрисовку ~900 мс. Сабсеты и
   unicode-range скопированы дословно из выдачи Google Fonts (Chrome UA);
   latin-ext у Manrope обязателен — в нём живёт знак ₽ (U+20BD). */

/* Manrope — variable 400..600 (один файл на сабсет вместо трёх весов) */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../mobile_assets/fonts/manrope-var-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../mobile_assets/fonts/manrope-var-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../mobile_assets/fonts/manrope-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Rubik Spray Paint — фолбэк TagType; пока TagType грузится, не скачивается вовсе */
@font-face {
  font-family: 'Rubik Spray Paint';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../mobile_assets/fonts/rubik-spray-paint-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Rubik Spray Paint';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../mobile_assets/fonts/rubik-spray-paint-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* PT Mono — цены и календарь (services/booking); ₽ в нём нет — падает в Manrope */
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../mobile_assets/fonts/pt-mono-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../mobile_assets/fonts/pt-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #0c0d0c;
  --bg-card: #1b1b1d;
  --acid: #c6f21e;
  --ink: #f5f5f2;
  --muted: #9c9c9e;
  --font-marker: 'TagType', 'Rubik Spray Paint', cursive; /* заголовки секций, карточки */
  --font-body: 'Manrope', 'Segoe UI', sans-serif;
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.6 0 0 0 0 0.6 0 0 0 0 0.6 0 0 0 0.12 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { overscroll-behavior-y: none; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
html, body { overflow-x: hidden; overflow-x: clip; }

body {
  /* фон почти плоский тёмный; лёгкое высветление к верхнему правому — там, где
     кроп героя несёт свой свет, шов маскируется совпадением тонов */
  background-color: var(--bg);
  background-image:
    radial-gradient(90% 400px at 88% 50px, #1c1d1c 0%, #121312 45%, transparent 75%);
  background-repeat: no-repeat;
  color: var(--ink);
  font: 400 16px/1.5 var(--font-body);
  max-width: 440px;
  margin-inline: auto;
  padding-bottom: env(safe-area-inset-bottom);
}

a, button { touch-action: manipulation; }
/* картинки по умолчанию перетаскиваемы: «схватиться» за фото в ленте начинало
   нативный drag и жест уходил ему, а не скроллу. Гасим drag/callout, чтобы палец
   всегда скроллил (у всех <img> в разметке ещё и draggable="false"). */
img { user-select: none; -webkit-user-drag: none; -webkit-touch-callout: none; }
ul, ol { list-style: none; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* ---------- шапка ---------- */

.topbar {
  position: relative; z-index: 5;
  display: flex; align-items: center;
  padding: 10px 24px 0 27px;
}
.topbar__home, .footer__home { display: inline-flex; }
.topbar__logo { width: 84px; height: auto; }
.topbar__tag {
  display: flex; align-items: center; gap: 10px;
  margin-left: 74px;
  font: 400 12.5px/1.4 var(--font-body);
  letter-spacing: 0.02em;
}
.spark { color: var(--acid); flex: none; }
.spark--tag { width: 20px; height: 20px; transform: rotate(-12deg); }
.topbar__burger {
  width: 46px; height: 46px; margin-left: auto;
  border-radius: 50%;
  border: 1.5px solid rgba(198, 242, 30, 0.85);
  background: transparent; color: #f0f0ee;
  display: grid; place-items: center; cursor: pointer;
}
.topbar__burger:active { background: rgba(198, 242, 30, 0.12); }

/* ---------- бургер-оверлей ---------- */

.menu {
  position: fixed; inset: 0; z-index: 30;
  background: rgba(7, 7, 8, 0.97);
  display: grid; place-items: center;
  opacity: 0; visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}
.menu.open { opacity: 1; visibility: visible; transition: opacity 0.25s ease; }
.menu__list { display: grid; gap: 26px; text-align: center; }
.menu__list a {
  font: 400 24px var(--font-marker);
  letter-spacing: 0.05em; color: var(--ink); text-decoration: none;
  text-transform: uppercase;
}
.menu__list a:active { color: var(--acid); }
.menu__tel { font-family: var(--font-body); font-size: 17px; color: var(--muted); text-transform: none; }

/* ---------- герой ----------
   Вертикали (CSS px от верха, из референса /1.94): фото 103…, КРЕЙЗИ ~150,
   МАНИКЮР ~235, подзаголовок ~310, CTA 374–441. */

.hero { position: relative; }

/* <picture> — только обёртка для выбора кадра (телефон/десктоп), в раскладке
   её быть не должно: сам <img> абсолютный, а пустой инлайн-бокс обёртки мог бы
   породить строчный бокс и сдвинуть заголовок вниз. display: contents убирает
   её из дерева боксов целиком; на выбор картинки это не влияет — он делается
   на уровне HTML, а не раскладки. */
.hero picture { display: contents; }

.hero__photo {
  /* верх фото в макете — 59px от верха страницы; .hero начинается после шапки (~77px) */
  position: absolute; z-index: 0;
  top: -18px; right: 0;
  width: 218px; height: auto;
  pointer-events: none;
  /* растворение краёв: слева/сверху тонкая кромка, снизу шире — запястье уходит в фон */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, #000 16px),
    linear-gradient(to bottom, transparent 0, #000 14px, #000 calc(100% - 30px), transparent);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0, #000 16px),
    linear-gradient(to bottom, transparent 0, #000 14px, #000 calc(100% - 30px), transparent);
  mask-composite: intersect;
}

.doodle { position: absolute; pointer-events: none; }
.doodle--star-left { left: 14px; top: 173px; width: 26px; color: #e8e8e4; }
/* Овал вокруг «кто» снят по просьбе владелицы (2026-07-28) — и на мобильном,
   и на десктопе. Гасим стилем, а не удаляем <svg> из вёрстки: так правка
   отменяется одной строкой, если решение переиграют. Значения ниже больше ни
   на что не влияют, но оставлены как след исходной геометрии. */
.doodle--circle { display: none; left: 148px; top: 161px; width: 112px; color: rgba(200, 200, 195, 0.75); z-index: 2; }
.doodle--star-cta { right: -16px; bottom: 16px; width: 15px; color: var(--acid); }

.hero__title {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: flex-start;
  padding: 24px 0 0 27px;
}
.hero__wordmark {
  width: 212px; height: auto;
  pointer-events: none;
}

.hero__sub {
  position: relative; z-index: 1;
  margin: 34px 0 0 46px;
  font-size: 17px; line-height: 1.22;
  letter-spacing: 0.22em;
  color: #d6d6d4;
}

/* CTA: кислотная пилюля внутри рваной белой рамки-обводки (SVG) */
.cta-wrap {
  position: relative; z-index: 1;
  width: 186px; height: 70px;
  margin: 29px 0 0 24px;
}
/* краска овала в Book_stroke.png смещена от центра холста (центр ≈ 93.5,36.5 из 200×68) —
   ширина и сдвиги подобраны так, чтобы центр овала совпал с центром пилюли (93,35) */
.cta-frame { position: absolute; left: 0; top: -1px; width: 198px; height: auto; transform: rotate(-0.6deg); }
.cta {
  position: absolute; left: 12px; top: 13px;
  width: 162px; height: 44px;
  display: inline-flex; align-items: center; justify-content: space-between;
  padding: 0 20px;
  background: var(--acid);
  border-radius: 22px;
  color: #101110; text-decoration: none;
  font: 600 15.5px var(--font-body);
  letter-spacing: 0.09em; text-transform: uppercase;
}
.cta:active { filter: brightness(0.92); }
.cta__arrow { width: 17px; height: 17px; }

/* ---------- секции: шапка-строка + пилюля ---------- */

.sec { margin-top: 40px; }
#services { margin-top: 30px; }
.sec__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 22px 0 28px;
}
.sec__head h2, .steps__head h2 {
  display: flex; align-items: center; gap: 12px;
  font: 400 22px var(--font-marker);
  letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.sec__head .spark, .steps__head .spark { width: 28px; height: 28px; transform: rotate(-8deg); }

.pill {
  display: inline-flex; align-items: center; gap: 10px; flex: none;
  height: 33px; padding: 0 17px;
  border: 1px solid rgba(198, 242, 30, 0.8);
  border-radius: 999px;
  color: var(--ink); text-decoration: none;
  font: 400 14px var(--font-body);
}
.pill svg { width: 14px; height: 14px; color: var(--acid); }
.pill:active { background: rgba(198, 242, 30, 0.1); }

/* ---------- ленты (нативный горизонтальный скролл) ---------- */

.rail {
  display: flex; gap: 9px;
  overflow-x: auto;
  /* overflow-x:auto заставляет overflow-y вычислиться в auto — лента становилась
     вертикально прокручиваемым контейнером (хватало 1px переполнения от обрывков
     .scard::before), и вертикальный свайп по «пустому» месту карточки тянул саму
     ленту вместо страницы. overflow-y:hidden убирает вертикальный ход ленты
     структурно: вертикальный жест уходит цепочкой на страницу, горизонтальный
     по-прежнему листает ленту. Обрывки .scard::before помещаются в паддинг (18/10px).
     touch-action НЕ ограничиваем: pan-x запрещает вертикальный пан для касаний,
     начатых на ленте (палец на фото работ глушил вертикальный скролл страницы) —
     нативному горизонтальному скроллеру нужен обычный auto. */
  overflow-y: hidden;
  padding: 16px 10px 4px;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > li { flex: none; scroll-snap-align: start; }

.rail--works { padding-bottom: 0; }
.rail--works img {
  width: 114px; height: 118px;
  object-fit: cover; border-radius: 5px; display: block;
}

/* == CRITICAL:END ==
   Конец критического блока именно ЗДЕСЬ, а не после hero: секция работ
   задевает низ первого экрана, и пока стили ленты ехали асинхронно,
   миниатюры рендерились в свой intrinsic-размер (320×427 из width/height
   атрибутов) и при доезде CSS схлопывались до 114×118 — Lighthouse считал
   это как CLS 0.49. Ленте (.sec/.rail/.rail--works) место в инлайне. */

/* ---------- карточки услуг ---------- */

.rail--cards { gap: 20px; padding: 18px 20px 10px 23px; }

/* рваный контур: клип на внутреннем слое, обрывок «бумаги» — на <li> под ним
   (clip-path режет и ::before, поэтому обрывок живёт на непорезанном родителе) */
.scard { position: relative; width: 178px; }
.scard::before {
  content: '';
  position: absolute; z-index: 0;
  left: -5px; bottom: -7px; width: 64px; height: 24px;
  background: #d9d6cf;
  clip-path: polygon(0 45%, 14% 0, 38% 28%, 62% 6%, 100% 40%, 82% 100%, 18% 88%);
  transform: rotate(-7deg);
}
/* Четыре формы обрывка по кругу (4n+1 — базовое правило выше). Раньше это
   были nth-child(2|3|4): карточки редактируются из админки, и на пятой все
   следующие получали бы форму первой, то есть один и тот же обрывок подряд. */
.scard:nth-child(4n + 2)::before { left: auto; right: -4px; bottom: -6px; width: 48px; height: 18px; transform: rotate(5deg); }
.scard:nth-child(4n + 3)::before { left: 30%; bottom: auto; top: -6px; width: 52px; height: 18px; transform: rotate(3deg); }
.scard:nth-child(4n)::before { left: -4px; bottom: auto; top: 30%; width: 20px; height: 44px; transform: rotate(2deg); }
.scard__in {
  position: relative; z-index: 1;
  display: flex; flex-direction: column;
  min-height: 122px; height: 100%;
  padding: 13px 14px 13px 18px;
  background-color: var(--bg-card);
  background-image: radial-gradient(120% 90% at 30% 0%, #232325 0%, transparent 55%), var(--noise);
  clip-path: polygon(
    2.5% 3%, 9% 0.5%, 28% 1.8%, 47% 0%, 68% 1.5%, 88% 0.5%, 97% 2.5%,
    99.5% 8%, 98.6% 26%, 100% 47%, 98.8% 68%, 99.6% 88%, 97% 97%,
    88% 99.4%, 66% 98.2%, 45% 100%, 24% 98.4%, 8% 99.6%, 2% 96.5%,
    0.4% 86%, 1.4% 64%, 0% 44%, 1.2% 22%, 0.6% 9%);
}
.scard__in h3 {
  display: flex; align-items: center; gap: 8px;
  font: 400 17px var(--font-marker);
  letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.scard__in h3 .spark { width: 17px; height: 17px; }
.scard__in p {
  margin-top: 8px;
  font-size: 12.5px; line-height: 1.38;
  color: #c7c7c9;
}
.scard__foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: auto; padding-top: 12px;
}
.scard__price {
  font: 600 16px var(--font-body);
  letter-spacing: 0.02em;
  color: var(--acid);
}
.scard__plus {
  position: relative;
  width: 27px; height: 27px;
  border: 1.5px solid var(--acid); border-radius: 50%;
  color: var(--acid);
  display: grid; place-items: center;
}
.scard__plus svg { width: 12px; height: 12px; }
.scard__plus::after { content: ''; position: absolute; inset: -9px; } /* зона тапа */
.scard__plus:active { background: rgba(198, 242, 30, 0.14); }

/* ---------- как проходит запись ---------- */

.steps { position: relative; margin-top: 8px; padding: 0 27px; }
.steps__head { position: relative; }
.steps__head h2 { display: block; line-height: 1.3; font-size: 24px; max-width: 230px; white-space: normal; }
.steps__head .spark { display: inline-block; margin-left: 10px; vertical-align: -3px; }
.steps__sticker {
  /* heart.png — вырезанный кластер с прозрачным фоном, бленды не нужны */
  position: absolute; right: 10px; top: -10px;
  width: 195px; height: auto;
  pointer-events: none;
}

.steps__list { margin-top: 30px; }
.steps__list li {
  display: flex; gap: 18px; align-items: baseline;
  padding: 15px 2px;
}
.steps__list li + li { border-top: 1px dashed rgba(255, 255, 255, 0.16); }
.steps__num {
  flex: none; width: 44px;
  font: 400 21px var(--font-marker);
  color: var(--acid);
}
.steps__list h3 { font: 600 15px var(--font-body); letter-spacing: 0.02em; }
.steps__list p { margin-top: 3px; font-size: 13px; color: var(--muted); }

.cta-wrap--center { margin: 26px auto 0; }

/* ---------- футер ---------- */

.footer {
  margin-top: 52px;
  padding: 24px 27px calc(30px + env(safe-area-inset-bottom));
  display: grid; justify-items: start; gap: 9px;
}
.footer__tear { width: calc(100% + 54px); margin: 0 -27px 10px; height: 12px; }
.footer__logo { width: 58px; height: auto; }
.footer__addr { font-size: 13px; color: var(--muted); }
.footer__hours { font-size: 13px; color: var(--muted); }
.footer__tel { font: 600 15px var(--font-body); color: var(--ink); text-decoration: none; }
.footer__soc { display: flex; gap: 20px; margin-top: 4px; }
.footer__soc a { font-size: 13px; color: var(--acid); text-decoration: none; }
.footer__req { margin-top: 6px; font-size: 11px; line-height: 1.5; color: #737375; }
.footer__copy { margin-top: 10px; font-size: 11.5px; color: #737375; }

/* ---------- узкие экраны (iPhone SE и близкие) ---------- */

/* == CRITICAL:BEGIN == (медиазапрос правит и первый экран — уезжает в инлайн целиком) */
@media (max-width: 385px) {
  .topbar { padding-inline: 20px; }
  .topbar__tag { margin-left: 34px; }
  .hero__title { padding-left: 20px; }
  .hero__wordmark { width: 182px; }
  .hero__photo { width: 176px; }
  .hero__sub { margin-left: 34px; font-size: 15px; }
  .doodle--star-left { top: 178px; width: 22px; }
  .doodle--circle { left: 118px; top: 168px; width: 100px; }
  .cta-wrap { margin-left: 16px; }
  .sec__head { padding: 0 14px 0 20px; }
  .sec__head h2 { font-size: 21px; }
  .pill { height: 30px; padding: 0 13px; font-size: 13px; }
  .steps { padding-inline: 20px; }
  .steps__head h2 { font-size: 23px; max-width: 200px; }
  .steps__sticker { width: 146px; right: 0; top: -8px; }
  .footer { padding-inline: 20px; }
  .footer__tear { width: calc(100% + 40px); margin-inline: -20px; }
}
/* == CRITICAL:END == */

/* ---------- плашка о cookie ----------
   Намеренно на body-шрифте (Manrope), без граффити-начертания: это служебный
   текст, и «крейзи»-подача в юридической плашке читается как несерьёзность.
   z-index ниже меню (30), чтобы открытый бургер её перекрывал.

   Появления НЕТ намеренно. Сначала оно было переходом по классу из
   requestAnimationFrame, потом CSS-анимацией с fill-mode: both — и оба раза
   в фоновой вкладке плашка застревала на первом кадре, то есть висела
   невидимой, но продолжала ловить клики внизу экрана. Никакая плавность
   этого не стоит: базовое состояние теперь просто «видима». */
.cookiebar {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 25;
  display: flex; flex-direction: column; gap: 12px;
  padding: 15px 16px 16px;
  font-family: var(--font-body);
  background: #17181a;
  border: 1px solid rgba(245, 245, 242, 0.16);
  border-radius: 14px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
}
.cookiebar[hidden] { display: none; }
.cookiebar__text {
  margin: 0; font-size: 13px; line-height: 1.5; color: #cfcfcd;
}
.cookiebar__text a { color: var(--acid); text-decoration: none; white-space: nowrap; }
.cookiebar__text a:hover { text-decoration: underline; }
.cookiebar__row { display: flex; align-items: center; gap: 12px; }
.cookiebar__btn {
  flex: none;
  min-height: 40px; padding: 0 22px;
  font: 600 14px/1 var(--font-body); letter-spacing: 0.01em;
  color: #10110f; background: var(--acid);
  border: 0; border-radius: 999px; cursor: pointer;
}
.cookiebar__btn:active { transform: translateY(1px); }

/* Уход: только прозрачность, без transform — на широких экранах transform
   занят центрированием, и его перебивка сдвинула бы плашку вбок. */
.cookiebar.is-out { opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
  .cookiebar.is-out { transition: opacity 0.2s ease; }
}

@media (min-width: 560px) {
  .cookiebar {
    left: 50%; right: auto; transform: translateX(-50%);
    width: min(520px, calc(100vw - 24px));
    flex-direction: row; align-items: center; gap: 16px;
  }
}

/* ---------- десктоп ----------
   Мобильный макет (колонка 440) расширяется до 1160; ниже 768px не меняется
   ничего. Разделено на ДВА блока подряд:
   1) этот, огороженный CRITICAL — первый экран, уезжает в инлайн mobile.html;
   2) следующий, без ограды — всё ниже сгиба, приезжает с асинхронным файлом.
   Осознанный размен: на десктопе карточки/шаги/футер мгновение рисуются
   по-мобильному и перекладываются по приезде файла. Это ниже сгиба, CLS не
   стоит, и ровно так же устроена существующая ограда выше по файлу.
   ПОСЛЕ ЛЮБОЙ ПРАВКИ ВНУТРИ ОГРАДЫ: py tools/inline_critical.py */

/* == CRITICAL:BEGIN == (первый экран десктопа; продолжение — блоком ниже) */
@media (min-width: 768px) {
  /* Единственные две переменные в проекте. Заведены не ради «шкалы отступов»
     (в файле везде литералы и так лучше), а потому что каждая связывает
     значения, которые обязаны двигаться вместе: --gutter держит вылет
     .footer__tear, --hero-top держит оба дудла. Объявлены ВНУТРИ медиазапроса,
     поэтому на мобильном их не существует вовсе. */
  /* Поля вместо колонки (правка 2026-07-28 по макету владелицы: «сайт сжат по
     ширине»). Раньше было max-width: 1160px, и на 1920 страница занимала 60%
     экрана. Теперь ширину задаёт ТОЛЬКО поле:
       clamp(40px, 6.6vw, 120px) — 6.6vw даёт ~95px на 1440, как в макете;
       max(..., (100vw - 1700px)/2) — на очень широких экранах поле растёт само
       и держит контент в пределах 1700px, чтобы строки не превращались в простыню.
     Одно выражение заменяет и контейнер, и его предел. */
  :root {
    --gutter: max(clamp(40px, 6.6vw, 120px), calc((100vw - 1700px) / 2));
    /* На сколько фото героя заезжает ВВЕРХ под шапку. Ноль до 1160px — и это
       не лень, а необходимость: там меню ещё двухстрочная полоса во всю
       ширину, и поднятое фото накрывало пилюлю «Записаться» (замерено на
       1159px). Перекрытие включается только вместе с однострочной шапкой,
       которая специально выровнена вправо и ложится на тёмный верх кадра. */
    --header-h: 0px;
  }

  /* body во всю ширину — это НЕ косметика, а условие полосного героя: у html и
     body стоит overflow-x: clip, и фото, вылезающее за колонку, срезалось бы по
     её краю. Отступ по-прежнему посекционный: padding-inline у body появиться
     не может — .hero его прямой ребёнок, и абсолютные координаты дудлов ушли бы
     в минус, где их съест тот же clip. */
  body { max-width: none; background-image: none; }

  /* ---- шапка ---- */

  .topbar { padding: 18px var(--gutter) 0; }
  .topbar__logo { width: 104px; }
  /* margin-left: 74px — хардкод под колонку 440, растянуть его нечем: строка
     не перераспределяется. Заменяем на auto, слоган уходит вправо. */
  .topbar__tag { margin-left: auto; font-size: 13.5px; }
  .topbar__burger { display: none; }

  /* ---- меню строкой ----
     #menu — СОСЕД .topbar, оба прямые дети body. Шесть пунктов маркерным
     начертанием занимают ~850px: вместе с логотипом и слоганом в одну строку
     они не помещаются (~1130 при контенте 1064), поэтому меню становится
     статичной полосой под строкой логотипа.
     Селектор пишется «.menu, .menu.open» намеренно: базовое .menu.open — это
     (0,2,0) и перебило бы голое .menu по transition. Так открытое и закрытое
     состояние на десктопе одинаковы, и клик по недостижимому бургеру не может
     дать странный вид. js/mobile.js при этом не трогаем вообще. */
  .menu, .menu.open {
    position: static; inset: auto; z-index: auto;
    display: block; background: transparent;
    /* place-items ОБЯЗАТЕЛЬНО сбрасывать вместе с display. В современном Chrome
       justify-items/justify-self действуют и на блочные боксы, а не только на
       grid: оставшийся от базового правила `place-items: center` продолжал
       ужимать <nav> до max-content и центрировать его (замерено: 795px на
       x=315 вместо 1064 на x=181), из-за чего margin-left:auto у телефона
       не имел свободного места и не работал. Симптом обманчив — computed
       display при этом честно показывает block. */
    place-items: normal;
    opacity: 1; visibility: visible; transition: none;
    padding: 10px var(--gutter) 16px;
  }
  .menu__list {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 10px 30px; text-align: left;
  }
  /* Пункты уходят с маркерного шрифта на основной. Это не только вкус: в
     граффити-начертании шесть пунктов занимают ~850px и в строку с логотипом
     не помещаются физически, а в Manrope 13px — ~470px, и однострочная шапка
     из макета становится возможной. */
  .menu__list a {
    font: 600 13px var(--font-body);
    letter-spacing: 0.1em;
    color: #d8d8d5;
  }
  .menu__list a:hover { color: var(--acid); }
  /* «Записаться» — кислотная пилюля, как в макете. Цепляемся за href, а не за
     позицию: порядок пунктов задаётся из админки и в любой момент меняется. */
  .menu__list a[href="/booking"] {
    padding: 11px 20px;
    background: var(--acid); color: #101110;
    border-radius: 999px;
  }
  .menu__list a[href="/booking"]:hover { color: #101110; filter: brightness(0.94); }
  /* .menu__tel несёт data-cms, а rebuildList при публикации складывает таких
     детей в preserved и возвращает с сохранённым классом — auto доживёт. */
  .menu__list .menu__tel { margin-left: auto; font-size: 14px; letter-spacing: 0.04em; }

  /* ---- герой ----
     Две колонки без единой правки разметки: текстовые блоки и так стоят слева
     в потоке, фото и так абсолютное справа. Все внутренние смещения = мобильное
     значение + 21 (48 - 27), чтобы рваная лесенка макета сохранилась точно. */

  .hero {
    /* ширина/высота фото через vw (не %), чтобы их можно было переиспользовать
       в min-height и в градиенте: проценты там считались бы от высоты.
       48vw — пропорция из макета владелицы. Высота задаётся ОТДЕЛЬНО, а не
       выводится из ширины: исходник 423x700 — вертикальный кроп, и при ширине
       691px он был бы 1143px высотой. Кадрируем object-fit: cover. */
    /* Фото БОЛЬШЕ НЕ уходит в обрез к краю экрана (правка по замечанию
       владелицы): у всего сайта широкие поля, и кадр, прилипший к краю,
       выбивался из этого ритма. Теперь правый край фото совпадает с правым
       краем контента (right: var(--gutter)), а сам кадр там растворяется
       градиентом — см. маску ниже.
       53vw подобрано так, чтобы при выросшем заголовке левый край кадра всё
       ещё оставался правее текста: запас проверен на 768..1920. */
    --photo-w: min(53vw, 900px);
    --photo-h: min(46vw, 700px);
    --hero-top: 40px;
    /* высота логотипа-заголовка нужна отдельно: от неё считается положение
       звезды, иначе при текучей ширине заголовка она отрывается от подзаголовка.
       Потолок 444px — родной размер @2x-растра (см. <picture> в mobile.html);
       выше него начнётся апскейл. */
    --wordmark-w: clamp(212px, 30vw, 444px);
    --wordmark-h: calc(var(--wordmark-w) * 0.59);
    min-height: calc(var(--photo-h) - var(--header-h) + 28px);
    /* Свечение переезжает сюда с body. У <html> фона нет, поэтому фон body
       распространяется на канву и позиционируется относительно КОРНЕВОГО
       элемента: замерено — на 1440 пик свечения стоит на x=1270 (88% вьюпорта),
       а колонка живёт в 500..940. Расширение body это не чинит. На .hero
       градиент привязан к фото конструктивно и не может от него уехать.
       Его работа — держать тон под кропом ~#0e0f0e, иначе маска-растворение
       фото даёт видимый шов. Коэффициенты сняты с мобильных пропорций
       (радиусы 1.816/1.834 ширины фото, центр 0.243 левее правого края
       и 0.041 выше верха). background-image стекающий контекст не создаёт. */
    background-image: radial-gradient(
      calc(var(--photo-w) * 1.15) calc(var(--photo-h) * 1.35)
      at calc(100% - var(--photo-w) * 0.4)
         calc(var(--photo-h) * 0.34 - var(--header-h)),
      #1c1d1c 0%, #121312 45%, transparent 75%);
    background-repeat: no-repeat;
  }

  .hero__photo {
    /* Правый край — ровно по краю контента, как у всех секций. Вверх кадр
       по-прежнему уходит под шапку: логотип и меню лежат поверх него, это
       работает потому, что .topbar несёт z-index: 5, а .hero — auto. */
    right: var(--gutter);
    top: calc(-1 * var(--header-h));
    width: var(--photo-w);
    height: var(--photo-h);
    object-fit: cover;
    /* cover режет кадр по бокам. Прижимаем окно кадрирования ВПРАВО (100%):
       лицо и кисть живут в правой части снимка, и при центрировании они
       упирались в правый край бокса — тот самый «угол». Со сдвигом окна
       сюжет уезжает к середине бокса, а слева добавляется тёмный фон,
       по которому мягко ложится растушёвка. */
    object-position: 100% 50%;
    /* Маска в процентах (вместо мобильных px) — масштабонезависима и покрывает
       весь текучий диапазон одной декларацией; мобильная px-маска выше по файлу
       не трогается.
       СПРАВА растушёвка вернулась (86% -> прозрачность): кадр обязан гаснуть
       ровно на линии поля, а не обрываться по ней. Слева — 8%, снизу — с 82%
       (object-fit: cover режет кадр по прямой, без растушёвки низ читался бы
       как обрыв). Сверху не растворяем: там фото уходит за верхний край.
       Правая растушёвка связана с object-position: 100% — окно кадрирования
       прижато вправо, и лицо приходится на 62..76% ширины бокса, то есть
       ЛЕВЕЕ зоны затухания. Меняете одно — проверьте второе, иначе градиент
       начнёт съедать лицо.
       Обе группы, -webkit- и стандартная, правятся только вместе. */
    -webkit-mask-image:
      linear-gradient(to right, transparent 0, #000 8%, #000 86%, transparent),
      linear-gradient(to bottom, #000 0, #000 82%, transparent);
    -webkit-mask-composite: source-in;
    mask-image:
      linear-gradient(to right, transparent 0, #000 8%, #000 86%, transparent),
      linear-gradient(to bottom, #000 0, #000 82%, transparent);
    mask-composite: intersect;
  }

  .hero__title { padding: var(--hero-top) 0 0 var(--gutter); }
  /* Заголовок вырастает под широкий макет. ВНИМАНИЕ: слот home.hero.wordmark
     на проде отдаёт растр 222x131 (@1x), и на 340px он размывается — исходник
     «Крейзи маникюр 2x.png» (444x262) лежит в mobile_assets, но подключается
     только через медиатеку админки. До замены картинки держим 340px как
     компромисс: меньше — заголовок теряется в широком макете. */
  .hero__wordmark { width: var(--wordmark-w); }
  /* Отступы СЧИТАЮТСЯ ОТ --gutter, а не зашиты числом. Поле теперь текучее
     (40..120px), и прежние 67/45/35 — посчитанные под фиксированные 48 —
     выносили подзаголовок, кнопку и звезду ЛЕВЕЕ заголовка. Смещения взяты
     из мобильных: подзаголовок +19, кнопка -3, звезда -13 относительно поля. */
  .hero__sub {
    margin: 64px 0 0 calc(var(--gutter) + 19px);
    font-size: clamp(20px, 1.9vw, 30px);
  }

  /* Кнопка целиком крупнее (мобильные 186x70 малы для широкого экрана).
     Все четыре числа связаны и правятся ТОЛЬКО вместе: рамка Book_stroke.png
     нарисована со смещённым от центра холста овалом, и пилюля позиционируется
     внутрь неё вручную. Коэффициент 1.35 к мобильным: 186->251, 198->267,
     12/13->16/18, 162x44->219x59. Растр 200x68 при этом тянется до 267px
     (x1.34) и слегка мылит — это рукописная обводка, на ней не читается,
     но крупнее уже нельзя. */
  .cta-wrap {
    margin: 56px 0 0 calc(var(--gutter) - 3px);
    width: 251px; height: 94px;
  }
  .cta-frame { width: 267px; top: -1px; }
  .cta {
    left: 16px; top: 18px;
    width: 219px; height: 59px;
    padding: 0 26px;
    font-size: 18px;
    border-radius: 30px;
  }
  .cta__arrow { width: 20px; height: 20px; }
  .doodle--star-cta { right: -22px; bottom: 22px; width: 20px; }

  /* Звезда привязана к низу заголовка, а не к абсолютному числу: заголовок
     текучий, и с фиксированным top она повисала между ним и подзаголовком. */
  .doodle--star-left {
    left: calc(var(--gutter) - 13px);
    top: calc(var(--hero-top) + var(--wordmark-h) + 50px);
  }

  /* ---- заголовки секций ---- */

  .sec { margin-top: 64px; }
  /* #services — это (1,0,0) и правилом .sec не перебивается, повторяем явно. */
  #services { margin-top: 56px; }
  .sec__head { padding: 0 var(--gutter); }
  .sec__head h2, .steps__head h2 { font-size: 30px; }
  .sec__head .spark, .steps__head .spark { width: 34px; height: 34px; }
  .pill { height: 38px; padding: 0 20px; font-size: 15px; }

  /* ---- лента работ -> сетка ----
     Ячейка ровно 200px — родной размер плитки, апскейла нет.
     auto-fit (не auto-fill), чтобы укороченная из админки галерея осталась
     по центру. aspect-ratio 200/207 = 0.9662 против нынешних 114/118 = 0.9661:
     кадрирование object-fit: cover сохраняется. */
  /* 768..1159 — плитки переносятся. Одну линию здесь включать нельзя: при
     восьми фото ячейка выходит ~70px на 768px, то есть МЕЛЬЧЕ мобильной (114).
     Одна линия живёт в блоке min-width: 1160px ниже. */
  .rail--works {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
    overflow: visible;
    padding: 26px var(--gutter) 0;
  }
  .rail--works img {
    width: 100%; height: auto;
    aspect-ratio: 200 / 207;
  }
}

@media (min-width: 1024px) {
  .hero { --hero-top: 56px; }
  .sec__head h2, .steps__head h2 { font-size: 34px; }
}

/* ---- шапка в одну строку (макет владелицы) ----
   Ниже 1160 меню остаётся отдельной полосой под логотипом: там ему не хватает
   места рядом с логотипом, и оно переносилось бы на вторую строку внахлёст. */
@media (min-width: 1160px) {
  :root { --header-h: 112px; }


  /* position: relative на body — база для абсолютного меню. Стекающий контекст
     при z-index: auto НЕ создаётся, поэтому mix-blend-mode у .note__smile
     на странице услуг остаётся жив. */
  body { position: relative; }

  .topbar { padding-top: 30px; }
  /* Слоган скрыт: в макете его нет, а в одной строке он встал бы ровно под
     меню. Текст остаётся в разметке и в админке — вернуть можно одной строкой. */
  .topbar__tag { display: none; }

  /* Затемнение под шапкой. Здесь и только здесь фото заезжает наверх, и меню
     ложится прямо на кадр — на светлых участках (кожа, блики на ногтях) пункты
     сливались. Градиент живёт на ::before у .topbar: она уже несёт z-index: 5,
     то есть создаёт стекающий контекст, поэтому z-index: -1 кладёт плашку
     ПОД логотип, но всё ещё НАД фото (у него z-index 0 в корневом контексте).
     Меню с z-index: 6 тоже остаётся сверху.
     Высота больше самой шапки — затухание должно закончиться ниже неё,
     иначе видна граница. */
  .topbar::before {
    content: '';
    position: absolute; z-index: -1;
    left: 0; right: 0; top: 0;
    height: 230px;
    background: linear-gradient(to bottom,
      rgba(10, 11, 10, 0.92) 0%,
      rgba(10, 11, 10, 0.72) 40%,
      rgba(10, 11, 10, 0.32) 72%,
      transparent 100%);
    pointer-events: none;
  }

  .menu, .menu.open {
    position: absolute;
    top: 36px; left: 0; right: 0;
    padding: 0 var(--gutter);
    z-index: 6;
  }
  .menu__list { flex-wrap: nowrap; justify-content: flex-end; gap: 30px; }
  .menu__list .menu__tel { margin-left: 0; color: var(--ink); }

  /* Все работы В ОДНУ ЛИНИЮ (просьба владелицы). grid-auto-flow: column кладёт
     в один ряд любое их число, сколько бы ни пришло из админки, а
     minmax(0, 1fr) разрешает плиткам сжиматься ниже натуральной ширины — без
     нуля они упёрлись бы в 200px и снова переносились.
     Побочный плюс: при восьми фото ячейка ~140px на 1440, то есть картинка
     теперь УМЕНЬШАЕТСЯ (исходник 200px), а не растягивается — стало резче.
     Обратная сторона: чем больше фото, тем они мельче (восемь — предел
     читаемости на 1440; пять дали бы ~234px). */
  .rail--works {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
  }
}
/* == CRITICAL:END == */

/* ---------- десктоп, ниже сгиба (начало — блоком выше) ----------
   Без ограды: в инлайн не уезжает, приезжает с асинхронным mobile.css. */

@media (min-width: 768px) {
  /* ---- карточки услуг ----
     Ширина и высота растут ВМЕСТЕ: 232/160 = 1.45 против мобильных
     178/122 = 1.46. Это важно — clip-path у .scard__in задан 24 точками
     В ПРОЦЕНТАХ, и он искажается не от размера коробки, а от смены её
     пропорции. Тот же полигон уже живёт при 1.46 и при 0.96 (.perk),
     так что коридор [0.9, 1.5] проверен продом. Менять одно измерение,
     не трогая второе, нельзя.
     .scard остаются ПРЯМЫМИ детьми .rail--cards — на этом держится цикл
     обрывков бумаги :nth-child(4n+1..4n). */
  .rail--cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 30px 24px;
    overflow: visible;
    padding: 28px var(--gutter) 18px;
  }
  .scard { width: auto; }
  /* min-height растёт вместе с шириной: на 1440 карточка ~294px, и при 205px
     высоты отношение 1.43 — то же, что на мобильном (178/122 = 1.46).
     Процентный clip-path плывёт именно от смены пропорции, поэтому тянуть
     карточку только по ширине нельзя. */
  .scard__in { min-height: 205px; padding: 18px 20px 18px 24px; }
  .scard__in h3 { font-size: 18px; }
  .scard__in p { margin-top: 10px; font-size: 13.5px; }
  .scard__foot { padding-top: 16px; }
  .scard__price { font-size: 18px; }

  /* ---- как проходит запись -> 2x2 ----
     Разделитель li + li в горизонтальной сетке рисовался бы над правым
     элементом первого ряда. Заменяем на «граница у всех, снять у первого
     ряда»: двойка в -n+2 связана с числом колонок. Правило переживает
     изменение числа шагов из админки (data-cms-list="steps"). */
  .steps { margin-top: 26px; padding: 0 var(--gutter); }
  .steps__head h2 { max-width: 460px; }
  .steps__sticker { width: 300px; right: 0; top: -26px; }
  .steps__list {
    margin-top: 44px;
    display: grid; grid-template-columns: 1fr 1fr;
    column-gap: 56px;
  }
  .steps__list li,
  .steps__list li + li { border-top: 1px dashed rgba(255, 255, 255, 0.16); }
  .steps__list li:nth-child(-n + 2) { border-top: 0; }
  .steps__num { width: 52px; font-size: 25px; }
  .steps__list h3 { font-size: 17px; }
  .steps__list p { font-size: 14px; }

  /* .cta-wrap намеренно НЕ масштабируется ни на одной ширине: рамка
     Book_stroke.png — растр 200x68 и уже показывается в родном размере,
     любое увеличение даст мыло. */
  .cta-wrap--center { margin: 44px auto 0; }

  /* ---- футер -> три колонки ----
     .footer и так display: grid, это перешаблонивание. Явные номера строк
     безопасны: футер не data-cms-list, публикация его не переупорядочивает. */
  .footer {
    margin-top: 80px;
    padding: 28px var(--gutter) calc(40px + env(safe-area-inset-bottom));
    grid-template-columns: auto 1fr auto;
    column-gap: 48px; row-gap: 10px;
    align-items: start;
  }
  /* вылет привязан к --gutter — раньше 27px были прибиты в двух местах */
  .footer__tear {
    grid-column: 1 / -1;
    width: calc(100% + var(--gutter) * 2);
    margin: 0 calc(var(--gutter) * -1) 14px;
  }
  .footer__logo { width: 92px; }
  .footer__home { grid-column: 1; grid-row: 2 / span 3; }
  .footer__addr { grid-column: 2; grid-row: 2; }
  .footer__hours { grid-column: 2; grid-row: 3; }
  .footer__tel { grid-column: 2; grid-row: 4; }
  .footer__soc { grid-column: 3; grid-row: 2; margin-top: 0; }
  .footer__req { grid-column: 1 / -1; grid-row: 5; margin-top: 18px; max-width: 760px; }
  .footer__copy { grid-column: 1 / -1; grid-row: 6; }

  /* ---- политика конфиденциальности ----
     Стили .legal живут в собственном <style> внутри privacy.html, ПОСЛЕ
     mobile.css, поэтому при равной специфичности выигрывают они. Правку
     разметки это не требует: в ней <main class="legal">, так что
     main.legal (0,1,1) перебивает .legal (0,1,0), main.legal p (0,1,2)
     перебивает .legal p (0,1,1) и так далее. */
  main.legal {
    max-width: 820px; margin-inline: auto;
    padding: 16px var(--gutter) 0;
  }
  /* line-height задаём ЯВНО: в privacy.html заголовок описан шорткатом
     `font: 400 clamp(30px,10vw,40px)/1 var(--font-marker)`, то есть с
     межстрочным 1. Одна правка font-size его не трогает, и на 44px хвосты
     граффити-глифов налезают на строку с датой. (На мобильном они тоже
     касаются её — дефект не наш и там не трогается: мобильный рендер обязан
     остаться прежним. Стоит починить отдельной правкой.) */
  main.legal .legal__title { font-size: 44px; line-height: 1.12; margin-bottom: 16px; }
  main.legal .legal__meta { font-size: 13.5px; }
  main.legal h2 { font-size: 17px; margin-top: 28px; }
  main.legal p, main.legal li { font-size: 15px; line-height: 1.7; }
  main.legal .legal__op { padding: 18px 20px; font-size: 14px; }
}

/* Шаги в одну строку, как в макете. Четвёрка в -n+4 — снова число колонок:
   при четырёх шагах пунктиров не остаётся вовсе (в макете их и нет), а если
   из админки добавят пятый — он ляжет во второй ряд уже с разделителем. */
@media (min-width: 1280px) {
  .steps__list { grid-template-columns: repeat(4, 1fr); column-gap: 36px; }
  .steps__list li:nth-child(-n + 4) { border-top: 0; }
}
