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

@font-face{font-family:'Inter';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
/* latin-ext подключён ради одного знака: рубль (U+20BD) живёт именно здесь,
   и без этого файла все цены показывались квадратиком. */
@font-face{font-family:'Inter';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,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:'Inter';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('fonts/inter-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212,U+FEFF,U+FFFD}

:root{
  --brand:#8A4549; --brand-deep:#5A2A2D; --brand-soft:#EDECEB; --brand-lite:#A84E53;
  --cta:#7F3539; --cta-deep:#6E2E32;
  --page:#F0E9E1; --card:#FFFFFF; --tint:#F6F5F4; --line:#DFDDD9; --line-2:#CCC8C2;
  --ink:#27191A; --soft:#543E3F; --mute:#6B5455; --line-strong:#8F7677;
  --warn:#B26B12; --bad:#B3261E;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;
  --r-sm:10px; --r:14px; --r-lg:20px; --pill:999px;
  /* Три слоя, а не один: контактная тень под краем, мягкая на отлёте и
     светлая линия сверху. Без неё карточка выглядит наклейкой. */
  --sh-1:0 1px 1px rgba(36,28,29,.05),0 2px 6px rgba(36,28,29,.06),0 12px 28px rgba(36,28,29,.07);
  --sh-lift:0 2px 4px rgba(36,28,29,.07),0 10px 22px rgba(36,28,29,.10),0 24px 48px rgba(36,28,29,.08);
  --sh-2:0 2px 4px rgba(57,39,40,.24),0 8px 18px rgba(57,39,40,.28);
  --edge:inset 0 1px 0 rgba(255,255,255,.9);
  --bar-h:64px;
  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;height:100%}
/* Цвет страницы держит html, а не body: при перетягивании за край экрана
   виден именно он, и без этого из-под страницы проглядывала белая полоса. */
html{background:var(--page)}

/* Подложка фона отдельным закреплённым слоем.

   Раньше градиент лежал на body с background-attachment:fixed — и уезжал
   вместе с прокруткой: вебвью на iOS это свойство игнорирует, и ниже первого
   экрана страница становилась плоской заливкой. Закреплённый элемент такой
   болезни не имеет и всегда закрывает ровно видимую область. */
html::before{content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(1000px 420px at 82% -12%,#E8E8E7,transparent 60%),
             linear-gradient(180deg,#E7E6E5,var(--page) 42%)}
body{
  font-family:var(--font);color:var(--ink);font-size:15px;line-height:1.45;letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  background:transparent;
  overscroll-behavior-y:none;
}

/* Виньетка по краям: без неё светлый фон и белая карточка сливаются в одно
   молочное пятно, и никакая тень уже не спасает. */
body::after{content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(120% 80% at 50% 30%,transparent 45%,rgba(49,39,40,.10) 100%)}

/* Зерно поверх фона. Рисуется фильтром, а не файлом: пара сотен байт против
   запроса за картинкой, и не мылится на плотных экранах. Без него плоская
   заливка читается как «сделано по шаблону». */
/* Базовый слой — только мелкое зерно. Оно даёт материал, но ни за что не
   цепляет взгляд и не спорит с текстом. */
/* Базовый слой — только мелкое зерно. Оно даёт материал, но ни за что не
   цепляет взгляд и не спорит с текстом. */
body::before{content:'';position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.13;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size:160px 160px;
  mix-blend-mode:multiply}

/* Травинок больше нет: это была прямая деталь лугового оформления Кузи.
   Главная берёт тот же мелкий шум, что и остальные вкладки. */
/* Хребет на дне страницы. Рисуется один раз и стоит на месте: в мини-аппе
   фон прокручивается вместе с содержимым, и «живая» трава при каждом свайпе
   отвлекала бы от цифр. */
/* Стоит НАД нижним баром: за баром его попросту не видно. Маска сверху
   растворяет хребет в бумаге — получается дымка, как на снимке в шапке. */
.ridge{position:fixed;left:0;right:0;bottom:calc(var(--bar-h) + env(safe-area-inset-bottom) - 14px);
  height:200px;z-index:0;pointer-events:none;
  opacity:.62;mask-image:linear-gradient(180deg,transparent,#000 42%)}
.ridge svg{display:block;width:100%;height:100%}

.app{position:relative;z-index:1;max-width:460px;margin:0 auto;
  padding:calc(env(safe-area-inset-top) + 6px) 16px
          calc(var(--bar-h) + env(safe-area-inset-bottom) + 14px)}

/* ─────────────────────────── шапка */
.top{display:flex;align-items:center;gap:10px;padding:2px 2px 0}
.top .ava{position:relative;width:38px;height:38px;border-radius:50%;flex:0 0 auto;overflow:hidden;
  background:linear-gradient(135deg,#A04C51,#5A2A2D);color:#fff;
  display:grid;place-items:center;font-weight:800;font-size:15px;
  box-shadow:0 1px 3px rgba(36,28,29,.28),inset 0 0 0 1px rgba(255,255,255,.35)}
.top .ava img{width:100%;height:100%;object-fit:cover;display:block}
.top .who{min-width:0}
.top .who b{display:block;font-size:16px;font-weight:800;color:var(--brand-deep);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.top .who span{display:block;font-size:12px;color:var(--mute)}
.top .sp{flex:1}
.top a.sup{height:34px;padding:0 13px;border-radius:var(--pill);display:inline-flex;align-items:center;gap:7px;
  color:var(--brand-deep);background:#fff;border:1px solid var(--line-2);text-decoration:none;
  font-size:13px;font-weight:800;box-shadow:0 1px 3px rgba(44,37,37,.06)}
.top a.sup:active{transform:translateY(1px)}

/* ─────────────────────────── карточки */
.card{position:relative;background:linear-gradient(180deg,#fff,#FBFBFB);
  border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-1),var(--edge);padding:13px 14px 14px;margin-top:11px}
.card.flat{box-shadow:none;background:transparent;border:0;padding:2px 2px 0;margin-top:14px}
.lbl{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.09em;
  color:var(--mute)}

/* Карточка подписки — главный объект экрана, и выглядеть должна тяжелее
   остальных. Тяжесть даёт только тень: цветной грани сверху больше нет,
   на бумаге она читалась как полоса поверх блока. overflow оставлен —
   на нём держатся скруглённые углы у вложенного содержимого. */
.card.lead{box-shadow:var(--sh-lift),var(--edge);overflow:hidden}
.card h2{margin:0 0 2px;font-size:17px;font-weight:800;letter-spacing:-.01em}
.card p.sub{margin:0;color:var(--mute);font-size:13px}

.hero{position:relative;margin-top:14px;border-radius:var(--r-lg);overflow:hidden;
  background:linear-gradient(135deg,#A04C51,#5A2A2D 72%);
  border:1px solid rgba(50,36,36,.55);
  box-shadow:0 3px 8px rgba(36,28,29,.16),0 16px 34px rgba(36,28,29,.22);
  color:#fff;min-height:138px;isolation:isolate}
/* Тонкая светлая грань по верхнему краю — от неё карточка «поднимается». */
.hero::after{content:'';position:absolute;inset:0;z-index:3;pointer-events:none;
  border-radius:inherit;box-shadow:inset 0 1px 0 rgba(255,255,255,.26)}
/* Содержимое прижато вправо: слева на снимке сидит Кузя, и текст поверх него
   закрывал единственную живую деталь баннера. */
.hero-in{position:relative;z-index:2;height:100%;min-height:138px;
  display:flex;flex-direction:column;align-items:flex-end;justify-content:center;
  text-align:right;padding:20px 18px;max-width:64%;margin-left:auto}
/* Сумеречный вариант: зелёная заливка на синем небе выглядела грязью,
   поэтому у закончившейся подписки и градиент, и подложка холодные. */
.hero.dusk{background:linear-gradient(135deg,#3E4A63,#232C3D 72%);
  border-color:rgba(24,30,44,.6)}
.hero.dusk::before{background:linear-gradient(90deg,rgba(18,24,38,.10) 0%,
  rgba(18,24,38,.28) 26%,rgba(18,24,38,.70) 52%,rgba(18,24,38,.90) 76%,
  rgba(18,24,38,.95) 100%)}
.hero.dusk .chip i{background:#F2C14E;box-shadow:0 0 0 3px rgba(242,193,78,.22)}

/* Луг за текстом. Тот же приём, что на странице подписки: снимок во всю
   карточку и градиент поверх — иначе белые буквы теряются в траве. */
.hero .kuz{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:22% 15%;z-index:0;filter:saturate(1.5) contrast(1.12) brightness(.98)}
/* Градиент кладётся ПОВЕРХ снимка, а не под ним: одинаковый z-index красит
   псевдоэлемент раньше картинки, и белые буквы оказывались на ярком небе. */
.hero::before{content:'';position:absolute;inset:0;z-index:1;
  /* Слева темнее, справа луг проступает: текст читается, а картинка не
   превращается в однотонную заливку. */
/* Темнеет ВПРАВО, к тексту: слева снимок остаётся чистым, и Кузя виден
   целиком. Раньше было наоборот, и градиент закрашивал именно его. */
background:linear-gradient(90deg,rgba(39,26,27,.10) 0%,rgba(39,26,27,.24) 26%,
             rgba(39,26,27,.68) 52%,rgba(39,26,27,.90) 76%,rgba(39,26,27,.95) 100%)}
.hero .k{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.09em;
  opacity:.86;text-shadow:0 1px 2px rgba(29,20,21,.5)}
.hero .v{font-size:28px;font-weight:800;line-height:1.08;margin-top:6px;
  text-shadow:0 2px 6px rgba(29,20,21,.45)}
.hero .m{margin-top:6px;font-size:13px;opacity:.92;text-shadow:0 1px 3px rgba(29,20,21,.45)}
/* Чип статуса. Общая деталь: стоит и на баннере главной, и на визитке
   профиля, поэтому к .hero не привязан. */
.chip{display:inline-flex;align-items:center;gap:7px;margin-top:12px;padding:6px 13px;
  border-radius:var(--pill);background:rgba(27,18,19,.42);border:1px solid rgba(255,255,255,.44);
  font-size:12px;font-weight:800;backdrop-filter:blur(4px);
  box-shadow:0 2px 8px rgba(27,18,19,.3)}
.chip i{width:6px;height:6px;border-radius:50%;background:#F07A81;
  box-shadow:0 0 0 3px rgba(211,151,155,.22);animation:pulse 2.6s ease-in-out infinite}
.chip.off i{background:#F2C14E;animation:none}
@keyframes pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.72);opacity:.65}}

/* Шапка продления. Отдельный вид, потому что это не карточка товара, а
   напоминание о том, что у человека уже есть. */
.card.renew{margin-top:12px;padding:12px 14px 13px}
.card.renew h2{margin-top:2px}
.card.renew .now{display:flex;align-items:baseline;gap:7px;margin-top:8px;padding:6px 10px;
  border-radius:var(--pill);background:var(--brand-soft);align-self:flex-start;
  width:-moz-fit-content;width:fit-content}
.card.renew .now span{font-size:11px;font-weight:800;text-transform:uppercase;
  letter-spacing:.06em;color:var(--mute)}
.card.renew .now b{font-size:13.5px;font-weight:800;color:var(--brand-deep)}
.card.renew .sub{margin-top:8px}

/* ─────────────────────────── блок подписки */

/* Три числа в ряд с разделителями. Строчный список «ключ — значение» на
   главной проигрывает: там всё одинаково важно, а тут видно главное. */
.stats{display:grid;grid-template-columns:repeat(3,1fr);margin:11px -4px 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.stats .c{padding:9px 4px;text-align:center;position:relative}
.stats .c+.c::before{content:'';position:absolute;left:0;top:14px;bottom:14px;
  width:1px;background:var(--line)}
.stats .c b{display:block;font-size:17px;font-weight:800;letter-spacing:-.02em;line-height:1.1}
.stats .c span{display:block;font-size:11px;font-weight:700;color:var(--mute);margin-top:4px;
  text-transform:uppercase;letter-spacing:.05em}
.stats .c b.low{color:var(--warn)}
.stats .c b.out{color:var(--bad)}

.traffic{margin-top:11px}
.traffic .t{display:flex;justify-content:space-between;align-items:baseline;font-size:13px}
.traffic .t span{color:var(--mute)}
.traffic .t b{font-weight:800}

/* Ссылка подписки. Тёмная вдавленная панель: это не текст и не кнопка, а
   то, что уносят в другое приложение, и выглядеть должна как поле с данными. */
.link{margin-top:10px;display:flex;align-items:stretch;gap:0;
  border:1px solid var(--line-2);border-radius:var(--r);overflow:hidden;
  background:linear-gradient(180deg,#F0EFEE,#E8E6E4);
  box-shadow:inset 0 2px 5px rgba(36,28,29,.10)}
.link .txt{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;
  padding:8px 11px;color:var(--brand-deep)}
.link .txt i{font-style:normal;font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.08em;color:var(--mute)}
.link .txt b{font-weight:700;font-size:13px;line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.link a{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;
  padding:8px 11px;text-decoration:none;color:var(--brand-deep)}
.link a i{font-style:normal;font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.08em;color:var(--mute)}
.link a b{font-weight:700;font-size:13px;line-height:1.3;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.link button{position:relative;flex:0 0 auto;width:56px;border:0;
  border-left:1px solid var(--line-2);
  background:linear-gradient(180deg,#fff,#F3F2F0);color:var(--cta);cursor:pointer;
  display:grid;place-items:center;font-family:var(--font);overflow:hidden;
  transition:background .22s ease,color .22s ease}
.link button:active{background:var(--brand-soft)}
/* Обе иконки лежат в одной клетке сетки — так они меняются на месте, без
   скачка ширины. */
.link button svg{grid-area:1/1;width:19px;height:19px;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1),opacity .18s ease}
.link button svg.ok{transform:scale(.4) rotate(-25deg);opacity:0}
.link button.done{background:linear-gradient(180deg,#8E3E42,#6E2E32);color:#fff}
.link button.done svg{transform:scale(.4) rotate(25deg);opacity:0}
.link button.done svg.ok{transform:none;opacity:1}

/* Волна по полю ссылки: короткая подсветка слева направо, чтобы было видно,
   что скопировалось именно оно. */
.link{position:relative}
.link.flash::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(121,86,88,.22),transparent);
  animation:flash .7s ease-out}
@keyframes flash{from{transform:translateX(-100%)}to{transform:translateX(100%)}}

/* Кнопка «Скопировать ссылку» в профиле отвечает тем же зелёным. */
.btn.ghost.done{background:linear-gradient(180deg,#EBE9E7,#DFDAD4);
  border-color:var(--cta);color:var(--brand-deep)}

/* Нумерованные шаги. Кружок с цифрой рисуется счётчиком: обычный список
   даёт мелкие цифры без выравнивания. */
.steps{list-style:none;counter-reset:step;margin:10px 0 0;padding:0;display:grid;gap:9px}
.steps li{counter-increment:step;display:flex;align-items:flex-start;gap:10px;
  font-size:13.5px;color:var(--soft);line-height:1.35}
.steps li::before{content:counter(step);flex:0 0 auto;width:22px;height:22px;border-radius:50%;
  background:linear-gradient(180deg,#E9E7E5,#DFDAD4);color:var(--brand-deep);
  font-size:12px;font-weight:800;display:grid;place-items:center;margin-top:1px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.8)}

/* ─────────────────────────── профиль */

/* Визитка. Тот же зелёный, что у баннера главной, но без снимка: фотография
   Кузи уже стоит на первом экране, и второй раз она читается как повтор.
   Материал держит травяной узор — тот, что лежит на фоне главной. */
.me{position:relative;display:grid;grid-template-columns:auto 1fr auto;
  align-items:center;gap:11px 13px;margin-top:14px;
  padding:15px 16px;border-radius:var(--r-lg);overflow:hidden;color:#fff;isolation:isolate;
  background:linear-gradient(135deg,#A04C51,#5A2A2D 72%);
  border:1px solid rgba(50,36,36,.55);
  box-shadow:0 3px 8px rgba(36,28,29,.16),0 16px 34px rgba(36,28,29,.22)}
/* Узор с визитки убран: это был тот же травяной тайл, что лежал фоном
   у Кузи. Карточку держат градиент и тень. */
.me::after{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;box-shadow:inset 0 1px 0 rgba(255,255,255,.26)}
.me>*{position:relative;z-index:1}
/* Кружок светлый, а не тёмный, как в шапке: на зелёном фоне тёмная аватарка
   сливается с карточкой, и человек на своей же визитке пропадает. */
.me .ava{width:56px;height:56px;border-radius:50%;flex:0 0 auto;overflow:hidden;
  display:grid;place-items:center;font-size:22px;font-weight:800;color:var(--brand-deep);
  background:linear-gradient(180deg,#F3F2F1,#DFDAD4);
  box-shadow:0 2px 6px rgba(29,20,21,.3),0 0 0 2px rgba(255,255,255,.55)}
.me .ava img{width:100%;height:100%;object-fit:cover;display:block}
.me .tx{min-width:0;flex:1}
.me .tx b{display:block;font-size:19px;font-weight:800;letter-spacing:-.015em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 1px 3px rgba(29,20,21,.35)}
/* Номер. Подпись словами и цифры в одну строку: «id 123456» одним размером
   читалось как служебная строка отладки, хотя это ровно то, что человек
   присылает в поддержку. Цифры табличные — иначе номер «прыгает» шириной при
   смене состояния. */
.me .cid{grid-column:1/-1;display:flex;align-items:center;gap:9px;padding:6px 7px 6px 13px;
  border-radius:var(--pill);cursor:pointer;font-family:var(--font);
  background:rgba(27,18,19,.34);border:1px solid rgba(255,255,255,.36);color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16);
  transition:background .16s ease,transform .1s ease}
.me .cid i{font-style:normal;font-size:10.5px;font-weight:800;text-transform:uppercase;
  letter-spacing:.07em;opacity:.72}
.me .cid b{margin-left:auto;font-size:14.5px;font-weight:800;letter-spacing:.03em;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
/* Кружок с иконкой: копирование и его подтверждение — одно место, две
   картинки одна поверх другой, как у кнопки рядом со ссылкой. */
.me .cid .ic{position:relative;flex:0 0 auto;width:26px;height:26px;border-radius:50%;
  display:grid;place-items:center;background:rgba(255,255,255,.18)}
.me .cid .ic svg{grid-area:1/1;width:13px;height:13px;
  transition:transform .18s cubic-bezier(.2,.8,.3,1),opacity .18s ease}
.me .cid .ic svg.ok{transform:scale(.4) rotate(-25deg);opacity:0}
.me .cid:active{background:rgba(27,18,19,.58);transform:translateY(1px)}
.me .cid.done{background:rgba(211,151,155,.24);border-color:rgba(211,151,155,.6)}
.me .cid.done .ic{background:rgba(211,151,155,.34)}
.me .cid.done svg{transform:scale(.4) rotate(25deg);opacity:0}
.me .cid.done svg.ok{transform:none;opacity:1}
.me .chip{margin-top:0;flex:0 0 auto;align-self:center}
/* Сумерки — по той же логике, что у баннера: без доступа зелёный луг обещает
   то, чего сейчас нет. */
.me.dusk{background:linear-gradient(135deg,#3E4A63,#232C3D 72%);
  border-color:rgba(24,30,44,.6)}
.me.dusk .ava{color:#232C3D}
.me.dusk .chip i{background:#F2C14E;box-shadow:0 0 0 3px rgba(242,193,78,.22)}

/* Датчики расхода. На главной те же числа стоят счётчиками — там важно
   «сколько осталось». Здесь важно «сколько из сколького», а это показывает
   полоса, а не цифра. */
.gauges{display:grid;gap:12px;margin-top:13px}
.gauge .t{display:flex;align-items:baseline;justify-content:space-between;gap:10px;font-size:13px}
.gauge .t span{color:var(--mute)}
.gauge .t b{font-weight:800;letter-spacing:-.01em}
.gauge .t b.warn{color:var(--warn)}
.gauge .t b.bad{color:var(--bad)}

/* Состав тарифа списком с галочками — та же деталь, что на витрине: человек
   уже видел её при покупке и узнаёт, что читает про то же самое. */
.card>.feat{margin:11px 0 0;padding:0;list-style:none;display:grid;gap:7px;
  font-size:13.5px;color:var(--soft)}
.card>.feat li{display:flex;gap:9px;align-items:flex-start;line-height:1.35}
.card>.feat li svg{flex:0 0 auto;margin-top:3px;color:var(--brand)}

/* Флаги стран. Крупно и в один ряд: это единственная строка экрана, которую
   читают картинкой, а не текстом. */
.locs{display:flex;align-items:center;gap:11px;margin-top:12px;padding:9px 12px;
  border-radius:var(--r);background:var(--tint);border:1px solid var(--line)}
.locs b{flex:0 0 auto;font-size:17px;letter-spacing:.08em;line-height:1.2}
.locs span{font-size:12px;color:var(--mute)}

/* Действия профиля. Главная кнопка во всю ширину, остальное — плитками по
   две: «докупить трафик» и «поддержка» одинаково важны и одинаково редки,
   и список строк ради них занимал пол-экрана. */
.acts-wrap{margin-top:12px;display:grid;gap:8px}
.acts{display:grid;grid-template-columns:1fr 1fr;gap:8px}
/* Нечётная последняя плитка растягивается: дыра в половину ряда читается как
   недогруженный экран. */
.acts>:last-child:nth-child(odd){grid-column:1/-1}
/* Иконка слева от подписи, а не над ней: столбиком плитка вырастала вдвое,
   и нижняя пара уезжала под нижний бар — а это ровно «поддержка», за которой
   идут в самый неудачный момент. */
.act{display:flex;align-items:center;gap:9px;
  padding:9px 10px;border:1px solid var(--line);border-radius:var(--r);cursor:pointer;
  font-family:var(--font);text-align:left;color:var(--ink);
  background:linear-gradient(180deg,#fff,#FBFBFB);
  box-shadow:0 1px 2px rgba(36,28,29,.06),0 6px 16px rgba(36,28,29,.06),var(--edge);
  transition:transform .1s ease,box-shadow .16s ease}
.act .ic{flex:0 0 auto;width:31px;height:31px;border-radius:10px;display:grid;place-items:center;
  background:var(--brand-soft);color:var(--brand-deep)}
.act .ic svg{width:17px;height:17px}
/* Подпись в одну строку: перенос делал соседние плитки разной плотности и
   ряд читался как случайно свёрстанный. */
.act b{min-width:0;font-size:13px;font-weight:800;letter-spacing:-.02em;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.act:active{transform:translateY(1px);
  box-shadow:inset 0 2px 6px rgba(36,28,29,.10)}

/* ─────────────────────────── кнопки */
.btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  height:45px;border:0;border-radius:var(--r);cursor:pointer;
  font-family:var(--font);font-size:16px;font-weight:800;letter-spacing:-.01em;
  text-decoration:none;
  background:linear-gradient(180deg,#8E3E42,var(--cta-deep) 62%,#662A2D);color:#fff;
  box-shadow:var(--sh-2),inset 0 1px 0 rgba(255,255,255,.28),
             inset 0 -1px 0 rgba(0,0,0,.16);
  transition:transform .1s ease,box-shadow .16s ease,filter .16s ease}
/* Нажатие вдавливает, а не сдвигает: сдвиг на пиксель на телефоне не читается. */
.btn:active{transform:translateY(1px);filter:brightness(.96);
  box-shadow:0 1px 3px rgba(57,39,40,.3),inset 0 3px 7px rgba(0,0,0,.24)}
.btn[disabled]{opacity:.55;box-shadow:none;pointer-events:none}
.btn.ghost{background:linear-gradient(180deg,#fff,#F5F4F3);color:var(--brand-deep);
  border:1px solid var(--line-2);
  box-shadow:0 1px 2px rgba(36,28,29,.06),0 4px 12px rgba(36,28,29,.06),var(--edge)}
.btn.ghost:active{filter:none;background:var(--brand-soft);
  box-shadow:inset 0 2px 6px rgba(36,28,29,.12)}
.btn.soft{background:var(--brand-soft);color:var(--brand-deep);box-shadow:none}
.btn.sm{height:44px;font-size:15px}
.btns{display:grid;gap:8px;margin-top:11px}
.btns.two{grid-template-columns:1fr 1fr}

/* ─────────────────────────── полосы */
.meter{margin-top:6px;height:8px;border-radius:var(--pill);background:var(--brand-soft);overflow:hidden}
.meter i{display:block;height:100%;border-radius:var(--pill);
  background:linear-gradient(90deg,#AE555A,#8E3E42);transition:width .5s cubic-bezier(.22,1,.36,1)}
.meter i.warn{background:linear-gradient(90deg,#E8B14C,#C8892A)}
.meter i.bad{background:linear-gradient(90deg,#D9705F,#B3261E)}


/* ─────────────────────────── магазин */

/* Переключатель разделов. Бегунок отдельным элементом, а не рамкой на
   кнопке: так он едет между разделами, и переход виден движением, а не
   перекраской. */
/* Авторское display:grid сильнее браузерного правила для [hidden], поэтому
   скрытие приходится объявлять самим — иначе переключатель оставался
   висеть на внутренних шагах покупки. */
.seg[hidden]{display:none}
.seg{position:relative;display:grid;grid-template-columns:repeat(3,1fr);gap:0;
  margin-top:14px;padding:4px;border-radius:var(--pill);
  background:linear-gradient(180deg,#E4E2DE,#DEDBD6);
  border:1px solid var(--line-2);
  box-shadow:inset 0 2px 5px rgba(36,28,29,.10)}
.seg .pin{position:absolute;top:4px;bottom:4px;left:4px;width:calc((100% - 8px)/3);
  border-radius:var(--pill);background:linear-gradient(180deg,#fff,#F4F3F2);
  box-shadow:0 1px 2px rgba(36,28,29,.10),0 4px 10px rgba(36,28,29,.10),
             inset 0 1px 0 rgba(255,255,255,.9);
  transition:transform .28s cubic-bezier(.22,1,.36,1)}
.seg button{position:relative;z-index:1;border:0;background:none;cursor:pointer;
  font-family:var(--font);font-size:13.5px;font-weight:800;letter-spacing:-.01em;
  color:var(--mute);height:38px;transition:color .2s ease}
.seg button.on{color:var(--brand-deep)}

/* Строка тарифа. Свёрнутая — это одна строка: название, короткая суть и цена
   «от». Развёрнутая добавляет сроки и кнопку. */
.tar{position:relative;background:linear-gradient(180deg,#fff,#FBFAF9);
  border:1px solid var(--line);border-radius:var(--r-lg);margin-top:10px;
  box-shadow:var(--sh-1),var(--edge);overflow:hidden}
/* Карточка тарифа — целиком кнопка: попасть по строке проще, чем по
   стрелке, а промах здесь стоит покупки. */
.tar.pick{display:block;width:100%;text-align:left;font-family:var(--font);
  padding:12px 14px;cursor:pointer;margin-top:9px}
.tar.pick:active{transform:translateY(1px);box-shadow:inset 0 2px 8px rgba(36,28,29,.10)}
.tar.pick .hd{padding:0;cursor:default}
/* Стрелка стоит в шапке, у цены: подвал держался только на флагах, а без
   них это была строка ради одной стрелки. */
.tar .hd .ch{flex:0 0 auto;color:var(--line-strong);display:flex;align-self:center}
/* Метка стоит в строке с названием, а не поверх карточки: в углу она
   наезжала на цену и на стрелку. */
.tar .hd .nm b .mark{display:inline-block;margin-left:7px;vertical-align:1px;
  font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  color:var(--brand-deep);background:var(--brand-soft);padding:2px 7px;
  border-radius:var(--pill)}
.tar .hd .nm b .mark.hot{background:#FBEFD6;color:#8A5A0F}
.tar .hd{display:flex;align-items:center;gap:12px;padding:14px 15px;cursor:pointer;
  width:100%;border:0;background:none;font-family:var(--font);text-align:left}
.tar .hd .nm{min-width:0;flex:1}
.tar .hd .nm b{display:block;font-size:15.5px;font-weight:800;letter-spacing:-.01em}
.tar .hd .nm span{display:block;font-size:12px;color:var(--mute);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tar .hd .pr{flex:0 0 auto;text-align:right}
.tar .hd .pr b{display:block;font-size:18px;font-weight:800;color:var(--cta);
  letter-spacing:-.02em;line-height:1.1}
.tar .hd .pr i{font-style:normal;display:block;font-size:10px;color:var(--mute);
  text-transform:uppercase;letter-spacing:.06em}
.tar .hd .ch{flex:0 0 auto;color:var(--line-strong);transition:transform .26s cubic-bezier(.22,1,.36,1)}
.tar.on .hd .ch{transform:rotate(90deg)}

/* Раскрытая часть отделяется от шапки материалом: тон, внутренняя тень и
   линия сверху.

   Травяного узора здесь нет намеренно. Он стоял ровно под ценами и
   галочками — не за карточками, как на фоне страницы, а прямо под текстом,
   и рябил так, что цифры переставали читаться. Фактура нужна там, где на
   неё не смотрят. */
.tar.on .body>*{opacity:1;transform:none}
.tar .feat{margin:9px 0 0;padding:0;list-style:none;display:grid;gap:4px;
  font-size:12.5px;color:var(--soft)}
.tar .feat li{display:flex;gap:7px;align-items:flex-start}
.tar .feat li svg{flex:0 0 auto;margin-top:2px;color:var(--brand)}

/* ─────────────────────────── тарифы */
.plans{display:grid;gap:12px;margin-top:12px}
.plan{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px;box-shadow:var(--sh-1);transition:border-color .15s ease,box-shadow .15s ease}
.plan.on{border-color:var(--brand);box-shadow:0 0 0 2px rgba(121,86,88,.16),var(--sh-1)}
.plan .hd{display:flex;align-items:baseline;gap:8px}
.plan .hd b{font-size:17px;font-weight:800}
.plan .badge{margin-left:auto;font-size:11px;font-weight:800;padding:4px 9px;border-radius:var(--pill);
  background:var(--brand-soft);color:var(--brand-deep);text-transform:uppercase;letter-spacing:.04em}
.plan .badge.best{background:#FDF0D8;color:#8A5A0F}
.plan .feat{margin:10px 0 0;padding:0;list-style:none;display:grid;gap:6px;font-size:13px;color:var(--soft)}
.plan .feat li{display:flex;gap:8px;align-items:flex-start}
.plan .feat li svg{flex:0 0 auto;margin-top:2px;color:var(--brand)}

/* Ровно три в ряд. Пять сроков при автоподборе вставали как 4+1, и
   одинокая карточка во втором ряду читалась как обрезанный список. */
.terms{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px}
.term{border:1px solid var(--line-2);background:var(--tint);border-radius:var(--r-sm);
  padding:9px 6px;text-align:center;cursor:pointer;transition:all .14s ease}
.term.on{border-color:var(--cta);background:#fff;box-shadow:0 0 0 2px rgba(108,72,74,.14)}
.term b{display:block;font-size:14px;font-weight:800}
.term span{display:block;font-size:11px;color:var(--mute);margin-top:2px}
.term .save{display:block;font-size:10px;font-weight:800;color:var(--cta);margin-top:3px}

/* «Сейчас → станет». Два одинаковых блока со стрелкой между ними: разница
   читается за один взгляд, а число в счётчике перестаёт быть отвлечённым. */
.swap{display:flex;align-items:stretch;gap:10px;margin-top:4px}
.swap .box{flex:1;text-align:center;padding:12px 6px 11px;border-radius:var(--r);
  border:1px solid var(--line-2);background:linear-gradient(180deg,#FAF9F8,#F1F0EF)}
.swap .box.next{border-color:var(--cta);
  background:linear-gradient(180deg,#EBE9E7,#E3DED8);
  box-shadow:0 0 0 2px rgba(108,72,74,.12),inset 0 1px 0 rgba(255,255,255,.7)}
.swap .box i{display:block;font-style:normal;font-size:10px;font-weight:800;
  text-transform:uppercase;letter-spacing:.08em;color:var(--mute)}
.swap .box.next i{color:var(--cta)}
.swap .box b{display:block;font-size:30px;font-weight:800;line-height:1.05;margin-top:5px;
  letter-spacing:-.03em}
.swap .box.next b{color:var(--brand-deep)}
.swap .box span{display:block;font-size:11.5px;color:var(--mute);margin-top:2px}
.swap .arrow{flex:0 0 auto;align-self:center;color:var(--line-strong);display:flex}

.busy{margin-top:9px;text-align:center;font-size:12.5px;color:var(--mute)}

/* Счётчик слотов: две кнопки и число между ними. */
.step{display:flex;align-items:center;gap:14px;justify-content:center;padding:12px 0 2px}
.step button{width:52px;height:52px;border-radius:16px;border:1px solid var(--line-2);
  background:linear-gradient(180deg,#fff,#F3F2F0);color:var(--brand-deep);
  font-family:var(--font);font-size:26px;font-weight:800;line-height:1;cursor:pointer;
  box-shadow:0 1px 2px rgba(36,28,29,.08),var(--edge)}
.step button:active{background:var(--brand-soft);box-shadow:inset 0 2px 6px rgba(36,28,29,.14)}
.step button[disabled]{opacity:.4;pointer-events:none}
.step .val{min-width:118px;text-align:center}
.step .val b{display:block;font-size:30px;font-weight:800;line-height:1;letter-spacing:-.03em;
  color:var(--cta)}
.step .val span{display:block;font-size:12px;color:var(--mute);margin-top:4px}

/* Строка выбора: срок или способ оплаты. Одна высота, одна логика нажатия —
   на обоих шагах человек делает одно и то же движение. */
.opt{display:flex;align-items:center;gap:12px;width:100%;margin-top:7px;
  padding:10px 14px;border:1px solid var(--line);border-radius:var(--r);
  background:linear-gradient(180deg,#fff,#FBFAF9);box-shadow:var(--sh-1),var(--edge);
  font-family:var(--font);text-align:left;cursor:pointer;
  animation:rise .3s cubic-bezier(.22,1,.36,1) both;
  transition:transform .12s ease,box-shadow .16s ease}
.opt:active{transform:translateY(1px);box-shadow:inset 0 2px 8px rgba(36,28,29,.10)}
.opt .nm{flex:1;min-width:0}
.opt .nm b{display:block;font-size:15px;font-weight:800;letter-spacing:-.01em;line-height:1.2}
.opt .nm span{display:block;font-size:11.5px;color:var(--mute);margin-top:1px}
.opt .pr{flex:0 0 auto;text-align:right}
.opt .pr b{display:block;font-size:16.5px;font-weight:800;color:var(--cta);
  letter-spacing:-.02em;line-height:1.15}
.opt .pr i{font-style:normal;display:block;font-size:10px;font-weight:800;margin-top:2px;
  color:var(--brand-deep);background:var(--brand-soft);border-radius:var(--pill);padding:1px 6px}
.opt .ch{flex:0 0 auto;color:var(--line-strong)}

/* Шапка внутреннего шага: стрелка назад и то, что уже выбрано. */
.back{display:flex;align-items:center;gap:12px;margin-top:14px;padding:2px 0 6px}
.back .ico{flex:0 0 auto;width:40px;height:40px;border-radius:14px;cursor:pointer;
  border:1px solid var(--line-2);background:linear-gradient(180deg,#fff,#F4F3F2);
  color:var(--brand-deep);display:grid;place-items:center;
  box-shadow:0 1px 2px rgba(36,28,29,.08),var(--edge)}
.back .ico:active{background:var(--brand-soft);box-shadow:inset 0 2px 6px rgba(36,28,29,.12)}
.back .tx{min-width:0}
.back .tx b{display:block;font-size:17px;font-weight:800;letter-spacing:-.015em}
.back .tx span{display:block;font-size:12.5px;color:var(--mute);margin-top:1px}

/* Кнопка в ожидании ответа кассы: текст остаётся, поверх идёт полоска. */
/* Ожидание кассы у строки срока и плитки пакета: та же полоска, что у
   кнопки. Раньше класс был описан только для .btn, и нажатие на строку или
   плитку внешне не менялось всё время, пока выставляется счёт. */
.opt.wait,.tile.wait{pointer-events:none;position:relative;overflow:hidden;opacity:.6}
.opt.wait::after,.tile.wait::after{content:'';position:absolute;left:0;top:0;bottom:0;width:40%;
  background:linear-gradient(90deg,transparent,rgba(121,86,88,.20),transparent);
  animation:sweep 1s linear infinite}
.btn.wait{pointer-events:none;position:relative;overflow:hidden;color:transparent}
.btn.wait::after{content:'';position:absolute;left:0;top:0;bottom:0;width:40%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);
  animation:sweep 1s linear infinite}
@keyframes sweep{from{transform:translateX(-100%)}to{transform:translateX(350%)}}

/* ─────────────────────────── сетка мелких товаров */
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}
.tile{border:1px solid var(--line);background:var(--card);border-radius:var(--r);padding:12px;
  text-align:left;cursor:pointer;box-shadow:var(--sh-1);font-family:var(--font)}
.tile b{display:block;font-size:15px;font-weight:800}
.tile span{display:block;font-size:12px;color:var(--mute);margin-top:2px}
.tile em{display:block;font-style:normal;margin-top:8px;font-size:15px;font-weight:800;color:var(--cta)}
.tile:active{transform:translateY(1px)}

/* ─────────────────────────── витрина по ссылке подписки (buy.html)

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

   --bar-h обнуляем на уровне страницы, а не правим три отступа поимённо:
   от неё считают своё место и поле страницы, и трава, и подсказка. */
body.buy-page{--bar-h:0px}
body.buy-page .app{padding-bottom:calc(env(safe-area-inset-bottom) + 28px)}
body.buy-page .toast{bottom:calc(env(safe-area-inset-bottom) + 20px)}
/* Та же ловушка, что у .seg и .gate: авторский display сильнее браузерного
   правила для [hidden], и кнопка «Подписка» оставалась на экране даже там,
   куда возвращаться некуда — например у того, у кого подписки нет вовсе. */
.top a.sup[hidden]{display:none}

/* На широком экране кабинет отводит место левой панели и прижимает колонку к
   ней. У витрины панели нет, и то же правило уводило страницу вправо от
   центра — здесь колонка просто стоит посередине. */
@media (min-width: 960px) {
  body.buy-page .app{margin:0 auto;max-width:720px;padding:26px 40px 56px}
  body.buy-page .ridge{left:0}
  body.buy-page .toast{left:50%}
}

/* Метка «выбирают» — строкой рядом с названием, как в карточке тарифа.
   Поверх угла плитки она наезжала бы на цену: на широком экране плитка
   становится строкой, и угол занят. */
.tile b .mark{display:inline-block;margin-left:6px;vertical-align:1px;
  font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  color:var(--brand-deep);background:var(--brand-soft);padding:2px 7px;
  border-radius:var(--pill)}
.tile b .mark.hot{background:#FBEFD6;color:#8A5A0F}

/* Цена и выгода — одной строкой: «−48 %» без цены рядом ни о чём не говорит,
   а под ценой отдельной строкой удлиняет плитку на треть. */
.tile .row{display:flex;align-items:baseline;gap:7px;margin-top:8px}
.tile .row em{margin-top:0}
.tile .row i{font-style:normal;font-size:10.5px;font-weight:800;color:var(--brand-deep);
  background:var(--brand-soft);border-radius:var(--pill);padding:2px 7px}

/* ─────────────────────────── нижний бар */
.bar{position:fixed;left:0;right:0;bottom:0;z-index:5;
  padding-bottom:env(safe-area-inset-bottom);
  background:rgba(255,255,255,.88);backdrop-filter:blur(14px) saturate(1.4);
  border-top:1px solid var(--line)}
.bar .in{max-width:460px;margin:0 auto;height:var(--bar-h);display:grid;grid-template-columns:repeat(4,1fr)}
/* Имя продукта в панели — только для широкого экрана (см. конец файла).
   Внизу телефона оно занимало пятую колонку, и «Профиль» уезжал за край. */
.bar .brand{display:none}
.bar button{border:0;background:none;font-family:var(--font);cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  color:var(--mute);font-size:11px;font-weight:700;padding:0;position:relative}
.bar button svg{width:23px;height:23px;transition:transform .2s cubic-bezier(.22,1,.36,1)}
.bar button.on{color:var(--cta)}
.bar button.on svg{transform:translateY(-1px) scale(1.06)}
.bar button.on::before{content:'';position:absolute;top:6px;width:26px;height:3px;border-radius:var(--pill);
  background:var(--cta)}

/* ─────────────────────────── экраны и переходы */
.screen{display:none}
.screen.on{display:block;animation:in .3s cubic-bezier(.22,1,.36,1) both}
@keyframes in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* Карточки въезжают по очереди. Задержку каждой проставляет скрипт — в CSS
   пришлось бы плодить :nth-child под неизвестное число тарифов. */
.tar{animation:rise .34s cubic-bezier(.22,1,.36,1) both}
@keyframes rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

/* Плитки товаров — тем же движением, но короче: их много, и длинная
   очередь превращается в ожидание. */
.tiles .tile{animation:rise .3s cubic-bezier(.22,1,.36,1) both}
.tiles .tile:nth-child(2n){animation-delay:.04s}
.tiles .tile:nth-child(n+3){animation-delay:.08s}
.tiles .tile:nth-child(n+5){animation-delay:.12s}
.tiles .tile:nth-child(n+7){animation-delay:.16s}

@media (prefers-reduced-motion: reduce){
  .screen.on,.tar,.tiles .tile,.btn.wait::after{animation:none}
  .btn,.tile,.tip,.act,.tar.pick,.opt,.seg .pin,.link button,.link button svg,
  .me .cid,.me .cid .ic svg{transition:none}
  .link.flash::after{animation:none}
  .opt{animation:none}
  .chip i{animation:none}
}

.skel{border-radius:var(--r);background:linear-gradient(90deg,#E9E8E7,#F3F3F2,#E9E8E7);
  background-size:200% 100%;animation:sk 1.2s linear infinite;height:14px;margin:8px 0}
@keyframes sk{from{background-position:200% 0}to{background-position:-200% 0}}

/* Карточка-подсказка: короткая, с иконкой, кликабельная целиком. */
.tip{display:flex;align-items:center;gap:12px;margin-top:8px;padding:10px 14px;
  background:linear-gradient(180deg,#fff,#FAFAF9);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--sh-1),var(--edge);
  cursor:pointer;width:100%;text-align:left;font-family:var(--font);
  transition:transform .12s ease,box-shadow .16s ease}
.tip:active{transform:translateY(1px);box-shadow:inset 0 2px 6px rgba(36,28,29,.10)}
.tip .ic{flex:0 0 auto;width:36px;height:36px;border-radius:11px;display:grid;place-items:center;
  background:linear-gradient(180deg,#E9E7E5,#DFDAD4);color:var(--brand-deep);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.8),0 1px 2px rgba(36,28,29,.08)}
.tip b{display:block;font-size:15px;font-weight:800}
.tip span{display:block;font-size:12.5px;color:var(--mute);margin-top:1px}
.tip .go{margin-left:auto;color:var(--line-strong)}

.note{margin-top:10px;font-size:12px;color:var(--mute);text-align:center}
.copy{display:flex;gap:8px;align-items:center;margin-top:12px;padding:12px;border-radius:var(--r);
  background:var(--tint);border:1px dashed var(--line-2);font-size:13px;word-break:break-all}
.copy b{font-weight:700;color:var(--soft)}

.toast{position:fixed;left:50%;bottom:calc(var(--bar-h) + env(safe-area-inset-bottom) + 16px);
  transform:translate(-50%,20px);z-index:20;opacity:0;pointer-events:none;
  background:rgba(44,37,37,.94);color:#fff;font-size:14px;font-weight:700;
  padding:11px 18px;border-radius:var(--pill);box-shadow:0 8px 24px rgba(44,37,37,.28);
  transition:opacity .22s ease,transform .22s cubic-bezier(.22,1,.36,1)}
.toast.on{opacity:1;transform:translate(-50%,0)}

/* ─────────────────────────── окно входа (обычный браузер)

   Карточка стоит по центру видимой области, а не «сверху с отступом»: на
   десктопе поле в полтора экрана высотой, и прижатый к верху блок посреди
   пустого луга выглядит недогруженной страницей. */
.gate{position:relative;z-index:1;min-height:100svh;display:flex;align-items:center;
  justify-content:center;padding:32px 18px calc(120px + env(safe-area-inset-bottom))}
/* Та же история, что у переключателя разделов выше: авторское display:flex
   сильнее браузерного правила для [hidden], и без этой строки окно входа
   оставалось висеть поверх кабинета — уже после того, как человек вошёл. */
.gate[hidden]{display:none}
.gate-card{width:100%;max-width:404px;background:var(--card);border-radius:var(--r-lg);
  padding:26px 24px 22px;text-align:center;box-shadow:var(--sh-lift),var(--edge);
  border:1px solid var(--line);
  animation:gate-in .42s cubic-bezier(.22,1,.36,1) both}
@keyframes gate-in{from{opacity:0;transform:translateY(14px) scale(.985)}}

/* Кузя в кружке с зелёной каймой и галочкой — тот же снимок, что на главной
   баннером, поэтому после входа экран не подменяется незнакомой картинкой.
   Кадр смещён влево: сам Кузя стоит в левой четверти снимка, и кружок по
   центру показывал бы пустой луг. */
.gate-kuz{position:relative;width:112px;height:112px;margin:0 auto 14px}
.gate-kuz img{width:100%;height:100%;object-fit:cover;object-position:24% 42%;border-radius:50%;
  background:var(--brand-soft);box-shadow:0 0 0 4px #fff,0 0 0 6px var(--brand-soft),
  0 10px 22px rgba(36,28,29,.14)}
.gate-badge{position:absolute;right:2px;bottom:2px;width:32px;height:32px;border-radius:50%;
  display:grid;place-items:center;background:linear-gradient(180deg,#A04C51,var(--cta-deep));
  box-shadow:0 0 0 3px #fff,0 4px 10px rgba(57,39,40,.32)}
.gate-badge svg{width:17px;height:17px}

.gate h1{font-size:25px;font-weight:800;color:var(--brand-deep);margin:0 0 6px;
  letter-spacing:-.02em}
.gate-lead{color:var(--soft);margin:0 0 20px;font-size:14.5px;line-height:1.5}

/* Наша кнопка и настоящий виджет — один стек. Виджет прозрачный и растянут
   чуть шире кнопки: его iframe меньше, а кликать человек будет по краям
   тоже. Без растяжения углы кнопки просто не отвечают. */
.tgwrap{position:relative;isolation:isolate}
.tgbtn{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;height:52px;
  border:0;border-radius:var(--r);cursor:pointer;font-family:var(--font);
  font-size:16.5px;font-weight:800;letter-spacing:-.01em;color:#fff;
  background:linear-gradient(180deg,#31B0EE,#229ED9 62%,#1C8FC7);
  box-shadow:0 2px 4px rgba(20,110,160,.26),0 10px 22px rgba(20,110,160,.28),
             inset 0 1px 0 rgba(255,255,255,.32),inset 0 -1px 0 rgba(0,0,0,.14);
  transition:transform .1s ease,box-shadow .16s ease,filter .16s ease}
.tgbtn svg{width:22px;height:22px;flex:none}
.tgwrap:hover .tgbtn{filter:brightness(1.04)}
.tgwrap:active .tgbtn{transform:translateY(1px);filter:brightness(.96);
  box-shadow:0 1px 3px rgba(20,110,160,.3),inset 0 3px 7px rgba(0,0,0,.2)}
/* Пока виджета нет, подложка не должна притворяться нажимаемой: прогиб под
   пальцем на мёртвой кнопке читается как «нажал, и не сработало». */
.tgwrap.wait{cursor:progress}
.tgwrap.wait:active .tgbtn{transform:none;filter:none;
  box-shadow:0 2px 4px rgba(20,110,160,.26),0 10px 22px rgba(20,110,160,.28),
             inset 0 1px 0 rgba(255,255,255,.32),inset 0 -1px 0 rgba(0,0,0,.14)}
.tgreal{position:absolute;left:50%;top:50%;z-index:2;opacity:0;
  transform:translate(-50%,-50%) scale(1.6);overflow:hidden}
.tgreal iframe{display:block}
/* Виджет ещё грузится. Кнопку при этом не гасим: серая кнопка читается как
   сломанная, а ждать тут доли секунды — достаточно бегунка справа. */
.tgspin{position:absolute;right:16px;top:50%;width:18px;height:18px;margin-top:-9px;z-index:3;
  border:2px solid rgba(255,255,255,.35);border-top-color:#fff;border-radius:50%;
  opacity:0;pointer-events:none;animation:tgspin .8s linear infinite}
.tgwrap.wait .tgspin{opacity:1}
@keyframes tgspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .gate-card{animation:none}
  .tgspin{animation-duration:2.4s}
}

.gate-fall{margin:12px 0 0;font-size:13.5px;color:var(--mute)}
.gate-fall a{color:var(--brand-deep);font-weight:700}

.gate-list{list-style:none;margin:20px 0 0;padding:16px 0 0;border-top:1px solid var(--line);
  display:grid;gap:11px;text-align:left}
.gate-list li{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--soft)}
.gate-list svg{width:19px;height:19px;flex:none;color:var(--brand)}

.gate-note{display:flex;align-items:flex-start;gap:8px;text-align:left;margin:16px 0 0;
  padding:11px 12px;border-radius:var(--r-sm);background:var(--tint);
  font-size:12.5px;line-height:1.45;color:var(--mute)}
.gate-note svg{width:15px;height:15px;flex:none;margin-top:1px;color:var(--brand)}


/* ─────────────────────────── широкий экран

   Кабинет родился внутри Telegram, поэтому по умолчанию он — узкая колонка
   под большой палец. На мониторе та же колонка посреди пустого луга выглядит
   недоделанной страницей, и дело не в ширине: на телефоне навигация внизу
   потому, что там её достаёт палец, а на мониторе руки лежат на клавиатуре,
   и низ экрана — самое далёкое от взгляда место.

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

   Порог 960: до него две колонки по 340 не помещаются, и раскладка
   разъезжается раньше, чем начинает помогать. */
@media (min-width: 960px) {
  :root { --rail: 252px; }

  /* Панель: из нижней полосы — в левую колонку. */
  .bar { top: 0; right: auto; width: var(--rail); height: 100vh;
    padding: 20px 14px calc(20px + env(safe-area-inset-bottom));
    border-top: 0; border-right: 1px solid var(--line);
    background: rgba(255,255,255,.72) }
  .bar .in { max-width: none; height: auto; display: flex; flex-direction: column; gap: 3px }
  .bar .brand { display: flex; align-items: center; gap: 10px; padding: 6px 12px 18px }
  .bar .brand img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover;
    object-position: 24% 42%; box-shadow: 0 0 0 2px #fff, 0 2px 6px rgba(36,28,29,.18) }
  .bar .brand b { font-size: 15.5px; font-weight: 800; color: var(--brand-deep);
    letter-spacing: -.01em }
  .bar button { flex-direction: row; justify-content: flex-start; gap: 12px;
    height: 46px; padding: 0 12px; border-radius: 13px; font-size: 14.5px; font-weight: 700 }
  .bar button .lb { font-size: 14.5px }
  .bar button:hover { background: rgba(237,242,230,.7); color: var(--brand-deep) }
  .bar button.on { background: var(--brand-soft) }
  .bar button.on svg { transform: none }
  /* Метка активного пункта переезжает с верхнего края на левый: в столбце
     подчёркивание сверху читается как отрыв кнопки от списка. */
  .bar button.on::before { top: 50%; left: 2px; width: 3px; height: 22px;
    transform: translateY(-50%) }

  /* Содержимое встаёт правее панели и держит свою ширину по центру
     оставшегося поля, а не растекается на весь монитор. */
  /* Колонка одна и узкая: кнопка во всю ширину монитора не становится
     заметнее, она становится непонятной — глаз не связывает подпись слева с
     ценой у правого края. 640 — ширина, на которой строка ещё читается одним
     взглядом.

     Стоит колонка по центру ЭКРАНА, а не по центру поля справа от панели:
     во втором случае она заметно уезжает вправо, и страница выглядит
     сдвинутой. Прижаться к панели ближе, чем на её ширину, max() не даст —
     на узком мониторе колонка просто встаёт сразу за ней. */
  .app { max-width: none; margin: 0;
    margin-left: max(var(--rail), calc(50vw - 360px));
    padding: 26px 40px 56px }
  .app > .top, .app > .screen { max-width: 640px; margin-left: 0; margin-right: 0 }
  .top { gap: 12px; padding: 0 2px 6px }
  .top .ava { width: 44px; height: 44px; font-size: 17px }
  .top .who b { font-size: 18px }
  .top .who span { font-size: 13px }
  .top a.sup { height: 38px; font-size: 13.5px }
  .top a.sup:hover { border-color: var(--line-strong); color: var(--cta-deep) }

  /* Трава начинается за панелью, иначе она лезет под её нижние пункты. Но
     только когда панель на экране: на окне входа её нет, и сдвинутая трава
     оставляла у левого края пустую полосу шириной ровно с панель. */
  .ridge { bottom: -6px }
  body:has(#bar:not([hidden])) .ridge { left: var(--rail) }
  .toast { left: calc(50% + var(--rail) / 2); bottom: 28px }

  /* Баннер на широком экране может позволить себе рост: это единственная
     картинка кабинета, и в 138 пикселей от неё остаётся полоска. */
  .hero { margin-top: 8px; min-height: 224px }
  .hero-in { min-height: 224px; max-width: 54%; padding: 28px 30px }
  .hero .v { font-size: 40px }
  .hero .m { font-size: 14.5px }
  .hero .k { font-size: 12px }

  /* Всё содержимое — одной лентой сверху вниз, каждый блок во всю ширину
     колонки. Ряды из двух кнопок заставляли глаз метаться влево-вправо,
     а разная ширина соседних блоков ломала общую левую границу — то самое,
     по чему страница и читается как аккуратная. */
  #home-body, #profile-body, #ref-body, #shop-body {
    display: flex; flex-direction: column; gap: 12px; margin-top: 16px }
  #home-body > *, #profile-body > *, #ref-body > *, #shop-body > * { margin-top: 0 }

  /* Плитки трафика и действия профиля — тоже в столбик: они соседи по
     экрану, и сетка из двух колонок посреди списка выбивается. */
  .tiles { display: flex; flex-direction: column; gap: 10px }
  .acts { grid-template-columns: 1fr }

  /* Внутри плитки объём и цена встают в строку — как у сроков продления.
     Столбиком, как на телефоне, цена оказывалась под названием, а справа
     оставалось полкарточки пустоты, и список сбивался с общего ритма
     «слева что, справа сколько». */
  .tile { display: flex; align-items: center; gap: 12px; padding: 13px 16px }
  .tile b { flex: 0 0 auto }
  .tile span { margin-top: 0; flex: 1 }
  .tile em { margin-top: 0; margin-left: auto; font-size: 16px }
  /* цена с выгодой едет вправо целым блоком, а не одной ценой */
  .tile .row { margin-top: 0; margin-left: auto }

  /* Магазин: тарифы и плитки — рядами, карточки-объяснения — во всю ширину. */

  .card { padding: 16px 18px 18px }

  /* Наведение. На телефоне его нет вовсе, и весь отклик жил в :active —
     на мониторе от этого интерфейс кажется неживым до самого нажатия. */
  .btn:hover { filter: brightness(1.05) }
  .btn.ghost:hover { border-color: var(--line-strong); background: #fff }
  .tar:hover, .tile:hover, .tip:hover, .act:hover, .opt:hover {
    border-color: var(--line-strong); box-shadow: var(--sh-lift);
    transform: translateY(-1px) }
  .tar, .tile, .tip, .act, .opt { transition: transform .14s ease, box-shadow .18s ease,
    border-color .18s ease }
  .link button:hover { background: var(--brand-soft) }
  .cid:hover { border-color: var(--line-strong) }

  @media (prefers-reduced-motion: reduce) {
    .tar:hover, .tile:hover, .tip:hover, .act:hover, .opt:hover { transform: none }
  }
}


/* Друзья: своя посадка шапки. Общая с главной ставила самурая в тот же
   угол, и на этом экране его закрывал текст. */
#ref-hero .kuz{object-position:22% 5%}
