/* Собрано build.js. Не правьте этот файл — правьте themes/ и modules/. */
@font-face{font-family:'Raleway';font-style:normal;font-weight:400 800;font-display:swap;src:url(fonts/raleway-cyr.woff2) format('woff2');unicode-range:U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}
@font-face{font-family:'Raleway';font-style:normal;font-weight:400 800;font-display:swap;src:url(fonts/raleway-cyr.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}
@font-face{font-family:'Raleway';font-style:normal;font-weight:400 800;font-display:swap;src:url(fonts/raleway-lat.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:'Raleway';font-style:normal;font-weight:400 800;font-display:swap;src:url(fonts/raleway-lat.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;}
/* Собрано build.js из config.js → theme. Правьте конфиг, не этот файл. */
:root{
  --bg:#F7FDF7;
  --paper:#FFFFFF;
  --ink:#303531;
  --ink2:#535853;
  --ink3:#707671;
  --line:#DBE2DC;
  --line2:#909691;
  --accent:#7A9E7E;
  --on-accent:#303531;
  --accent-d:#5F8363;
  --soft:#DFECE0;
  --softer:#EFF6EF;
  --second:#467748;
  --second-l:#DDF2DD;
  --gold:#BD8630;
  --radius:24px;
  --nav-h:76px;
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-t:env(safe-area-inset-top,0px);
  --sans:'Raleway',-apple-system,'Segoe UI',system-ui,sans-serif;
  --serif:'Georgia','Times New Roman',serif;
  --body:var(--sans);
  --logo:url(logo.svg);
  /* Украшения нет — маска должна быть прозрачной картинкой, а не none.
     С none маска отключается совсем, и элемент .euc ложится поверх баннера
     сплошным светлым прямоугольником. */
  --decor:linear-gradient(#0000,#0000);
  --decor-size:132px;
}

/* ═══ themes/base.css ═══ */
/* Основа: сброс, типографика, карточки, кнопки, поля, списки, кабинет.

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

/* ── Производные токены ──────────────────────────────────────────
   Основные цвета и --radius приходят из config.js → theme. Здесь только
   то, что считается от них: три радиуса вместо одного и тени, окрашенные
   в цвет чернил заведения. Серая тень на тёплом фоне выглядит грязью. */
:root{
  --r-lg:calc(var(--radius) + 4px);
  --r-md:calc(var(--radius) - 3px);
  --r-sm:calc(var(--radius) - 7px);
  --sh-1:0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent);
  --sh-2:0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
         0 10px 26px -12px color-mix(in srgb,var(--ink) 26%,transparent);
  --sh-3:0 2px 6px color-mix(in srgb,var(--ink) 6%,transparent),
         0 20px 44px -20px color-mix(in srgb,var(--ink) 34%,transparent);
  --pad:20px;
  --pad-card:18px;

  /* Ручки, за которые дёргают атмосферы (см. конец файла).
     Всё остальное считает себя от них само. */
  --btn-pad:17px 20px;
  --btn-fs:16px;
  --rise:.34s;
  --card-line:0px solid transparent;

  /* Кнопка красится фирменным цветом в полную силу, а текст на ней
     подбирает сборка: белый или чернила — что даёт больше контраста
     (--on-accent). Раньше ядро всегда брало белый, и ради контраста
     приходилось гасить сам цвет заведения: яркий оранжевый под белым
     даёт 2,6:1, поэтому кнопка уезжала в кирпич. Тёмные чернила на том
     же оранжевом дают 6,3:1 — и ярко, и читаемо. */
  --accent-btn:linear-gradient(165deg,
               color-mix(in srgb,var(--accent) 93%,#fff),
               color-mix(in srgb,var(--accent) 88%,var(--accent-d)));

  /* Текстовые ступени серого. --ink2 и --ink3 из конфига остаются на
     линиях, заливках значков и всём нетекстовом: как текст они дают
     4,3:1 и 2,3:1 — ниже нормы оба. Эти выведены из тех же чернил,
     поэтому теплота палитры клиента не теряется. */
  --tx-2:color-mix(in srgb,var(--ink) 82%,var(--bg));
  --tx-3:color-mix(in srgb,var(--ink) 72%,var(--bg));
  --accent-t:color-mix(in srgb,var(--ink) 10%,var(--accent-d));
  --second-t:color-mix(in srgb,var(--ink) 40%,var(--second));
}

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
/* Отскок страницы за край выключаем именно на html, а не только на body:
   на body свойство до самого окна не доходит, и на айфоне страница
   продолжала оттягиваться за верхний край. Вместе с ней уезжала вверх
   и нижняя панель — она приклеена к окну, а не к странице. */
html{scroll-behavior:smooth;overscroll-behavior-y:none;}
html,body{height:100%;}
body{
  font-family:var(--body);   /* serif или sans — задаётся в config.js → theme.bodyFont */
  background:var(--bg);color:var(--ink);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overscroll-behavior-y:none;
  font-size:16px;line-height:1.5;letter-spacing:-.006em;
  /* У переменного шрифта есть все веса — синтезировать наклон и жир нечем
     и незачем. Табличные цифры включаются точечно, ниже: на всём тексте
     они шире пропорциональных и разбивают ритм строки. */
  font-synthesis:none;
}
/* Цифры, которые меняются на месте и должны стоять колонкой */
.price,.srv .pr,.day b,.bonus .n,.statrow b,.time,.nav .badge,.stat,.qrlink{
  font-variant-numeric:tabular-nums;}
button,input,textarea,select{font-family:var(--sans);font-size:16px;color:inherit;background:none;border:none;}
button{cursor:pointer;}
a{color:inherit;text-decoration:none;}
img{display:block;max-width:100%;}
/* Без своего цвета выделение стирает текст на всех тёмных блоках:
   белые буквы оказываются на кремовом фоне, 1,06:1. */
::selection{background:var(--soft);color:var(--ink);}

/* ── Фокус ───────────────────────────────────────────────────────
   Родное кольцо было сбито глобальным outline:none — значит клавиатура,
   внешняя клавиатура на айпаде и Switch Control не показывали вообще
   ничего. Возвращаем, но только :focus-visible: от пальца кольцо
   не появляется, от клавиатуры появляется всегда. */
/* tabindex="-1" исключён намеренно: роутер ставит фокус на заголовок
   экрана, чтобы диктор прочитал, куда человек попал. Кольцо вокруг
   заголовка при этом рисовать не надо — человек туда не переходил. */
:where(a,button,input,select,textarea,[tabindex]:not([tabindex="-1"])):focus-visible{
  outline:3px solid var(--ink);outline-offset:3px;border-radius:6px;}
#app h1:focus,#app h1:focus-visible{outline:none;}
.banner :focus-visible,.btn.dark:focus-visible,.nav .tab.core:focus-visible .ring{
  outline:3px solid #fff;outline-offset:3px;}
.check input:focus-visible + .box{outline:3px solid var(--ink);outline-offset:3px;}
@media(forced-colors:active){
  :where(a,button,input,select,textarea):focus-visible{outline-color:Highlight;}}

/* Только для диктора: видимого места не занимает, но читается вслух */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;}
/* Ошибка под конкретным полем. Всплывашка — для глаз, эта строка — чтобы
   человек понял, какое именно поле не приняли, и услышал это диктором. */
.ferr{font-size:12.5px;font-weight:600;color:var(--accent-t);margin-top:6px;
  font-family:var(--sans);}
.inp[aria-invalid="true"]{border-color:var(--accent-d);background:var(--paper);}
.toast.err{background:var(--accent-d);}
svg.i{flex:0 0 auto;vertical-align:middle;}

#app{min-height:100%;padding-bottom:calc(var(--nav-h) + var(--safe-b) + 8px);}
.screen{padding:calc(var(--safe-t) + 14px) var(--pad) 34px;max-width:760px;margin:0 auto;
  animation:fade .22s ease;}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
/* Тот же экран, перерисованный на месте, — не новый экран. Без этого
   каждый тап по времени, дню или чипсу перемигивал всю страницу:
   роутер пересоздаёт #app целиком, и анимация входа стартовала заново. */
#app.same .screen{animation:none;}

/* ── Типографика ─────────────────────────────────────────────────
   Заголовок держится на весе и на тесноте: 700 и отрицательный трекинг.
   Раньше h1 стоял четырёхсотым — заголовок ничем не отличался от текста,
   и экран выглядел сплошной серой простынёй. */
h1{font-size:clamp(27px,7.6vw,33px);line-height:1.06;font-weight:700;
  letter-spacing:-.032em;text-wrap:balance;font-family:var(--sans);}
h2{font-size:20px;line-height:1.15;font-weight:700;letter-spacing:-.024em;
  text-wrap:balance;font-family:var(--sans);}
h3{font-size:16px;font-weight:700;letter-spacing:-.018em;font-family:var(--sans);}
p,.lead,.small,.tiny,.hint,.li .t span{text-wrap:pretty;}
.sans{font-family:var(--sans);}
.lead{font-size:15px;color:var(--ink2);font-family:var(--sans);line-height:1.5;
  letter-spacing:-.004em;}
.dim{color:var(--ink2);} .dim2{color:var(--ink3);}
.small{font-size:13.5px;font-family:var(--sans);line-height:1.45;}
.tiny{font-size:12px;font-family:var(--sans);line-height:1.45;}
.center{text-align:center;} .tleft{text-align:left;} .bold{font-weight:700;}
.strike{text-decoration:line-through;}
.w100{width:100%;}
.ell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;}
.mt4{margin-top:4px}.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}
.mt20{margin-top:20px}.mt24{margin-top:24px}.mt28{margin-top:30px}.mt36{margin-top:40px}
.pad36{padding:38px var(--pad-card);}
button.link{background:none;}
.link{font-size:13.5px;font-family:var(--sans);font-weight:600;color:var(--accent-t);
  text-decoration:underline;text-decoration-thickness:from-font;
  text-underline-offset:.22em;text-decoration-skip-ink:auto;
  /* Ссылка-кнопка («Все мастера») жила высотой в 16 точек: попасть
     пальцем можно только прицелившись. Отступы вокруг текста дают
     нормальную мишень, а на вид ничего не меняется — фон прозрачный.
     Отрицательные поля возвращают её на прежнее место в строке. */
  padding:9px 6px;margin:-9px -6px;}
.price{font-size:25px;font-weight:800;font-family:var(--sans);letter-spacing:-.03em;}

.sechead{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-bottom:14px;}
/* Надзаголовок секции. Он не должен спорить с заголовком — поэтому мелкий,
   разряженный и в третьей ступени серого. */
.eyebrow{font-family:var(--sans);font-size:11px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink3);}
.eyebrow.light{color:rgba(255,255,255,.6);}

/* Шапка: знак заведения плюс дескриптор — это фирменный блок */
.apphead{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;
  padding-top:4px;}
.lockup{display:flex;align-items:center;gap:12px;min-width:0;}
.logo{display:block;width:150px;max-width:100%;height:52px;flex:0 0 auto;background:var(--ink);
  -webkit-mask:var(--logo) no-repeat left center/contain;
  mask:var(--logo) no-repeat left center/contain;}
.descr{font-family:var(--sans);font-size:10px;line-height:1.4;letter-spacing:.1em;
  font-weight:600;text-transform:uppercase;color:var(--ink3);padding-left:12px;
  border-left:1px solid var(--line2);}
.pill{display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:50%;flex:0 0 auto;margin-top:6px;
  background:var(--paper);color:var(--tx-2);box-shadow:var(--sh-1);}

/* ── Карточки ────────────────────────────────────────────────────
   Три ступени, и это единственное, чем блоки отличаются друг от друга:
   .card       — то, ради чего экран открыли: белое, с тенью;
   .card.flat  — фон, без тени: справка, сноска, подложка;
   .card.note  — тёплая заливка: подсказка, на которую надо посмотреть.
   Рамок нет нигде. Рамка вокруг каждого блока — то, от чего интерфейс
   становится похож на бланк. */
.card{background:var(--paper);border-radius:var(--r-lg);padding:var(--pad-card);
  box-shadow:var(--sh-2);border:var(--card-line);}
.card.flat{background:color-mix(in srgb,var(--ink) 4%,var(--bg));box-shadow:none;}
.card.note{background:var(--softer);box-shadow:none;}
.card.accentcard{background:linear-gradient(150deg,color-mix(in srgb,var(--accent) 13%,var(--paper)),color-mix(in srgb,var(--gold) 8%,var(--paper)));
  box-shadow:none;}
button.card{display:block;width:100%;text-align:left;font-family:var(--body);
  transition:transform .12s,box-shadow .12s;}
button.card:active{transform:scale(.98);}
.chev{color:var(--tx-3);transform:rotate(180deg);display:flex;}
/* Плашка статуса прижата к первой строке: по центру двухстрочного
   названия она повисает в пустоте между строк. */
.between > .stat{align-self:flex-start;margin-top:1px;}

/* ── Баннер главной ──────────────────────────────────────────────
   Первый экран красится фирменным цветом в полную силу, а не гасится
   до тёмного. Тёмная плашка выглядела дорого и ровно настолько же
   безрадостно — для салона, куда приводят собаку, это не тот тон.
   Текст на баннере — те же чернила, что и на кнопке: 6,3:1. */
.banner{border-radius:var(--r-lg);color:var(--on-accent);
  padding:calc(var(--pad-card) + 10px) var(--pad-card) calc(var(--pad-card) + 8px);
  background:
    radial-gradient(90% 70% at 8% 4%,color-mix(in srgb,var(--gold) 78%,transparent) 0%,transparent 58%),
    radial-gradient(85% 75% at 100% 100%,color-mix(in srgb,var(--accent) 60%,var(--accent-d)) 0%,transparent 62%),
    linear-gradient(150deg,color-mix(in srgb,var(--accent) 92%,#fff),var(--accent));
  box-shadow:0 14px 34px -16px color-mix(in srgb,var(--accent) 85%,transparent);}
/* На баннере текст лежит поверх рисунка, а не на чистом фоне — значит
   ему нужен вес больше обычного. 800 против 700 и плотный лид держат
   строку читаемой, не заставляя гасить сам рисунок до невидимости. */
.banner h1{font-size:clamp(28px,8vw,35px);color:var(--on-accent);
  letter-spacing:-.036em;font-weight:800;
  text-shadow:0 1px 0 color-mix(in srgb,var(--on-accent) 8%,transparent);}
.banner .lead{color:color-mix(in srgb,var(--on-accent) 86%,transparent);
  font-weight:500;}
/* Кнопка внутри баннера — контрастная плашка чернил: белая на светлом
   оранжевом растворяется, а тёмная читается с любого расстояния. */
.banner .btn{background:var(--ink);color:var(--paper);
  box-shadow:0 10px 24px -12px rgba(0,0,0,.55);}

/* ── Кнопки ──────────────────────────────────────────────────────
   Главная кнопка — заливка с уходом в тёмный край: чистый светлый
   коралл под белым текстом даёт контраст на грани читаемости. */
.btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  padding:var(--btn-pad);border-radius:var(--r-md);font-size:var(--btn-fs);font-weight:700;
  letter-spacing:-.014em;font-family:var(--sans);
  background:var(--accent-btn);color:var(--on-accent);
  box-shadow:0 10px 22px -10px color-mix(in srgb,var(--accent) 75%,transparent);
  transition:transform .12s,opacity .12s,box-shadow .12s;}
.btn:active{transform:scale(.96);box-shadow:none;}
.btn[disabled]{opacity:.4;pointer-events:none;box-shadow:none;
  background:color-mix(in srgb,var(--ink) 12%,var(--bg));color:var(--ink2);}
/* Светлая кнопка лежит и на фоне, и на белой карточке. На белом одна
   только тень её не показывает — нужен волосяной контур. */
.btn.ghost{background:var(--paper);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--line2),var(--sh-1);}
.btn.soft{background:color-mix(in srgb,var(--accent) 11%,var(--paper));color:var(--accent-d);
  box-shadow:none;}
.btn.dark{background:var(--ink);color:#fff;box-shadow:var(--sh-2);}
.btn.small{padding:11px 16px;font-size:13.5px;border-radius:var(--r-sm);width:auto;gap:6px;}
/* Маленькая светлая кнопка чаще всего лежит на белой карточке — контур
   ей нужен даже сильнее, чем большой. */
.btn.ghost.small{box-shadow:inset 0 0 0 1px var(--line2);}
.btn.small:not(.ghost){box-shadow:none;}

.row{display:flex;gap:10px;} .row.wrap{flex-wrap:wrap;}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
.row2 > *{min-width:0;}
.row2 > .btn{width:100%;}
.between{display:flex;align-items:center;justify-content:space-between;gap:12px;}
.grow{flex:1;min-width:0;}

/* Ряд с горизонтальной прокруткой: акции в каталоге и мастера на главной
   каркаса «Запись». Лежит здесь, а не в модуле каталога, потому что
   в салоне каталога нет, а ряд мастеров есть — иначе карточки
   разъезжаются в столбик во всю ширину.
   scroll-padding обязателен: со «снапом» браузер подтягивает первую
   карточку к самому краю и левый отступ пропадает. */
.hrow{display:flex;gap:12px;overflow-x:auto;
  margin-left:calc(var(--pad) * -1);margin-right:calc(var(--pad) * -1);
  padding:4px var(--pad) 12px;scroll-snap-type:x proximity;
  scroll-padding-left:var(--pad);scroll-padding-right:var(--pad);
  scrollbar-width:none;-webkit-overflow-scrolling:touch;}
.hrow::-webkit-scrollbar{display:none;}

/* ── Поля ввода ──────────────────────────────────────────────────
   Поле — вдавленное, а не обведённое: заливка чуть темнее бумаги
   и волосяная линия. Так форма читается как форма, а не как таблица. */
label.f{display:block;margin-top:14px;}
label.f.nomt{margin-top:0;}
label.f > span{display:block;font-size:12px;font-weight:600;color:var(--ink2);
  margin-bottom:6px;font-family:var(--sans);}
.inp{width:100%;min-width:0;max-width:100%;
  background:color-mix(in srgb,var(--ink) 4%,var(--bg));
  border:1px solid transparent;border-radius:var(--r-md);
  padding:15px 15px;font-size:16px;transition:border-color .15s,background .15s,box-shadow .15s;}
/* Родное поле даты в Safari тянется по своему содержимому и центрирует текст */
input[type="date"].inp{-webkit-appearance:none;appearance:none;text-align:left;
  min-height:54px;display:block;}
input[type="date"].inp::-webkit-date-and-time-value{text-align:left;margin:0;}
.inp:focus{border-color:var(--accent);background:var(--paper);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 14%,transparent);}
.card .inp{background:color-mix(in srgb,var(--ink) 4%,var(--bg));}
select.inp{appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236E6165' stroke-width='1.8' stroke-linecap='round'><path d='M4 6.5 8 10.5 12 6.5'/></svg>");
  background-repeat:no-repeat;background-position:right 14px center;padding-right:38px;}
textarea.inp{min-height:88px;resize:vertical;line-height:1.45;}
.hint{font-size:12px;color:var(--ink3);margin-top:8px;font-family:var(--sans);line-height:1.45;}

/* Свой чекбокс — родной на айфоне выглядит инородно */
.check{display:flex;align-items:flex-start;gap:11px;cursor:pointer;}
.check input{position:absolute;opacity:0;width:0;height:0;}
.check .box{width:23px;height:23px;border-radius:max(4px,calc(var(--radius) - 10px));border:1.5px solid var(--line2);
  background:var(--paper);display:flex;align-items:center;justify-content:center;
  color:transparent;flex:0 0 auto;transition:.15s;margin-top:1px;}
.check input:checked + .box{background:var(--accent);border-color:var(--accent);color:var(--on-accent);}

/* ── Чипсы ───────────────────────────────────────────────────────
   Были padding 9px 9px — слово упиралось в края, и ряд читался как
   склеенная гармошка. Воздух по бокам решает половину вопроса. */
.scroller{margin-left:calc(var(--pad) * -1);margin-right:calc(var(--pad) * -1);
  padding:0 var(--pad);overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;}
.scroller::-webkit-scrollbar{display:none;}
/* Отступы сверху и снизу — не для красоты: ряд лежит в overflow-x,
   и без них свечение выбранной плитки срезается ровно по её краю. */
.chips{display:flex;gap:7px;width:max-content;padding:6px 0 12px;}
.chiprows{display:flex;flex-direction:column;gap:7px;width:max-content;padding:6px 0 12px;}
.chip{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;
  padding:12px 16px;border-radius:999px;
  background:var(--paper);font-size:13.5px;font-weight:600;font-family:var(--sans);
  white-space:nowrap;color:var(--ink2);box-shadow:var(--sh-1);transition:.15s;}
.chip.on{background:var(--ink);color:#fff;box-shadow:var(--sh-2);}

.sortbox{display:inline-flex;align-items:center;gap:6px;color:var(--ink2);
  font-family:var(--sans);font-size:13.5px;}
.sortbox select{appearance:none;font-size:13.5px;color:var(--ink);font-weight:700;
  padding-right:2px;}

/* ── Строки списков ─────────────────────────────────────────────
   Разделитель — не сплошная линия во всю ширину, а линия с отступом
   под значок: список читается столбиком, а не решёткой. */
.li{display:flex;gap:13px;align-items:center;padding:13px 0;position:relative;}
.li + .li::before{content:'';position:absolute;left:53px;right:0;top:0;height:1px;
  background:var(--line);}
.li:first-child{padding-top:2px;}
.li:last-child{padding-bottom:2px;}
.e{width:40px;height:40px;border-radius:max(6px,calc(var(--radius) - 5px));background:var(--softer);display:flex;
  align-items:center;justify-content:center;color:var(--accent-d);flex:0 0 auto;}
.e.second{background:var(--second-l);color:var(--second);}
.e.num{font-family:var(--sans);font-size:15px;font-weight:800;}
.bige{display:inline-flex;width:66px;height:66px;border-radius:max(10px,calc(var(--radius) + 4px));background:var(--softer);
  align-items:center;justify-content:center;color:var(--accent-d);}
.ok{color:var(--second);font-weight:700;}
.li .t{flex:1;min-width:0;}
.li .t b{display:block;font-size:15px;font-weight:700;letter-spacing:-.015em;
  font-family:var(--sans);}
/* Жирные подписи наследовали 1.5 от body и рыхлились на двух строках */
.bold.sans,.li .t b,.rowbtn .t{line-height:1.25;}
.li .t span{display:block;font-size:13px;color:var(--ink2);font-family:var(--sans);margin-top:3px;
  line-height:1.4;}
/* Значок остаётся 16px, а палец должен попадать по 44. Отрицательные
   поля не дают строке подрасти от этого. */
.x{color:var(--tx-3);display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;padding:0;margin:-10px -10px -10px 0;}

/* Липкая нижняя панель действия */
.stickypad{height:100px;}
.sticky{position:fixed;left:0;right:0;bottom:calc(var(--nav-h) + var(--safe-b));z-index:30;
  padding:14px var(--pad) 16px;background:color-mix(in srgb,var(--bg) 94%,transparent);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);}
.sticky::before{content:'';position:absolute;left:0;right:0;top:-26px;height:26px;
  background:linear-gradient(180deg,color-mix(in srgb,var(--bg) 0%,transparent),color-mix(in srgb,var(--bg) 94%,transparent));
  pointer-events:none;}
.sticky .in{max-width:760px;margin:0 auto;}

/* Подсказка — сверху, чтобы не закрывать кнопку внизу */
.toast{position:fixed;top:calc(var(--safe-t) + 12px);left:50%;
  transform:translate(-50%,-140%);opacity:0;transition:transform .25s cubic-bezier(.2,.9,.3,1.2),opacity .25s;
  display:flex;align-items:center;gap:9px;
  background:var(--ink);color:#fff;padding:13px 18px;border-radius:var(--r-md);
  font-size:14px;font-weight:700;z-index:99;max-width:calc(100% - 32px);
  font-family:var(--sans);box-shadow:var(--sh-3);}
.toast.in{transform:translate(-50%,0);opacity:1;}
.toast .ti{display:flex;opacity:.7;}

/* Шапка экрана с кнопкой назад */
.top{display:flex;align-items:center;gap:12px;}
.back{width:44px;height:44px;border-radius:50%;background:var(--paper);
  display:flex;align-items:center;justify-content:center;flex:0 0 auto;color:var(--tx-2);
  box-shadow:var(--sh-1);}
.back.liked{color:var(--accent);}

.okmark{display:inline-flex;width:82px;height:82px;border-radius:50%;background:var(--second-l);
  align-items:center;justify-content:center;color:var(--second);margin-top:24px;}

.seg{display:flex;background:color-mix(in srgb,var(--ink) 6%,var(--bg));
  border-radius:var(--r-md);padding:4px;gap:4px;}
.seg button{flex:1;padding:11px 8px;border-radius:calc(var(--r-md) - 4px);font-size:14px;
  font-weight:700;color:var(--ink2);transition:.15s;
  /* На узком экране (320 точек — это айфон SE, их ещё много) три
     кнопки не помещались и выталкивали страницу вбок. Разрешаем
     тексту переноситься и ужиматься, вместо того чтобы ломать экран. */
  min-width:0;overflow-wrap:anywhere;}
@media (max-width:360px){ .seg button{font-size:13px;padding:10px 5px;} }
.seg button.on{background:var(--paper);color:var(--ink);box-shadow:var(--sh-1);}

/* ── Отклик на нажатие ───────────────────────────────────────────
   Системная подсветка отключена глобально (-webkit-tap-highlight-color),
   поэтому каждая цель нажатия обязана отвечать сама. Два значения на всё
   ядро: 0.96 — кнопки и плитки, 0.98 — карточка во всю ширину, там 0.96
   читается как прыжок. */
.chip,.back,.pill{transition:transform .12s ease,box-shadow .15s ease;}
.chip:active,.back:active,.pill:active{transform:scale(.96);}
.srv,.rowbtn{transition:opacity .12s ease;}
.srv:active,.rowbtn:active{opacity:.55;}

/* Меньше движения. 0.01ms, а не none: события transitionend должны
   продолжать срабатывать, иначе ждущий их код виснет навсегда. */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;}
  html{scroll-behavior:auto;}
}
/* Человек попросил в системе больше контраста — отдаём границы вместо теней */
@media(prefers-contrast:more){
  .card,.chip,.day,.time,.inp,.btn.ghost{box-shadow:none;outline:1px solid var(--line2);}
}
/* Высокий контраст Windows и Android: цвета отдаём системе целиком */
@media(forced-colors:active){
  .card,.chip,.day,.time{border:1px solid CanvasText;}
  .day.on,.time.on,.chip.on{forced-color-adjust:none;background:Highlight;color:HighlightText;}
  .nav{border-top:1px solid CanvasText;}
}

/* Строка-кнопка в настройках: значок, подпись, значение справа */
.rowbtn{display:flex;align-items:center;gap:13px;width:100%;padding:12px 0;
  text-align:left;font-family:var(--sans);position:relative;}
.rowbtn + .rowbtn::before{content:'';position:absolute;left:53px;right:0;top:0;height:1px;
  background:var(--line);}
.rowbtn .t{flex:1;font-size:15px;font-weight:700;letter-spacing:-.015em;}
.rowbtn .val{font-size:13.5px;color:var(--ink3);}
.rowbtn .chev{transform:rotate(180deg);display:flex;color:var(--ink3);}
.e.white{background:var(--paper);}
.card.note .e{background:var(--paper);}

/* ---------- Кабинет мастерской ---------- */
.seg.small4 button{padding:10px 4px;font-size:12.5px;}
/* Пять вкладок в кабинете: ужимаем, чтобы влезли без прокрутки */
.seg.small5{padding:3px;gap:2px;}
.seg.small5 button{padding:10px 2px;font-size:11.5px;border-radius:max(4px,calc(var(--r-md) - 3px));}
/* В кабинете нет нижней навигации — освобождаем место */
body:has(#nav[style*="none"]) #app{padding-bottom:24px;}
.stat{font-family:var(--sans);font-size:11.5px;font-weight:800;padding:5px 11px;
  border-radius:999px;background:var(--softer);color:var(--accent-d);white-space:nowrap;
  letter-spacing:.01em;}
.stat.st-собираем{background:#FDF0DF;color:#96682A;}
.stat.st-в{background:#E9EFF6;color:#3F6392;}
.stat[class*="доставлен"]{background:var(--second-l);color:var(--second);}
.stat[class*="отмен"]{background:#F1EDEE;color:var(--ink3);}
.statrow{display:flex;gap:10px;}
.statrow > div{flex:1;background:color-mix(in srgb,var(--ink) 4%,var(--bg));
  border-radius:var(--r-md);padding:13px 14px;}
.statrow b{display:block;font-family:var(--sans);font-size:21px;font-weight:800;
  line-height:1.15;letter-spacing:-.03em;}
.statrow span{display:block;font-family:var(--sans);font-size:11.5px;color:var(--ink3);margin-top:3px;}
/* Номер сборки — заодно вход в кабинет. Для клиента это просто подпись. */
.build{cursor:pointer;padding:10px 12px;min-height:44px;font-family:var(--sans);}
.fl{display:block;font-size:12px;color:var(--ink2);font-family:var(--sans);}

.chip.flat{background:transparent;box-shadow:none;color:var(--ink3);
  padding-left:0;padding-right:6px;gap:5px;}

.btn.small.w100{width:100%;}

/* ── QR-код на стойку ─────────────────────────────────────────
   Белое поле вокруг кода обязательно: без него камера не читает. */
.qrbox{display:flex;justify-content:center;}
.qrbox img{width:232px;height:232px;display:block;border-radius:var(--r-sm);
  background:#fff;image-rendering:pixelated;box-shadow:var(--sh-1);}
.qrlink{word-break:break-all;color:var(--ink2);font-family:var(--sans);font-size:13px;}

/* Печать: на бумагу уходит только карточка с кодом и адресом. */
@media print{
  #nav,.top,.chips,.scroller,.noprint,.toast{display:none !important;}
  body,#app{background:#fff;padding:0;}
  .card{box-shadow:none;border:none;}
  .qrcard{page-break-inside:avoid;text-align:center;}
  .qrbox img{width:60mm;height:60mm;border:none;box-shadow:none;}
}

/* ── «Вышла свежая версия» ─────────────────────────────────────
   Полоска поверх всего, но выше нижней навигации, чтобы не закрывать
   вкладки. Её можно закрыть — тогда до следующего запуска не мешает. */
.newver{position:fixed;left:12px;right:12px;z-index:60;
  bottom:calc(var(--nav-h) + var(--safe-b) + 12px);
  display:flex;align-items:center;gap:10px;
  padding:10px 10px 10px 15px;border-radius:var(--r-md);
  background:var(--ink);color:#fff;font-family:var(--sans);font-size:13px;
  box-shadow:var(--sh-3);}
.newver span{flex:1;line-height:1.35;}
.newver .btn{width:auto;flex:none;}
.newver .x{background:none;border:none;color:#fff;opacity:.6;padding:4px;cursor:pointer;}
body:has(#nav[style*="none"]) .newver{bottom:calc(var(--safe-b) + 12px);}

/* ── Цвет текста ────────────────────────────────────────────────
   Замеры на фоне #FBF8F5 для палитры Dog House:
   --ink3 #ADA49C — 2,32:1, --ink2 #7D746D — 4,32:1, --accent-d — 4,40:1,
   --second на своей подложке — 2,79:1. Ниже AA всё, вплоть до порога 3:1
   для значков. Третья ступень серого не должна выражаться более светлым
   серым — на неё работают размер, капитель и вес, а цвет держит норму. */
.dim,.lead,.chip,.sortbox,.seg button,.qrlink,.fl,.li .t span,
label.f > span{color:var(--tx-2);}
.dim2,.eyebrow,.descr,.hint,.chev,.x,.statrow span,.chip.flat,
.rowbtn .val,.rowbtn .chev,.stat[class*="отмен"]{color:var(--tx-3);}
.btn.soft,.stat,.e,.bige,.back.liked{color:var(--accent-t);}
.ok,.e.second,.okmark,.stat[class*="доставлен"]{color:var(--second-t);}
/* На тёмных блоках цвет задан прозрачностью — она была занижена:
   надзаголовок давал 5,3:1. Баннер больше не тёмный, поэтому его лид
   красится чернилами и живёт в правиле выше — здесь только карточка
   баллов, она тёмной и осталась. */
.eyebrow.light{color:rgba(255,255,255,.78);}
.nw{white-space:nowrap;}

/* ── Свой цвет мастера ───────────────────────────────────────────
   Плашка и буква приходят инлайном в --tint / --tint-ink: считает их
   ядро от порядкового номера мастера, а не конфиг руками. Тона нет —
   всё падает обратно на фирменные цвета, и ничего не ломается. */
.e.tinted{background:var(--tint,var(--softer));color:var(--tint-ink,var(--accent-t));}
.card .stat{background:var(--tint,var(--softer));color:var(--tint-ink,var(--accent-t));}

/* Заголовок группы услуг: значок и подпись на одной линии */
.grouphead{display:flex;align-items:center;gap:8px;}
.grouphead .gi{display:flex;color:var(--accent-t);}

/* ── Иллюстрации ─────────────────────────────────────────────────
   Общее для всех картинок: ширина по месту, высота по пропорции.
   height:auto обязателен — в разметке высота проставлена в пикселях,
   чтобы браузер заранее знал, сколько места отвести, а показать её
   надо всё равно по ширине контейнера. */
.doneart img,.emptyart img,.gtile img{width:100%;height:auto;display:block;}
.doneart{max-width:min(62vw,260px);margin:8px auto 0;}
.emptyart{max-width:min(46vw,190px);margin:0 auto;}

/* Салют на экране «вы записались» */
/* Размер холста задаём и в пикселях, и в стилях. Без стилей браузер
   рисует холст в его «родных» пикселях: при плотности экрана 2 это
   вдвое больше окна. Салют тогда уезжал вправо и вниз — на экране
   оставался только левый верхний угол картинки. */
.confetti{position:fixed;inset:0;width:100%;height:100%;z-index:70;pointer-events:none;}

/* ── Витрина групп над прайсом ──────────────────────────────────
   Четыре плитки в ряд: больше не влезает на узкий телефон, меньше —
   и ряд перестаёт читаться как оглавление. */
.gtiles{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
.gtile{display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:10px 4px 9px;border-radius:var(--r-md);background:var(--paper);
  box-shadow:var(--sh-1);font-family:var(--sans);transition:transform .12s ease;}
.gtile:active{transform:scale(.95);}
.gtile img{max-width:56px;}
.gtile span{font-size:10.5px;font-weight:700;letter-spacing:-.01em;
  color:var(--tx-2);text-align:center;line-height:1.15;}

/* Место фото, когда фотографии нет: значок на подложке вместо битой
   рамки. Размер задаёт то место, куда картинку вставили. */
.bige.nophoto{width:100%;height:100%;border-radius:0;background:var(--softer);
  align-items:center;justify-content:center;}

/* ── Кружки прогресса: штампы и остаток абонемента ──────────────
   Жили в каркасе «Магазин», пока их не понадобилось показать
   в «Записи» — та же история, что была с рядом прокрутки .hrow.
   Место такого — здесь: это не витрина, а счётчик, и он нужен
   везде, где человек копит к награде. */
.stamp{width:11px;height:11px;border-radius:50%;flex:none;
  border:1.5px solid var(--line2);}
.stamp.on{background:var(--accent);border-color:var(--accent);}

/* ── Картинка и украшение в баннере ─────────────────────────────
   Блок banner живёт в ядре и общий для всех каркасов, а стили его
   картинки лежали только в каркасе «Запись». В магазине и у эксперта
   первое же положенное в brand/ фото выходило в натуральный размер
   и разваливало баннер. Место таких стилей — здесь, рядом с блоком. */
.banner .herobox{position:absolute;right:-6px;bottom:-6px;width:44%;
  max-width:190px;pointer-events:none;}
.banner .heroart{width:100%;height:auto;display:block;}
/* Украшение-накладка: маска из --decor, задаётся в config.js → theme.
   Нет украшения — маска прозрачная, элемент не виден. */
.banner .euc{position:absolute;right:10px;top:10px;width:var(--decor-size);
  height:var(--decor-size);opacity:.14;pointer-events:none;
  background:currentColor;-webkit-mask:var(--decor) no-repeat center/contain;
  mask:var(--decor) no-repeat center/contain;}

/* ── Живая обложка ──────────────────────────────────────────────
   Два режима. С фото: текст светлый на нижнем затемнении. Без фото:
   мягкий градиент из палитры бренда, текст чернилами. Плашка статуса
   («Барсик записан на субботу») читается на обоих — полупрозрачная
   бумага с размытием. */
.hero{position:relative;border-radius:var(--r-lg);overflow:hidden;min-height:264px;
  display:flex;align-items:flex-end;box-shadow:var(--sh-2);}
.hero .heroimg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}
.heromesh{position:absolute;inset:0;background:
  radial-gradient(at 14% 18%, color-mix(in srgb,var(--accent) 24%,var(--softer)) 0px, transparent 55%),
  radial-gradient(at 86% 8%,  color-mix(in srgb,var(--second) 18%,var(--softer)) 0px, transparent 50%),
  radial-gradient(at 50% 96%, color-mix(in srgb,var(--accent) 34%,var(--soft)) 0px, transparent 60%),
  var(--softer);}
.hero .herotxt{position:relative;width:100%;padding:26px var(--pad-card) var(--pad-card);}
.hero.withimg .herotxt{background:linear-gradient(180deg,transparent,
  color-mix(in srgb,var(--ink) 62%,transparent) 72%);color:#fff;}
.hero.withimg .herotxt .lead{color:color-mix(in srgb,#fff 88%,transparent);}
.herostat{display:inline-flex;align-items:center;gap:8px;max-width:100%;
  padding:10px 13px;border-radius:13px;font-weight:600;font-size:14.5px;
  font-family:var(--sans);color:var(--ink);text-align:left;
  background:color-mix(in srgb,var(--paper) 86%,transparent);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  box-shadow:var(--sh-1);}
.herostat span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.btn.big{width:100%;padding:16px 22px;font-size:17px;}

/* ── Появление экрана ───────────────────────────────────────────
   Мягкий подъём блоков с лёгкой лесенкой. Глобальный блок
   prefers-reduced-motion выше гасит и это. */
@keyframes riseIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.screen>*{animation:riseIn var(--rise) ease backwards;}
.screen>*:nth-child(2){animation-delay:.05s}
.screen>*:nth-child(3){animation-delay:.09s}
.screen>*:nth-child(4){animation-delay:.13s}
.screen>*:nth-child(5){animation-delay:.16s}
.screen>*:nth-child(n+6){animation-delay:.19s}

/* ── Вау-финал знакомства и тёплая шапка профиля ───────────────── */
.wow{display:flex;align-items:center;gap:14px;text-align:left;
  padding:14px 16px;border-radius:var(--r-md);
  background:color-mix(in srgb,var(--accent) 10%,var(--paper));
  border:1px dashed color-mix(in srgb,var(--accent) 45%,transparent);}
.wowsum{font-size:30px;font-weight:800;font-family:var(--sans);
  letter-spacing:-.03em;color:var(--accent-t);flex:none;}
.wowtxt{font-size:13.5px;font-family:var(--sans);line-height:1.4;color:var(--tx-2);}
.pfhi{font-family:var(--sans);font-size:15px;color:var(--tx-2);margin-top:4px;}

/* ── Атмосферы ───────────────────────────────────────────────────
   Характер поверх облика. Облик отвечает на вопрос «какого мы
   цвета и каким шрифтом говорим», атмосфера — «как мы себя ведём»:
   плотность, скругления, скорость появления, вес теней.
   Класс ставит сборка: config.js → theme.atmosphere → body.atm-*.

   Четыре характера под ниши первой волны:
   · cozy      — кондитеры, цветы, подарки. Крупные тёплые карточки,
                 больше округлости, тени как крем — заметные и мягкие.
   · premium   — психологи, эксперты. Минимализм и воздух: больше
                 отступов, спокойнее углы, вместо теней — тонкая
                 линия, появление неторопливое.
   · cute      — груминг, всё про животных. Крупные кнопки, самые
                 круглые углы, отклик быстрый и дружелюбный.
   · education — курсы и школы. Структурнее: плотнее, углы строже,
                 карточка очерчена линией, анимации короткие.

   Ориентир зафиксирован в oblik.mjs: Wildberries / Pinterest /
   Instagram, не Битрикс. Атмосфера не трогает фирменный цвет
   и шрифты — это территория облика.                              */

body.atm-cozy{
  --pad-card:22px;
  --r-lg:calc(var(--radius) + 8px);
  --r-md:calc(var(--radius) + 1px);
  --rise:.44s;
  --sh-2:0 2px 3px color-mix(in srgb,var(--ink) 4%,transparent),
         0 16px 36px -14px color-mix(in srgb,var(--ink) 30%,transparent);
}
body.atm-premium{
  --pad:24px;
  --pad-card:24px;
  --r-lg:calc(var(--radius) - 5px);
  --r-md:calc(var(--radius) - 8px);
  --rise:.5s;
  --sh-2:none;
  --card-line:1px solid var(--line);
}
body.atm-premium h1{letter-spacing:-.025em;}
body.atm-cute{
  --btn-pad:19px 22px;
  --btn-fs:17px;
  --r-lg:calc(var(--radius) + 10px);
  --r-md:calc(var(--radius) + 5px);
  --rise:.28s;
}
body.atm-cute .chip{padding:11px 16px;}
body.atm-education{
  --pad-card:16px;
  --r-lg:calc(var(--radius) - 3px);
  --r-md:calc(var(--radius) - 6px);
  --rise:.26s;
  --sh-2:var(--sh-1);
  --card-line:1px solid var(--line);
}

/* ── Отзывы на главной ───────────────────────────────────────────
   Цитаты клиенток, отобранные Хозяйкой в кабинете. Кавычка крупно,
   имя приглушённо: главное — живые слова, а не оформление. */
.rev{position:relative;padding-top:calc(var(--pad-card) + 14px);}
.rev::before{content:'“';position:absolute;top:2px;left:var(--pad-card);
  font-family:var(--serif);font-size:46px;line-height:1;
  color:color-mix(in srgb,var(--accent) 55%,transparent);}
.rev p{font-size:15px;line-height:1.55;}
.rev .who{margin-top:10px;font-family:var(--sans);font-size:12.5px;
  font-weight:600;color:var(--tx-2);}

/* ── Частые вопросы ──────────────────────────────────────────────
   Родные details/summary: работают без единой строки кода. */
.faq details{border-bottom:1px solid var(--line);}
.faq details:last-child{border-bottom:none;}
.faq summary{list-style:none;cursor:pointer;display:flex;gap:10px;
  align-items:center;justify-content:space-between;
  padding:14px 2px;font-family:var(--sans);font-weight:600;font-size:14.5px;}
.faq summary::-webkit-details-marker{display:none;}
.faq summary::after{content:'+';flex:none;font-size:20px;font-weight:400;
  color:var(--tx-3);transition:transform .18s;}
.faq details[open] summary::after{transform:rotate(45deg);}
.faq .a{padding:0 2px 14px;font-size:14px;line-height:1.55;color:var(--tx-2);}


/* ═══ themes/nav.css ═══ */
/* Нижняя навигация.

   Центральная кнопка — единственный элемент интерфейса, который выпирает
   за пределы панели, поэтому ей нужен вырез: кольцо цветом фона вокруг
   круга. Без него кнопка выглядит кляксой, наехавшей на полоску. */

/* Свой слой: панель с размытием фона айфон рисует отдельно от страницы,
   и без явного слоя во время инерционной прокрутки она успевает
   съехать вместе с содержимым. */
.nav{position:fixed;left:0;right:0;bottom:0;z-index:40;
  transform:translateZ(0);
  /* min-height, а не height: при системном шрифте в 200% подписи
     перестают влезать в фиксированные 76 пикселей. */
  min-height:calc(var(--nav-h) + var(--safe-b));padding-bottom:var(--safe-b);
  background:color-mix(in srgb,var(--paper) 88%,transparent);
  backdrop-filter:blur(20px) saturate(1.5);-webkit-backdrop-filter:blur(20px) saturate(1.5);
  box-shadow:0 -1px 0 var(--line),0 -12px 30px -22px color-mix(in srgb,var(--ink) 60%,transparent);
  display:flex;justify-content:space-around;}

.nav .tab{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;
  padding-top:12px;padding-bottom:8px;font-size:10px;font-weight:600;letter-spacing:.005em;
  color:var(--tx-3);font-family:var(--sans);transition:color .15s;}
.nav .tab .i{transition:transform .18s cubic-bezier(.2,.9,.3,1.3);}
.nav .tab.on,.nav .tab[aria-current="page"]{color:var(--accent-t);}
.nav .tab.on .i{transform:translateY(-1px) scale(1.06);}

/* Центральная кнопка.
   Геометрия здесь считается, а не подбирается. Подпись у обычной вкладки
   начинается на 12 + 22 + 5 = 39 пикселях от верха панели. Чтобы подпись
   центральной встала на ту же линию, кольцо должно занимать в потоке
   ровно 22 пикселя — столько же, сколько значок. Отсюда 50 − 28 = 22:
   размер кольца минус подъём. Раньше −20px стояли на самой вкладке,
   вверх уезжал весь столбец, и подпись сидела на 14 пикселей ниже
   соседних — это было видно на любом снимке. */
.nav .tab.core{margin-top:0;gap:5px;color:var(--tx-2);}
.nav .tab.core.on{color:var(--accent-t);}
.nav .tab.core .ring{width:50px;height:50px;border-radius:50%;
  margin-top:-28px;
  background:var(--accent-btn);
  display:flex;align-items:center;justify-content:center;position:relative;
  color:var(--on-accent);
  box-shadow:0 10px 22px -8px color-mix(in srgb,var(--accent) 85%,transparent),
             0 0 0 6px color-mix(in srgb,var(--paper) 88%,transparent);
  transition:transform .15s;}
.nav .tab.core:active .ring{transform:scale(.96);}

.nav .badge{position:absolute;top:-4px;right:-4px;background:var(--ink);color:#fff;
  min-width:21px;height:21px;border-radius:11px;font-size:11px;font-weight:800;
  display:flex;align-items:center;justify-content:center;padding:0 5px;
  box-shadow:0 0 0 2px var(--paper);}


/* ═══ core/onboard.css ═══ */
/* ЗНАКОМСТВО. Экраны первого запуска.

   Правило вёрстки здесь одно: кнопка всегда внизу, картинка всегда
   вверху, а всё, что между ними, растягивается. Так четыре разных
   по объёму шага выглядят одним движением, а палец не ищет кнопку
   каждый раз в новом месте. */

.onb{display:flex;flex-direction:column;min-height:100svh;text-align:center;
  padding-bottom:0;}
/* Кнопка прилипает к низу окна. На маленьком экране шаг с питомцем
   не влезает целиком, и без этого «дальше» оказывается за краем:
   человек видит форму, не видит выхода из неё и решает, что застрял. */
.onbfoot{position:sticky;bottom:0;z-index:2;background:var(--bg);
  padding-bottom:calc(var(--safe-b) + 10px);}
.onbfoot::before{content:'';position:absolute;left:0;right:0;top:-20px;height:20px;
  pointer-events:none;
  background:linear-gradient(color-mix(in srgb,var(--bg) 0%,transparent),var(--bg));}
.onb > .onbgrow{flex:1 1 auto;min-height:14px;}
/* Нижней навигации на этих экранах нет — значит и запаса под неё
   быть не должно, иначе под кнопкой висит пустая полоса. */
body.nonav #app{padding-bottom:0;}

.onb .onbtop{display:flex;align-items:center;justify-content:space-between;
  min-height:38px;flex-direction:row-reverse;}
.onbdots{display:flex;gap:6px;align-items:center;}
.onbdots i{width:7px;height:7px;border-radius:99px;background:var(--line2);
  transition:width .22s ease,background .22s ease;}
.onbdots i.on{width:22px;background:var(--accent);}

/* Круг под картинкой. Он же спасает те иллюстрации, у которых фон
   не прозрачный: круг обрезает угол и рисунок перестаёт быть
   наклейкой на странице. */
.onbart{margin:10px auto 0;width:min(58vw,214px);aspect-ratio:1/1;border-radius:50%;
  background:var(--softer);display:flex;align-items:center;justify-content:center;
  overflow:hidden;flex:0 0 auto;}
.onbart img{width:88%;height:88%;object-fit:contain;}
/* Там, где под картинкой стоит форма, круг меньше: иначе кнопка
   «дальше» уезжает за нижний край и человек её не находит. */
.onb.form .onbart{width:min(42vw,152px);margin-top:4px;}
.onb.form h1{margin-top:14px;}
/* Низкий экран: круг сжимается, чтобы форма начиналась выше. Картинка
   здесь не главное — главное, чтобы поле и кнопка были видны сразу. */
@media (max-height:700px){
  .onb.form .onbart{width:min(32vw,116px);}
  .onb.form h1{margin-top:10px;font-size:25px;}
  .onb.form .lead{font-size:14px;}
}
.onb h1{text-align:center;}
.onb .lead{text-align:center;margin-left:auto;margin-right:auto;max-width:34ch;}
.onb .card{text-align:left;}
.onb .btn + .btn{margin-top:10px;}

/* Третья по важности кнопка: не заливка и не рамка, а просто текст.
   Выход должен быть виден, но не спорить с основным действием. */
.btn.flat{background:transparent;box-shadow:none;color:var(--ink3);font-weight:600;}
.btn.flat:active{transform:scale(.98);}

/* Поля-группы внутри знакомства размечены не подписью, а блоком —
   у чипсов и мордочек нет одного поля, на которое можно указать. */
.onb div.f{display:block;margin-top:14px;}
.onb div.f > span{display:block;font-size:12px;font-weight:600;color:var(--ink2);
  margin-bottom:6px;font-family:var(--sans);}

/* Мордочки: тот же набор, что и у мастеров. Своя морда делает карточку
   питомца узнаваемой в списке с одного взгляда. */
.faces{display:flex;flex-wrap:wrap;gap:6px;}
.face{width:46px;height:46px;border-radius:var(--r-md);background:var(--softer);
  display:flex;align-items:center;justify-content:center;color:var(--accent-d);
  border:2px solid transparent;transition:transform .12s ease,border-color .15s;}
.face:active{transform:scale(.94);}
.face.on{border-color:var(--accent);background:var(--paper);box-shadow:var(--sh-2);}

/* Карточка питомца в списке: морда вместо значка-сердечка. */
.li .pet{display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:50%;background:var(--softer);color:var(--accent-d);
  flex:0 0 auto;}


/* ═══ frames/booking/home.css ═══ */
/* Главная каркаса «Запись»: украшение баннера и карточка мастера. */

/* Фирменный мотив на баннере. Не картинка, а маска: цвет берётся от
   темы, поэтому один и тот же файл работает в любой палитре и весит
   пару сотен байт. Размер плитки задаётся в config.js → theme.decorSize;
   украшения нет — маска прозрачная, и блок просто не виден. */
/* Обрезки у самой плашки нет: уши собаки выходят за верхний край, и это
   нарочно. Всё, что обрезать надо — низ рисунка и скруглённые углы, —
   обрезает отдельная рамка .herobox, а узор .euc держит свои углы сам. */
.banner{position:relative;overflow:visible;}
/* Рисунок уходит из-под текста. Две маски, наложенные пересечением:
   первая — сами следы, вторая — наклонный градиент, прозрачный там, где
   лежит заголовок. Следы остаются на своих местах, но в левом верхнем
   углу их нет, и строка читается по чистому. */
.euc{position:absolute;inset:0;pointer-events:none;z-index:0;
  border-radius:inherit;overflow:hidden;
  color:var(--on-accent);opacity:.13;background:currentColor;
  -webkit-mask-image:var(--decor),linear-gradient(122deg,#0000 0%,#0000 34%,#000 82%);
  mask-image:var(--decor),linear-gradient(122deg,#0000 0%,#0000 34%,#000 82%);
  -webkit-mask-repeat:repeat,no-repeat; mask-repeat:repeat,no-repeat;
  -webkit-mask-size:var(--decor-size,132px),100% 100%;
  mask-size:var(--decor-size,132px),100% 100%;
  -webkit-mask-composite:source-in; mask-composite:intersect;}
.banner > *:not(.euc):not(.herobox){position:relative;z-index:1;}

/* Карточка мастера в ряду на главной. Инициал крупный: пока студия
   не дала фотографии, буква и есть портрет — она должна выглядеть
   решением, а не заглушкой. */
.mcard{flex:0 0 124px;scroll-snap-align:start;background:var(--paper);
  border-radius:var(--r-md);overflow:hidden;box-shadow:var(--sh-2);
  display:flex;flex-direction:column;text-align:left;font-family:var(--sans);
  transition:transform .14s;}
.mcard:active{transform:scale(.975);}
/* Пока студия не дала фотографии, буква и есть портрет — значит она
   должна выглядеть решением, а не заглушкой. Свой тон делает мастера
   узнаваемым: через два визита человек ищет глазами «зелёного»,
   а не читает имена. */
.mcard .ph{position:relative;aspect-ratio:1/1;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  background:var(--tint,var(--softer));}
.mcard .ph::after{content:'';position:absolute;inset:0;
  background:linear-gradient(160deg,rgba(255,255,255,.55),transparent 62%);}
.mcard .ph img{width:100%;height:100%;object-fit:cover;}
.mcard .ph .ini{position:relative;z-index:1;display:flex;
  color:var(--tint-fur,var(--ink));}
.mcard .ph .pf{display:block;filter:drop-shadow(0 3px 6px rgba(0,0,0,.14));}
/* Карточки чуть шире: морда должна читаться, а не угадываться */
.mcard{flex:0 0 132px;}
.mcard .b{padding:11px 12px 13px;display:flex;flex-direction:column;gap:3px;}
.mcard .nm{font-size:14px;font-weight:700;letter-spacing:-.015em;}
.mcard .ro{font-size:11.5px;color:var(--ink3);line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}

/* Герой на баннере. Картинка нарисована так, что собака сидит справа,
   а слева пусто под заголовок, — поэтому кладём её слоем во всю
   плашку и прижимаем к правому краю. Прозрачная часть пропускает
   фирменный оранжевый, который остаётся фоном баннера. */
/* Плашка должна быть заметно шире, чем выше: квадрат читается как
   картинка, а не как первый экран. Поэтому поля и промежутки внутри
   плотнее обычной карточки, а минимальная высота — только страховка
   на случай очень короткого текста. */
/* Отступ сверху больше обычного: там, где у других экранов просто воздух,
   здесь стоят уши. Без запаса они наезжают на шапку. */
.banner.mt16{margin-top:22px;}
.banner{min-height:236px;display:flex;flex-direction:column;
  align-items:flex-start;justify-content:center;
  padding:18px var(--pad-card) 14px;}
.banner .lead{margin-top:6px;font-size:13.5px;line-height:1.5;}
.banner .mt20{margin-top:10px;}

/* Размер собаки задаёт ширина, а не высота плашки. Это и есть причина,
   по которой уши вылезают наверх: рисунок выше плашки, значит верх
   торчит, а низ уходит под нижний край. Привяжись размер к высоте —
   собака дышала бы вместе с текстом и то раздувалась, то съёживалась. */
.herobox{position:absolute;left:0;right:0;bottom:0;top:-30px;
  overflow:hidden;border-radius:var(--r-lg);pointer-events:none;z-index:0;}
/* Правый край рисунка нарочно уведён за границу плашки. Собака
   нарисована с запасом пушистого бока; если её не подрезать, силуэт
   выходит слишком далеко влево и упирается в заголовок. */
/* Потолок высоты — не украшение, а предохранитель: размер задан шириной,
   и на широком экране собака иначе вырастала бы выше рамки и упиралась
   в шапку. Дойдя до потолка, она перестаёт расти и просто отходит правее,
   освобождая ещё немного места тексту. */
.banner .heroart{position:absolute;right:-12%;bottom:-2px;left:auto;top:auto;
  width:60%;height:auto;max-height:calc(100% + 26px);
  object-fit:contain;object-position:right bottom;}
/* Кнопка на баннере — по содержимому, а не во всю ширину: во всю ширину
   она перекрывала собаку и оставляла от неё одни уши. */
.banner .btn{width:auto;padding:13px 30px;}
/* Текст держится левее собаки. Заголовок мельче обычного не из вкуса,
   а по замеру: при прежнем кегле строка «Ваш питомец» доходила до уха.
   Ширина лида ограничена и в долях, и в пикселях — доля одна для всех
   экранов, а строка текста везде одной длины, и на узком экране только
   пиксельный предел не даёт ей рассыпаться на лишние строки. */
.banner h1{max-width:66%;font-size:clamp(24px,7.2vw,34px);line-height:1.02;}
.banner .lead{max-width:min(56%,170px);}
.banner .btn{position:relative;z-index:1;}

/* ── Мой мастер: та же карточка, но одна и крупнее ──────────────
   Фото меньше, чем в ряду мастеров: здесь важно не разглядывать,
   а узнать. Кнопка «к нему» справа, чтобы палец шёл сразу к ней. */
.ph.sm{width:48px;height:48px;border-radius:50%;overflow:hidden;flex:none;
  display:grid;place-items:center;background:var(--softer);}
.ph.sm img{width:100%;height:100%;object-fit:cover;}


/* ═══ modules/bonus/bonus.css ═══ */
/* Карточка баллов.

   Единственный блок в приложении, который заявляет «здесь ваши деньги»,
   поэтому он тёмный и с крупной цифрой. Всё остальное вокруг — светлое,
   и карточка читается первой, куда бы её ни поставили. */

.bonus{position:relative;overflow:hidden;color:#fff;border-radius:var(--r-lg);
  padding:24px 22px 22px;
  background:
    radial-gradient(95% 80% at 98% -8%,color-mix(in srgb,var(--accent) 90%,transparent) 0%,transparent 56%),
    radial-gradient(80% 70% at -6% 106%,color-mix(in srgb,var(--gold) 42%,transparent) 0%,transparent 58%),
    linear-gradient(155deg,color-mix(in srgb,var(--ink) 88%,#000),var(--ink));
  box-shadow:var(--sh-3);}
/* Тот же мотив следов, что на баннере: один знак, повторённый дважды,
   запоминается, а два разных украшения — нет. */
.bonus::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:#fff;opacity:.075;
  -webkit-mask-image:var(--decor),linear-gradient(122deg,#0000 0%,#0000 30%,#000 80%);
  mask-image:var(--decor),linear-gradient(122deg,#0000 0%,#0000 30%,#000 80%);
  -webkit-mask-repeat:repeat,no-repeat; mask-repeat:repeat,no-repeat;
  -webkit-mask-size:var(--decor-size,132px),100% 100%;
  mask-size:var(--decor-size,132px),100% 100%;
  -webkit-mask-composite:source-in; mask-composite:intersect;}
.bonus > *{position:relative;z-index:1;}
.bonus .n{font-size:48px;font-weight:800;font-family:var(--sans);line-height:.95;
  letter-spacing:-.045em;}
.bonus .bar{height:7px;background:rgba(255,255,255,.16);border-radius:99px;
  margin-top:16px;overflow:hidden;}
.bonus .bar i{display:block;height:100%;border-radius:99px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--gold) 70%,#fff),#fff);
  box-shadow:0 0 12px rgba(255,255,255,.45);}
.op8{opacity:.82;} .op9{opacity:.92;}


/* ═══ modules/booking/booking.css ═══ */
/* Запись: строка услуги, полоса дней, сетка времени. */

/* Строка услуги: слева что делаем, справа сколько стоит.
   Цена — самое тяжёлое в строке: человек в прайсе сначала находит цифру,
   а уже потом читает название. */
.srv{display:flex;align-items:flex-start;gap:12px;width:100%;text-align:left;
  padding:14px 0;font-family:var(--sans);position:relative;}
.srv + .srv::before{content:'';position:absolute;left:0;right:0;top:0;height:1px;
  background:var(--line);}
.srv:first-child{padding-top:2px;}
.srv:last-child{padding-bottom:2px;}
.srv .t{flex:1;min-width:0;}
.srv .t b{display:block;font-size:15px;font-weight:700;letter-spacing:-.015em;line-height:1.25;}
.srv .t span{display:block;font-size:13px;color:var(--tx-2);margin-top:3px;line-height:1.4;}
.srv .t .dur{color:var(--tx-3);font-size:12px;font-weight:600;}
/* Цена держится вверху строки, а не по центру описания: иначе у длинного
   описания цифра уезжает на середину и колонка цен перестаёт быть колонкой. */
.srv .p{display:flex;align-items:center;gap:6px;flex:0 0 auto;padding-top:1px;}
/* Описание — две строки. Полный текст человек читает на экране записи,
   а в прайсе ему нужно сравнить строки между собой. */
.srv .t span:not(.dur){display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;}
.srv .t .dur{margin-top:6px;}
.srv .pr{font-size:15px;font-weight:800;white-space:nowrap;letter-spacing:-.02em;}

/* Полоса дней. Цифра снизу — сколько свободных окон в этот день:
   видно сразу, куда есть смысл смотреть. */
.daychips{gap:8px;}
.day{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:3px;
  min-width:58px;padding:10px 8px 8px;border-radius:var(--r-md);
  background:var(--paper);font-family:var(--sans);box-shadow:var(--sh-1);
  color:var(--tx-3);transition:transform .12s ease,box-shadow .15s ease;}
.day .w{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;}
.day b{font-size:19px;font-weight:800;line-height:1.05;color:var(--ink);letter-spacing:-.03em;}
.day .n{font-size:10.5px;font-weight:600;color:var(--tx-3);}
/* Выбор отмечен не только заливкой: внутреннее белое кольцо остаётся
   видимым и при высоком контрасте, и при дальтонизме. */
.day.on{background:var(--accent-btn);color:var(--on-accent);
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--on-accent) 45%,transparent),
             0 8px 18px -10px color-mix(in srgb,var(--accent) 90%,transparent);}
.day.on b,.day.on .n,.day.on .w{color:var(--on-accent);}

/* Сетка времени. Четыре в ряд — попадает пальцем и влезает на экран. */
.times{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
@media(min-width:520px){.times{grid-template-columns:repeat(6,1fr);}}
.time{padding:13px 4px;border-radius:var(--r-sm);
  background:var(--paper);font-family:var(--sans);font-size:15px;font-weight:700;
  letter-spacing:-.02em;color:var(--ink);box-shadow:var(--sh-1);
  transition:transform .12s ease,box-shadow .15s ease;}
.time.on{background:var(--accent-btn);color:var(--on-accent);
  box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--on-accent) 45%,transparent),
             0 8px 18px -10px color-mix(in srgb,var(--accent) 90%,transparent);}
.day:active,.time:active{transform:scale(.96);}

/* Мастер сегодня не работает — значок гасим, чтобы список читался глазами */
.e.off{background:color-mix(in srgb,var(--ink) 5%,var(--bg));color:var(--tx-3);}

/* Статусы записи в кабинете и в «моих визитах» */
.stat[class*="отмен"]{background:color-mix(in srgb,var(--ink) 6%,var(--bg));color:var(--tx-3);}
.stat[class*="пришёл"]{background:var(--second-l);color:var(--second-t);}
.stat[class*="не пришёл"]{background:#F1EDEE;color:var(--tx-3);}

/* Кличка питомца в строке визита. Эмодзи здесь стояло цветное и чужое —
   в наборе значков есть своя лапа той же толщины линии. */
.petline{display:flex;align-items:center;gap:7px;}
.petline .i{color:var(--tx-3);flex:0 0 auto;}

/* День без единого свободного окна. Раньше такие дни просто исчезали
   из полосы, и человек не мог отличить «закрыто» от «всё занято». */
.day[disabled]{opacity:.5;box-shadow:none;background:transparent;pointer-events:none;}
.day[disabled] b{color:var(--tx-3);}

/* Адрес салона строкой в карточке визита. Кликается — открывает карты:
   человеку нужен маршрут, а не строка, которую надо переписывать руками. */
.addrline{display:flex;align-items:center;gap:6px;color:var(--tx-2);}
.addrline .i{color:var(--tx-3);flex:0 0 auto;}
.tright{text-align:right;}

/* ── Выбор мастера ───────────────────────────────────────────────
   Две в ряд: карточка должна быть крупной, чтобы морда и роль читались,
   но список из семи человек обязан помещаться на один-два экрана. */
.mgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.mtile{display:flex;flex-direction:column;align-items:center;gap:10px;
  padding:16px 12px 15px;border-radius:var(--r-lg);background:var(--paper);
  box-shadow:var(--sh-2);text-align:center;font-family:var(--sans);
  transition:transform .14s;}
.mtile:active{transform:scale(.97);}
.mtile .ph{display:flex;align-items:center;justify-content:center;
  width:78px;height:78px;border-radius:50%;flex:0 0 auto;overflow:hidden;
  background:var(--tint,var(--softer));color:var(--tint-fur,var(--ink));}
.mtile .ph img{width:100%;height:100%;object-fit:cover;}
.mtile .t{display:flex;flex-direction:column;gap:3px;min-width:0;width:100%;}
.mtile .t b{font-size:15px;font-weight:700;letter-spacing:-.015em;}
.mtile .t span{font-size:12px;color:var(--tx-2);line-height:1.35;}
.mtile .ad{display:flex;align-items:center;justify-content:center;gap:4px;
  color:var(--tx-3);font-size:11.5px;}
.mtile .ad .i{flex:0 0 auto;}

/* Плашка «записываетесь к такому-то» над прайсом */
.chosen{display:flex;align-items:center;gap:12px;}
.chosen .ph{display:flex;align-items:center;justify-content:center;
  width:52px;height:52px;border-radius:50%;flex:0 0 auto;overflow:hidden;
  background:var(--tint,var(--paper));color:var(--tint-fur,var(--ink));}
.chosen .ph img{width:100%;height:100%;object-fit:cover;}
