/* ============================================================================
   OkRouter.ru — дизайн-система панели и мастера установки

   Правила, которых держимся:
   · отступы только по шкале 4/8/12/16/24/32/48 — промежуточных значений нет;
   · размеров текста семь, между соседними видна разница, а не «полпикселя»;
   · радиусов четыре, теней две, высот у кнопок и полей три;
   · индиго — действие, зелёный — только состояние «работает»;
   · шрифты локальные: во время настройки роутера интернет пропадает.
   ============================================================================ */

@import url('fonts.css');

/* ---------------------------------------------------------------- ТОКЕНЫ -- */
:root{
  /* бренд */
  --indigo-800:#2C1F92;
  --indigo-700:#3A2BB8;
  --indigo-600:#4A38DC;
  --indigo-500:#5B4BE8;
  --indigo-400:#7C6CF5;
  --indigo-100:#E6E4FD;
  --indigo-50:#F1F0FE;

  /* фирменное переливание: индиго → фуксия → зелёный → бирюза → индиго */
  --grad-brand:linear-gradient(120deg,#6c71fe,#df59d7,#00c782,#00a5ad,#6c71fe) 0 0/300% 300%;
  --grad-brand:linear-gradient(120deg,
      lab(53.1443% 29.2277 -72.2812),
      lab(59.5416% 64.1665 -39.6588),
      lab(70.9129% -57.0592 22.3716),
      lab(61.2766% -61.6121 -25.1254),
      lab(53.1443% 29.2277 -72.2812)) 0 0/300% 300%;
  --grad-action:linear-gradient(135deg,#5B4BE8,#3A2BB8);

  /* нейтральные */
  --bg:#F7F8FB;
  --surface:#FFFFFF;
  --ink:#0B0B12;
  --ink-2:#2B2E3D;
  --muted:#666C82;      /* 4.9:1 на белом — проходит AA */
  --muted-2:#8A90A4;    /* только для подписей 13px и крупнее */
  --border:#E6E9F1;
  --border-2:#F0F1F7;

  /* состояния */
  --ok:#15704B;      --ok-bg:#E7F6EE;   --ok-dot:#1FA36B;
  --warn:#7A5C0C;    --warn-bg:#FDF3D6; --warn-dot:#D99E22;
  --err:#A81F17;     --err-bg:#FCEAE8;  --err-dot:#D63F32;
  --info:#175380;    --info-bg:#E4F0FB; --info-dot:#2E7CC4;

  /* пастель под иконки — четыре, больше в панели не нужно */
  --mint:#E7F6EE; --blue:#E4F0FB; --yellow:#FDF3D6; --lilac:#EFEBFE;

  /* шкала отступов */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;

  /* шкала текста */
  --t1:12px;  /* подписи, бейджи        */
  --t2:13px;  /* второстепенное         */
  --t3:15px;  /* основной текст         */
  --t4:17px;  /* заголовок карточки     */
  --t5:20px;  /* заголовок раздела      */
  --t6:26px;  /* крупное число          */
  --t7:34px;  /* заголовок экрана       */

  /* радиусы */
  --r1:10px;  /* иконки, чипы           */
  --r2:14px;  /* поля, мелкие карточки  */
  --r3:22px;  /* карточки, окна         */
  --r-pill:999px;

  /* высоты контролов */
  --h-sm:36px; --h-md:44px; --h-lg:52px;

  /* тени: две, третья — только под цветной кнопкой */
  --shadow-1:0 1px 2px rgba(16,18,40,.04), 0 4px 14px rgba(16,18,40,.05);
  --shadow-2:0 8px 24px rgba(38,26,120,.10), 0 32px 64px rgba(38,26,120,.10);
  --shadow-action:0 8px 24px rgba(74,56,220,.26);

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);

  --font-display:'Unbounded',system-ui,sans-serif;
  --font-body:'Onest',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,'SF Mono',Menlo,Consolas,monospace;
}

/* ------------------------------------------------------------------ БАЗА -- */
*,*::before,*::after{box-sizing:border-box}

body{
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--font-body); font-size:var(--t3); line-height:1.55;
  -webkit-font-smoothing:antialiased;
  /* блик вверху шире узкого экрана — без этого на телефоне появляется
     горизонтальная прокрутка на пустом месте */
  overflow-x:hidden;
}

h1,h2,h3,h4{margin:0; font-family:var(--font-display); font-weight:700; letter-spacing:-.04em; line-height:1.18}
h1{font-size:var(--t7); line-height:1.12}
h2{font-size:var(--t5)}
h3{font-size:var(--t4)}
h4{font-size:var(--t3)}
p{margin:0}
a{color:var(--indigo-600); text-decoration:none}
a:hover{text-decoration:underline}
ul,ol{margin:0; padding:0; list-style:none}
b,strong{font-weight:600}
.mono{font-family:var(--font-mono); font-variant-numeric:tabular-nums}

:focus-visible{outline:2px solid var(--indigo-500); outline-offset:2px; border-radius:6px}

.sub{color:var(--muted); font-size:var(--t2); line-height:1.55}
.eyebrow{font-size:var(--t1); font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted)}
.muted{color:var(--muted)}
.hidden{display:none !important}
/* Видно только программе чтения с экрана: заголовок страницы должен быть,
   но рисовать его на панели незачем — там и так понятно, где ты. */
.sr-only{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0}
.truncate{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

/* фирменное переливание в тексте */
.grad-text{
  background:var(--grad-brand);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
  animation:gradient-flow 14s ease infinite;
}
@keyframes gradient-flow{
  0%{background-position:0% 50%}
  50%{background-position:100% 50%}
  100%{background-position:0% 50%}
}
/* тонкая переливающаяся линия — заголовок раздела, край карточки */
.grad-line{height:3px; border-radius:var(--r-pill); background:var(--grad-brand);
  animation:gradient-flow 14s ease infinite}

/* мягкий брендовый блик вверху экрана — один, не «три пятна» */
.glow{position:fixed; z-index:-1; inset:-320px 0 auto 0; height:560px; pointer-events:none; opacity:.5;
  background:radial-gradient(600px 420px at 50% 50%,rgba(124,108,245,.55),rgba(124,108,245,0) 70%);
  filter:blur(60px)}

/* ---------------------------------------------------------------- МАКЕТ --- */
.wrap{width:100%; max-width:960px; margin:0 auto; padding:var(--s5) var(--s4)}
.wrap--narrow{max-width:600px}
.wrap--wide{max-width:1280px}

.stack{display:flex; flex-direction:column; gap:var(--s4)}
.stack--sm{gap:var(--s2)}
.stack--lg{gap:var(--s5)}
.row{display:flex; align-items:center; gap:var(--s3)}
.row--between{justify-content:space-between}
.row--wrap{flex-wrap:wrap}
.spacer{flex:1}

.grid{display:grid; gap:var(--s4)}
.grid--2{grid-template-columns:repeat(2,1fr)}
.grid--3{grid-template-columns:repeat(3,1fr)}
.grid--4{grid-template-columns:repeat(4,1fr)}

/* ---------------------------------------------------------------- ШАПКА --- */
.appbar{
  position:sticky; top:0; z-index:40; margin-bottom:var(--s5);
  display:flex; align-items:center; gap:var(--s4);
  height:var(--h-lg); padding:0 var(--s3) 0 var(--s4);
  background:rgba(255,255,255,.84); backdrop-filter:blur(18px) saturate(160%);
  border:1px solid var(--border); border-radius:var(--r-pill);
  box-shadow:var(--shadow-1);
}
.brand{display:inline-flex; align-items:center; gap:var(--s2)}
.brand svg{width:24px; height:24px; display:block; border-radius:7px}
.brand__text{font-family:var(--font-display); font-weight:800; font-size:var(--t2); letter-spacing:-.04em; color:var(--ink)}
/* «Ok» — фирменным градиентом (с запасным цветом, если clip:text не поддержан). */
.brand__ok{color:var(--indigo-600)}
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .brand__ok{background:linear-gradient(120deg,#7C6CF5,#4A38DC); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; color:transparent}
}
/* Приглушённый серый не набирал нужного контраста на белом — «.ru» читалось
   с трудом, а это часть имени. Берём цвет потемнее: вид тот же, читается. */
.brand__ru{color:var(--muted); font-weight:700}

/* ---------------------------------------------------------------- КНОПКИ -- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
  height:var(--h-md); padding:0 var(--s5);
  border:1px solid transparent; border-radius:var(--r-pill);
  font-family:var(--font-body); font-size:var(--t3); font-weight:600; letter-spacing:-.01em;
  cursor:pointer; white-space:nowrap; text-decoration:none;
  transition:transform .2s var(--ease), box-shadow .2s var(--ease),
             background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.btn:hover{text-decoration:none}
.btn:active{transform:translateY(1px)}
.btn--lg{height:var(--h-lg); padding:0 var(--s6)}
.btn--sm{height:var(--h-sm); padding:0 var(--s4); font-size:var(--t2)}
/* Страховка от вылета за край: кнопка в строке из нескольких кнопок должна
   уметь сжаться и перенести надпись, а не торчать за карточкой. */
.row > .btn{min-width:0; white-space:normal}
.btn--block{width:100%}
.btn[disabled],.btn.is-disabled{opacity:.45; pointer-events:none}
.btn svg{width:18px; height:18px; flex:none}

.btn--primary{color:#fff; background:var(--grad-action); box-shadow:var(--shadow-action)}
.btn--primary:hover{transform:translateY(-1px); box-shadow:0 12px 32px rgba(74,56,220,.34)}

.btn--soft{background:var(--surface); color:var(--ink); border-color:var(--border); box-shadow:var(--shadow-1)}
.btn--soft:hover{transform:translateY(-1px); border-color:var(--indigo-400)}

.btn--ghost{background:transparent; color:var(--ink-2)}
.btn--ghost:hover{background:rgba(11,11,18,.05)}

.btn--danger{background:var(--err-bg); color:var(--err); border-color:#F1D3CF}
.btn--danger:hover{background:#F8DBD7}

.btn--icon{width:var(--h-md); height:var(--h-md); padding:0; border-radius:var(--r2)}
.btn--icon.btn--sm{width:var(--h-sm); height:var(--h-sm)}

.btn.is-loading{pointer-events:none; color:transparent; position:relative}
.btn.is-loading::after{
  content:''; position:absolute; width:18px; height:18px; border-radius:50%;
  border:2px solid rgba(255,255,255,.35); border-top-color:#fff; animation:spin .8s linear infinite;
}
.btn--soft.is-loading::after,.btn--ghost.is-loading::after{
  border-color:rgba(11,11,18,.15); border-top-color:var(--indigo-500)}
@keyframes spin{to{transform:rotate(360deg)}}

/* Ссылка-действие. Высота 32 даже мышью: в строку текста 16px попадают не с
   первого раза, а на телефоне правило ниже поднимает её до 44. */
/* Ссылка-кнопка — такая же цель для пальца, как обычная кнопка: 44 пункта.
   Раньше здесь стояло 32, и промах бил по соседней строке. */
.linkbtn{border:0; background:none; padding:0 var(--s1); cursor:pointer; color:var(--indigo-600);
  font-family:var(--font-body); font-size:var(--t2); font-weight:600;
  min-height:44px; display:inline-flex; align-items:center; gap:var(--s1)}
.linkbtn:hover{text-decoration:underline}

/* ----------------------------------------------------------------- ПОЛЯ --- */
/* position нужен подсказке: она раскрывается по ширине поля, а не значка «?»,
   иначе на узком окне вылезает за карточку */
.field{position:relative; display:flex; flex-direction:column; gap:var(--s2)}
.lbl{font-size:var(--t2); font-weight:600; color:var(--ink-2)}
.hint{font-size:var(--t2); color:var(--muted)}
.hint--err{color:var(--err)}

.input,.select,.textarea{
  width:100%; height:var(--h-md); padding:0 var(--s4);
  background:var(--surface); color:var(--ink);
  border:1px solid var(--border); border-radius:var(--r2);
  font-family:var(--font-body); font-size:var(--t3); outline:0;
  transition:border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.textarea{height:auto; min-height:96px; padding:var(--s3) var(--s4); resize:vertical; line-height:1.55}
.input::placeholder,.textarea::placeholder{color:var(--muted-2)}
.input:focus,.select:focus,.textarea:focus{border-color:var(--indigo-400); box-shadow:0 0 0 4px rgba(91,75,232,.12)}
.input.is-err,.select.is-err{border-color:#E0A9A2; box-shadow:0 0 0 4px rgba(214,63,50,.1)}
.input[disabled]{background:#F5F6FA; color:var(--muted); cursor:not-allowed}

.select{appearance:none; cursor:pointer; padding-right:var(--s6);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='m5.5 8 4.5 4.5L14.5 8' stroke='%23666C82' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right var(--s3) center; background-size:18px}

.field__row{display:flex; gap:var(--s3)}
.field__row .input{flex:1; min-width:0}

.input--key{height:var(--h-lg); font-family:var(--font-mono); font-size:var(--t6); font-weight:600;
  letter-spacing:.18em; text-align:center; text-transform:uppercase}

.input-wrap{position:relative}
.input-wrap .input{padding-right:var(--h-md)}
.input-wrap__btn{position:absolute; right:var(--s1); top:50%; transform:translateY(-50%);
  font-family:var(--font-body); font-size:var(--t2);
  width:var(--h-sm); height:var(--h-sm); border:0; border-radius:var(--r1); background:transparent;
  cursor:pointer; color:var(--muted); display:flex; align-items:center; justify-content:center}
.input-wrap__btn:hover{background:var(--indigo-50); color:var(--indigo-600)}
.input-wrap__btn svg{width:18px; height:18px}

/* переключатель */
.switch{display:inline-flex; align-items:center; gap:var(--s3); cursor:pointer; user-select:none}
.switch input{position:absolute; opacity:0; pointer-events:none; font-size:var(--t3)}
.switch__track{position:relative; width:44px; height:24px; flex:none; border-radius:var(--r-pill);
  background:#DFE2EC; transition:background .25s var(--ease)}
.switch__track::after{content:''; position:absolute; top:2px; left:2px; width:20px; height:20px;
  border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(16,18,40,.24);
  transition:transform .25s var(--ease-out)}
.switch input:checked + .switch__track{background:var(--grad-action)}
.switch input:checked + .switch__track::after{transform:translateX(20px)}
.switch input:focus-visible + .switch__track{outline:2px solid var(--indigo-500); outline-offset:2px}
.switch__label{font-size:var(--t3)}

/* чекбокс */
.check{display:inline-flex; align-items:center; gap:var(--s3); cursor:pointer}
.check input{position:absolute; opacity:0; pointer-events:none; font-size:var(--t3)}
.check__box{width:20px; height:20px; flex:none; border-radius:6px; border:1.5px solid var(--border);
  background:#fff; display:flex; align-items:center; justify-content:center; transition:all .2s var(--ease)}
.check__box svg{width:12px; height:12px; color:#fff; opacity:0; transition:opacity .2s}
.check input:checked + .check__box{background:var(--indigo-600); border-color:var(--indigo-600)}
.check input:checked + .check__box svg{opacity:1}

/* сегментированный переключатель */
.seg{position:relative; display:inline-grid; grid-auto-flow:column; gap:var(--s1); padding:var(--s1);
  background:#EFF0F6; border-radius:var(--r-pill)}
.seg__btn{height:var(--h-sm); padding:0 var(--s4); border:0; border-radius:var(--r-pill);
  background:transparent; cursor:pointer;
  font-family:var(--font-body); font-size:var(--t2); font-weight:600; color:var(--muted);
  transition:color .25s var(--ease), background .25s var(--ease)}
.seg__btn.is-active{color:#fff; background:var(--grad-action)}
.seg__btn:not(.is-active):hover{color:var(--ink); background:rgba(91,75,232,.08)}

/* -------------------------------------------------------------- КАРТОЧКИ -- */
.card{background:var(--surface); border:1px solid var(--border); border-radius:var(--r3);
  box-shadow:var(--shadow-1)}
.card__head{display:flex; align-items:center; gap:var(--s3); padding:var(--s4)}
.card__head h3,.card__head .card__title{flex:1; min-width:0; font-size:var(--t3)}
.card__body{padding:0 var(--s4) var(--s4)}
.card__foot{display:flex; align-items:center; gap:var(--s3); padding:var(--s4);
  border-top:1px solid var(--border-2); flex-wrap:wrap}
.card--pad{padding:var(--s5)}
.card--accent{border-color:var(--indigo-100); box-shadow:var(--shadow-2)}

.card--fold > .card__head{cursor:pointer; user-select:none}
.card__caret{width:20px; height:20px; flex:none; color:var(--muted);
  transition:transform .3s var(--ease-out)}
.card--fold.is-open .card__caret{transform:rotate(180deg)}
.card--fold > .card__body{display:none}
.card--fold.is-open > .card__body{display:block; animation:foldIn .3s var(--ease-out)}
@keyframes foldIn{from{opacity:0; transform:translateY(-4px)}to{opacity:1; transform:none}}

.card__head .badge{flex:none}
.card__ico{width:var(--h-sm); height:var(--h-sm); flex:none; border-radius:var(--r1); display:flex;
  align-items:center; justify-content:center; background:var(--indigo-50); color:var(--indigo-600)}
.card__ico svg{width:20px; height:20px}

/* ------------------------------------------------------------- СОСТОЯНИЯ -- */
.dot{width:8px; height:8px; border-radius:50%; flex:none; display:inline-block; background:var(--muted-2)}
.dot--ok{background:var(--ok-dot); box-shadow:0 0 0 3px rgba(31,163,107,.18); animation:pulse 2.4s ease-in-out infinite}
.dot--warn{background:var(--warn-dot); box-shadow:0 0 0 3px rgba(217,158,34,.18)}
.dot--err{background:var(--err-dot); box-shadow:0 0 0 3px rgba(214,63,50,.18)}
@keyframes pulse{50%{box-shadow:0 0 0 7px rgba(31,163,107,.05)}}

.badge{display:inline-flex; align-items:center; gap:var(--s2); height:var(--s5); padding:0 var(--s3);
  border-radius:var(--r-pill); font-size:var(--t1); font-weight:600; white-space:nowrap}
.badge--ok{background:var(--ok-bg); color:var(--ok)}
.badge--warn{background:var(--warn-bg); color:var(--warn)}
.badge--err{background:var(--err-bg); color:var(--err)}
.badge--info{background:var(--info-bg); color:var(--info)}
.badge--indigo{background:var(--indigo-50); color:var(--indigo-600)}
.badge--grey{background:#EFF0F6; color:var(--muted)}
/* крестик «убрать» внутри чипа: маленький значок, но нажимать по нему нужно
   пальцем, поэтому область — 24×24, а не размер самого символа */
.badge__x{display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px;
  margin:0 -6px 0 var(--s1); border:0; border-radius:50%; background:transparent; color:inherit;
  cursor:pointer; font-size:var(--t3); line-height:1; transition:background .2s var(--ease)}
.badge__x:hover{background:rgba(11,11,18,.08)}

.note{display:flex; gap:var(--s3); padding:var(--s4); border-radius:var(--r2);
  font-size:var(--t3); line-height:1.55}
.note__ico{width:20px; height:20px; flex:none; margin-top:2px}
.note__ico svg{width:100%; height:100%}
.note b{display:block; margin-bottom:var(--s1)}
.note--ok{background:var(--ok-bg); color:var(--ok)}
.note--warn{background:var(--warn-bg); color:var(--warn)}
.note--err{background:var(--err-bg); color:var(--err)}
.note--info{background:var(--info-bg); color:var(--info)}
.note--plain{background:#F4F5FA; color:var(--ink-2)}
.note__actions{display:flex; gap:var(--s2); margin-top:var(--s3); flex-wrap:wrap}

/* --------------------------------------------------------------- МЕТРИКИ -- */
.stats{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--s3)}
.stat{padding:var(--s4); background:#F6F7FC; border:1px solid var(--border-2); border-radius:var(--r2)}
.stat__val{font-family:var(--font-display); font-size:var(--t6); font-weight:700; letter-spacing:-.045em; line-height:1}
.stat__val small{font-size:var(--t2); font-weight:600; color:var(--muted); margin-left:var(--s1)}
/* «ищут неподдерживаемое» в плитку 150px не влезает одним куском — разрешаем
   перенос внутри слова, иначе подпись обрезается */
/* «израсходовано за месяц» в плитку 150px одним куском не влезает: сначала
   пробуем перенос по слогам, и только в крайнем случае рвём слово */
.stat__cap{margin-top:var(--s2); font-size:var(--t2); color:var(--muted); line-height:1.4;
  hyphens:auto; overflow-wrap:break-word}
.stat--warn{background:var(--warn-bg); border-color:#F2DFB4}
.stat--warn .stat__val{color:var(--warn)}
.stat--err{background:var(--err-bg); border-color:#F1D3CF}
.stat--err .stat__val{color:var(--err)}

.skel{position:relative; overflow:hidden; background:#EBEEF6; border-radius:6px; color:transparent !important}
.skel::after{content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.75),transparent);
  animation:shimmer 1.4s infinite}
@keyframes shimmer{to{transform:translateX(100%)}}
.skel--line{height:12px; margin:var(--s1) 0}
.skel--val{height:var(--s5); width:70%}

/* ---------------------------------------------------------------- СПИСКИ -- */
.list{display:flex; flex-direction:column}
.list__row{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) 0;
  border-bottom:1px solid var(--border-2)}
.list__row:last-child{border-bottom:0}
.list__ico{width:var(--h-sm); height:var(--h-sm); flex:none; border-radius:var(--r1); background:#F2F3F9;
  color:var(--muted); display:flex; align-items:center; justify-content:center}
.list__ico svg{width:18px; height:18px}
.list__main{flex:1; min-width:0}
/* «конфиденциальности» в колонку 200px целиком не влезает — переносим внутри
   слова, иначе строка списка обрезается на узком экране */
.list__main b{display:block; font-size:var(--t3); font-weight:600; overflow-wrap:break-word}
.list__main span{font-size:var(--t2); color:var(--muted); overflow-wrap:break-word}
.list__side{margin-left:auto; text-align:right; font-size:var(--t2); color:var(--muted); white-space:nowrap}
/* Строка-ссылка: вся строка кликабельна, кнопка в каждой строке не нужна.
   Без отрицательных полей — иначе строка вылезает за карточку на телефоне. */
button.list__row{width:100%; text-align:left; font:inherit; color:inherit; cursor:pointer;
  background:none; border:0; border-bottom:1px solid var(--border-2);
  transition:background var(--dur) var(--ease)}
button.list__row:hover{background:#F6F7FC}
.list__go{width:16px; height:16px; flex:none; color:var(--muted-2)}

.country{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) 0;
  border-bottom:1px solid var(--border-2)}
.country:last-child{border-bottom:0}
.country__flag{width:28px; height:20px; flex:none; border-radius:4px; overflow:hidden;
  box-shadow:inset 0 0 0 1px rgba(11,11,18,.08)}
.country__flag svg{width:100%; height:100%; display:block}
.country__name{flex:1; min-width:0; font-size:var(--t3)}
.country__ping{font-size:var(--t2); color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap}

/* ------------------------------------------------------------------ ШАГИ -- */
.steps{display:flex; align-items:center; gap:var(--s2); margin-bottom:var(--s5); flex-wrap:wrap}
.steps--compact{display:none}
.step-pill{display:inline-flex; align-items:center; gap:var(--s2); height:var(--s6); padding:0 var(--s3);
  border-radius:var(--r-pill); background:#EFF0F6; color:var(--muted);
  font-size:var(--t1); font-weight:600; transition:all .25s var(--ease)}
.step-pill__n{width:20px; height:20px; border-radius:50%; background:#fff; color:var(--muted);
  display:flex; align-items:center; justify-content:center; font-size:var(--t1); font-weight:700}
.step-pill.is-done{background:var(--ok-bg); color:var(--ok)}
.step-pill.is-done .step-pill__n{background:var(--ok-dot); color:#fff}
.step-pill.is-current{background:var(--grad-action); color:#fff; box-shadow:var(--shadow-action)}
.step-pill.is-current .step-pill__n{background:rgba(255,255,255,.25); color:#fff}

.bar{height:8px; border-radius:var(--r-pill); background:#EBEEF6; overflow:hidden}
.bar i{display:block; height:100%; width:0; border-radius:var(--r-pill);
  background:var(--grad-brand); animation:gradient-flow 14s ease infinite;
  transition:width .5s var(--ease-out)}

/* журнал установки */
.inst{display:flex; flex-direction:column}
.inst__row{display:flex; align-items:flex-start; gap:var(--s3); padding:var(--s3) 0;
  border-bottom:1px solid var(--border-2)}
.inst__row:last-child{border-bottom:0}
.inst__mark{width:var(--s5); height:var(--s5); flex:none; border-radius:50%; background:#F1F2F8;
  display:flex; align-items:center; justify-content:center; color:var(--muted-2)}
.inst__mark svg{width:14px; height:14px}
.inst__main{flex:1; min-width:0}
.inst__main b{display:block; font-size:var(--t3); font-weight:500; color:var(--muted)}
.inst__note{font-size:var(--t2); color:var(--muted-2); margin-top:var(--s1)}
.inst__row.is-run .inst__mark{background:var(--indigo-50); color:var(--indigo-600)}
.inst__row.is-run .inst__mark::after{content:''; width:12px; height:12px; border-radius:50%;
  border:2px solid var(--indigo-100); border-top-color:var(--indigo-600); animation:spin .8s linear infinite}
.inst__row.is-run .inst__mark svg{display:none}
.inst__row.is-run .inst__main b{color:var(--ink); font-weight:600}
.inst__row.is-done .inst__mark{background:var(--ok-bg); color:var(--ok)}
.inst__row.is-done .inst__main b{color:var(--ink-2)}
.inst__row.is-err .inst__mark{background:var(--err-bg); color:var(--err)}
/* шаг, до которого ещё не дошли: виден, но не притягивает взгляд */
.inst__row.is-wait .inst__mark{background:#F6F7FC; color:var(--muted-2)}
.inst__row.is-wait .inst__main b{color:var(--muted-2)}
/* пропущенный шаг: он не ошибка и не достижение — просто не понадобился */
.inst__row.is-skip .inst__mark{background:#F1F2F8; color:var(--muted-2)}
.inst__row.is-skip .inst__main b{color:var(--muted)}
.inst__row.is-err .inst__main b{color:var(--err)}

/* --------------------------------------------------------------- ТАБЛИЦЫ -- */
.table-wrap{max-width:100%; overflow-x:auto; border:1px solid var(--border); border-radius:var(--r2);
  background:#fff; -webkit-overflow-scrolling:touch}
table.tbl{width:100%; border-collapse:collapse; font-size:var(--t2)}
.tbl th{position:sticky; top:0; z-index:1; background:#F6F7FC; text-align:left; font-weight:600;
  font-size:var(--t1); color:var(--muted); padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--border); white-space:nowrap}
.tbl td{padding:var(--s3) var(--s4); border-bottom:1px solid var(--border-2); vertical-align:middle}
.tbl tr:last-child td{border-bottom:0}
.tbl tbody tr:hover{background:#FAFBFE}
.tbl td.num{text-align:right; font-variant-numeric:tabular-nums}
/* Второстепенные колонки. На широком окне видны, на узком уходят —
   вместо горизонтальной прокрутки, которую в таблице никто не замечает. */
@container app (max-width:1000px){
  .tbl th.opt, .tbl td.opt{display:none}
  /* в админке рабочая область уже окна на ширину меню: четыре числа в ряд
     помещаются только на растянутом окне */
  .admin .stats{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* второстепенные показатели: на узком окне они только удлиняют экран */
  .stat--opt{display:none}
}

/* Кусок журнала установки в админке: читаем глазами, копируем целиком. */
.log{margin:0; padding:var(--s3) var(--s4); background:#F6F7FC; border:1px solid var(--border-2);
  border-radius:var(--r1); font-family:var(--font-mono); font-size:var(--t1); line-height:1.6;
  color:var(--ink-2); white-space:pre; overflow-x:auto; -webkit-overflow-scrolling:touch}

/* --------------------------------------------------------------- МОДАЛКИ -- */
.overlay{position:fixed; inset:0; z-index:80; display:flex; align-items:center; justify-content:center;
  padding:var(--s4); background:rgba(11,11,18,.42); backdrop-filter:blur(6px);
  animation:fadeIn .2s var(--ease)}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.modal{width:100%; max-width:480px; background:#fff; border-radius:var(--r3);
  box-shadow:var(--shadow-2); animation:modalIn .3s var(--ease-out); max-height:90vh; overflow:auto}
.modal--wide{max-width:680px}
@keyframes modalIn{from{opacity:0; transform:translateY(12px)}to{opacity:1; transform:none}}
.modal__head{display:flex; align-items:flex-start; gap:var(--s3); padding:var(--s5) var(--s5) 0}
.modal__head h3{flex:1}
.modal__close{width:var(--h-sm); height:var(--h-sm); border:0; border-radius:var(--r1); background:#F2F3F9;
  cursor:pointer; color:var(--muted); display:flex; align-items:center; justify-content:center; flex:none}
.modal__close:hover{background:#E8EAF2; color:var(--ink)}
.modal__close svg{width:16px; height:16px}
.modal__body{padding:var(--s4) var(--s5)}
.modal__foot{display:flex; gap:var(--s3); padding:0 var(--s5) var(--s5)}
.modal__foot .btn{flex:1}

/* QR */
.qr{display:flex; flex-direction:column; align-items:center; gap:var(--s4); padding:var(--s5);
  background:#F6F7FC; border-radius:var(--r2)}
.qr__img{width:184px; height:184px; background:#fff; border-radius:var(--r2); padding:var(--s3);
  box-shadow:var(--shadow-1)}
.qr__img svg,.qr__img img{width:100%; height:100%; display:block}
.qr__cred{text-align:center}
.qr__cred b{display:block; font-family:var(--font-display); font-size:var(--t4); letter-spacing:-.03em}
.qr__cred span{font-family:var(--font-mono); font-size:var(--t2); color:var(--muted)}

/* ------------------------------------------------------- ПУСТОЕ СОСТОЯНИЕ -- */
.empty{display:flex; flex-direction:column; align-items:center; gap:var(--s3); padding:var(--s6) var(--s4);
  text-align:center}
.empty__art{width:160px; height:120px}
.empty__art svg{width:100%; height:100%; display:block}
.empty b{font-size:var(--t3)}
.empty span{font-size:var(--t2); color:var(--muted); max-width:320px}

/* ---------------------------------------------------------- ИЛЛЮСТРАЦИИ --- */
/* Все сцены — одна линия 2px, индиго с пастельной подложкой.
   Анимации отвечают за смысл: поиск ищет, установка идёт, ошибка замерла. */
/* Сцена — блочный элемент фиксированной ширины: без auto-полей она липнет
   к левому краю, и весь экран выглядит перекошенным. */
.art{display:block; margin-inline:auto}
.art--sm{width:120px; height:96px}
.art--md{width:200px; height:150px}
.art--lg{width:280px; height:200px}

/* радар поиска роутера */
.art .radar-ring{transform-origin:center; opacity:0; animation:radar 3s ease-out infinite}
.art .radar-ring:nth-of-type(2){animation-delay:1s}
.art .radar-ring:nth-of-type(3){animation-delay:2s}
@keyframes radar{0%{opacity:.55; transform:scale(.35)}100%{opacity:0; transform:scale(1)}}

/* индикаторы роутера */
.art .led{animation:led 2.4s ease-in-out infinite}
.art .led:nth-of-type(2){animation-delay:.3s}
.art .led:nth-of-type(3){animation-delay:.6s}
@keyframes led{50%{opacity:.25}}

/* пакет, бегущий по проводу */
.art .packet{offset-rotate:0deg; animation:packet 2.6s var(--ease) infinite}
@keyframes packet{0%{offset-distance:0%; opacity:0}12%{opacity:1}88%{opacity:1}100%{offset-distance:100%; opacity:0}}

/* лёгкое покачивание сцены */
.art .float{animation:float 6s ease-in-out infinite}
@keyframes float{50%{transform:translateY(-4px)}}

/* ------------------------------------------------------- ОКНО ПРОГРАММЫ --- */
/* Это не сайт: окно Windows 1180×860, меньше 900×640 не бывает, растянуть
   на весь экран нельзя. Поэтому раскладка рассчитана на почти квадратное
   окно — колонка по центру оставила бы половину окна пустой.
   Тот же макет на Android схлопывается в одну колонку. */
/* Раскладка считается от ширины самого окна программы, а не от экрана:
   в Electron окно бывает 900, а монитор — 2560. Поэтому container, а не media. */
.app{display:flex; flex-direction:column; height:100%; min-height:0; padding:var(--s4);
  gap:var(--s4); overflow:hidden; container-type:inline-size; container-name:app}
.app__body{flex:1; min-height:0; overflow:auto; padding-right:var(--s1)}

/* мастер: слева действие, справа — что происходит */
.wiz{display:grid; grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr); gap:var(--s4);
  align-items:start}
.wiz__main{display:flex; flex-direction:column; gap:var(--s4)}
.wiz__side{display:flex; flex-direction:column; gap:var(--s4); position:sticky; top:0}

/* панель: две колонки карточек */
.dash{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:var(--s4); align-items:start}
.dash__col{display:flex; flex-direction:column; gap:var(--s4)}
.dash__wide{grid-column:1 / -1}

/* Базовый размер окна — 900×640, он же минимальный. Две колонки живут
   от 720: при 900 это 418+418, читается нормально. Ниже 720 — одна. */
@container app (max-width:720px){
  /* именно minmax(0,1fr): просто 1fr не даёт колонке быть уже содержимого,
     и карточки начинают торчать за край окна */
  .wiz,.dash{grid-template-columns:minmax(0,1fr)}
  .wiz__side{position:static}
}

/* QR внутри карточки показываем, только когда окно растянули: в базовом 900
   он съедает половину карточки, а тот же код открывается кнопкой */
.qr--narrow{display:none}
@container app (max-width:1100px){
  .qr--wide{display:none}
  .qr--narrow{display:inline-flex}
  /* две колонки внутри карточки при 418px превращаются в кашу */
  .card__body .grid--2{grid-template-columns:1fr}
}

/* телефон: тесно — уменьшаем поля, кнопки во всю ширину, крупные тапы */
@container app (max-width:640px){
  .app{padding:var(--s3); gap:var(--s3)}
  .switch{min-height:44px}
  .check{min-height:44px}
  .grid--2,.grid--3,.grid--4{grid-template-columns:minmax(0,1fr)}
  /* числа короткие — держим их по два в ряд, иначе четыре плитки занимают
     весь экран и до содержимого приходится листать */
  .stats{grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s2)}
  .card--pad{padding:var(--s4)}
  .steps{gap:var(--s1)}
  .step-pill{font-size:11px; padding:0 var(--s2)}
  /* длинную надпись на кнопке лучше перенести, чем обрезать окно */
  .btn{white-space:normal; min-width:0; padding-inline:var(--s4)}
  /* кнопки делят строку и переносятся только когда действительно не влезают:
     растягивать каждую на всю ширину — три строки там, где хватает одной */
  .row .btn{flex:0 1 auto; min-width:0}
  /* распорка на телефоне съедала остаток строки и выталкивала кнопки по одной —
     пусть переносится сама, а кнопки встают одной строкой под заголовком */
  .row--wrap .spacer{flex-basis:100%; height:0}
  .row:has(.btn){flex-wrap:wrap}
  /* сегментированный переключатель в строку не влезает — ставим в столбик */
  .seg{width:100%; grid-auto-flow:row}
  .seg__btn{width:100%}
  /* Палец — не мышь: любая цель не меньше 44px. Ссылку-кнопку и «показать
     пароль» на десктопе видно и в 16px, на телефоне в них не попасть. */
  .linkbtn{min-height:44px; display:inline-flex; align-items:center; justify-content:center}
  .input-wrap__btn{width:44px; height:44px}
  .btn--sm{height:var(--h-md)}
  .field__row{flex-direction:column}
  .field__row .btn{width:100%}
  h1{font-size:var(--t6)}
}

/* совсем узко — полоса шагов превращается в строку «шаг 6 из 7» */
/* Полоса шагов переносится на вторую строку раньше, чем кончается место:
   шесть пилюль требуют около 700px. Ниже — строка «шаг N из 6» с полосой. */
@container app (max-width:760px){
  .steps{display:none}
  .steps--compact{display:flex}
}

@container app (max-width:460px){
  /* на телефоне значок состояния съедает ширину заголовка карточки — уводим
     его под заголовок: пустой элемент с flex-basis:100% ломает строку */
  .card__head{flex-wrap:wrap}
  .card__head .card__caret{order:1}
  .card__head::after{content:''; order:2; flex-basis:100%; height:0}
  .card__head .badge{order:3; margin-left:calc(var(--h-sm) + var(--s3)); margin-top:calc(var(--s2) * -1)}
}

/* макет телефона в списке сетей — приём из текущей программы: человек сразу
   узнаёт экран, который увидит на телефоне */
.wifilist{border:1px solid var(--border); border-radius:var(--r2); overflow:hidden; background:#fff}
.wifilist__row{display:flex; align-items:center; gap:var(--s3); padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--border-2); font-size:var(--t3)}
.wifilist__row:last-child{border-bottom:0}
.wifilist__row.is-ours{background:var(--indigo-50); font-weight:600; color:var(--indigo-700)}
.wifilist__row.is-muted{color:var(--muted)}
.wifilist__ico{margin-left:auto; display:flex; gap:var(--s2); color:var(--muted-2)}
.wifilist__ico svg{width:16px; height:16px}
.wifilist__row.is-ours .wifilist__ico{color:var(--indigo-600)}

/* ------------------------------------------------------------ АДМИНКА ----- */
/* Внутренний инструмент: слева разделы, справа рабочая область. Плотность выше,
   чем в клиентской панели — здесь смотрят таблицы, а не «одно действие». */
/* Контейнер — обёртка: элемент не может реагировать на собственный
   контейнерный запрос, поэтому .admin им быть не должен. */
.app-root{height:100%; min-height:0; container-type:inline-size; container-name:app}
.admin{display:grid; grid-template-columns:236px minmax(0,1fr); height:100%; min-height:0}
.admin__side{display:flex; flex-direction:column; gap:var(--s1); padding:var(--s4);
  border-right:1px solid var(--border); background:#fff; overflow:auto}
/* Только вертикальная прокрутка: горизонтальную даёт .table-wrap у таблиц,
   а всё остальное обязано умещаться в окно. */
.admin__main{min-width:0; display:flex; flex-direction:column; gap:var(--s4);
  padding:var(--s4); overflow-y:auto; overflow-x:hidden}

.navitem{display:flex; align-items:center; gap:var(--s3); padding:var(--s3);
  border:0; border-radius:var(--r1); background:transparent; cursor:pointer; text-align:left;
  font-family:var(--font-body); font-size:var(--t2); color:var(--ink-2); width:100%;
  transition:background .2s var(--ease), color .2s var(--ease)}
.navitem:hover{background:rgba(91,75,232,.08)}
.navitem.is-active{background:var(--grad-action); color:#fff}
.navitem svg{width:18px; height:18px; flex:none}
.navitem__count{margin-left:auto; font-size:var(--t1); font-weight:600; opacity:.7}

/* строка фильтров */
.chips{display:flex; flex-wrap:wrap; gap:var(--s2)}
.chip-f{display:inline-flex; align-items:center; gap:var(--s2); height:var(--h-sm); padding:0 var(--s3);
  border:1px solid var(--border); border-radius:var(--r-pill); background:#fff; cursor:pointer;
  font-family:var(--font-body); font-size:var(--t2); color:var(--ink-2);
  transition:border-color .2s var(--ease), background .2s var(--ease), color .2s var(--ease)}
.chip-f:hover{border-color:var(--indigo-400)}
.chip-f.is-on{background:var(--indigo-50); border-color:var(--indigo-100); color:var(--indigo-700); font-weight:600}
.chip-f b{font-weight:700}

/* воронка установок */
.funnel{display:flex; flex-direction:column; gap:var(--s2)}
.funnel__row{display:grid; grid-template-columns:180px minmax(0,1fr) 96px; gap:var(--s3); align-items:center}
.funnel__name{font-size:var(--t2); color:var(--ink-2)}
.funnel__bar{height:26px; border-radius:var(--r1); background:#EEF0F6; overflow:hidden}
.funnel__bar i{display:block; height:100%; border-radius:var(--r1); background:var(--grad-action)}
.funnel__row.is-drop .funnel__bar i{background:linear-gradient(135deg,#E4785F,#D63F32)}
.funnel__val{font-size:var(--t2); text-align:right; font-variant-numeric:tabular-nums; color:var(--muted)}
.funnel__val b{color:var(--ink)}

/* страницы таблицы */
.pager{display:flex; align-items:center; justify-content:space-between; gap:var(--s3); flex-wrap:wrap}
.pager__pages{display:flex; gap:var(--s1)}
.pager__pages button{min-width:var(--h-sm); height:var(--h-sm); padding:0 var(--s2); border:1px solid var(--border);
  border-radius:var(--r1); background:#fff; cursor:pointer; font-family:var(--font-body); font-size:var(--t2)}
.pager__pages button.is-on{background:var(--grad-action); color:#fff; border-color:transparent}

/* узкое окно админки: разделы прячутся в верхнюю строку */
@container app (max-width:820px){
  .admin{grid-template-columns:minmax(0,1fr); grid-template-rows:auto minmax(0,1fr)}
  .admin__side{flex-direction:row; overflow-x:auto; border-right:0; border-bottom:1px solid var(--border);
    padding:var(--s3)}
  .navitem{width:auto; white-space:nowrap}
  .navitem__count{display:none}
  .funnel__row{grid-template-columns:120px minmax(0,1fr) 72px}
}

/* совсем узко (телефон поддержки): списки и страницы переносятся по строкам */
@container app (max-width:560px){
  .admin__main{padding:var(--s3)}
  /* чипы и страницы — тоже пальцем: 36px мало (правило стоит здесь, а не
     выше по файлу, иначе его перебивает базовая высота .chip-f) */
  .chip-f{height:var(--h-md)}
  .pager__pages button{min-width:var(--h-md); height:var(--h-md)}
  /* таблица и так прокручивается вбок: рвать «485 дней» на две строки незачем */
  .tbl th,.tbl td{white-space:nowrap}
  /* когда пометка «Через веб» переезжает под текст, цветная точка рядом с ней
     становится лишней: цвет уже несёт сама пометка */
  .list__row .way{display:none}
  .list__row{flex-wrap:wrap}
  /* правая колонка списка на телефоне встаёт под текст и переносится:
     «заливка 2:10, ожидание роутера 5:00» в строку уже не помещается */
  .list__side{margin-left:0; width:100%; text-align:left; white-space:normal}
  .pager{flex-direction:column; align-items:flex-start}
  .pager__pages{flex-wrap:wrap}
  .funnel__row{grid-template-columns:minmax(0,1fr); gap:var(--s1)}
  .funnel__val{text-align:left}
  .stat__val{font-size:var(--t5)}
}

/* --------------------------------------------------------------- ФЛАГИ ---- */
/* Рисуются flags.js — эмодзи нельзя: на Windows их нет. */
.flag{width:28px; height:20px; flex:none; border-radius:4px; overflow:hidden; display:block;
  box-shadow:inset 0 0 0 1px rgba(11,11,18,.1)}
.flag svg{width:100%; height:100%; display:block}
.flag--sm{width:20px; height:14px; border-radius:3px}
.flag--lg{width:40px; height:28px; border-radius:6px}
/* если страны нет в наборе — код двумя буквами, а не пустое место */
.flag--code{display:flex; align-items:center; justify-content:center; background:#EFF0F6;
  font-family:var(--font-mono); font-size:var(--t1); font-weight:600; color:var(--muted)}

/* -------------------------------------------------------------- СЛАЙДЕРЫ -- */
/* Одинаковые в Chrome и Firefox: у них разные псевдоэлементы, поэтому
   правила продублированы — иначе ползунок в одном браузере уезжает. */
.range{-webkit-appearance:none; appearance:none; width:100%; height:var(--s5); background:transparent;
  cursor:pointer; display:block}
.range::-webkit-slider-runnable-track{height:8px; border-radius:var(--r-pill);
  background:linear-gradient(90deg,var(--indigo-500) var(--fill,50%),#E6E9F1 var(--fill,50%))}
.range::-moz-range-track{height:8px; border-radius:var(--r-pill); background:#E6E9F1}
.range::-moz-range-progress{height:8px; border-radius:var(--r-pill); background:var(--indigo-500)}
.range::-webkit-slider-thumb{-webkit-appearance:none; appearance:none; width:24px; height:24px;
  margin-top:-8px; border-radius:50%; background:#fff; border:2px solid var(--indigo-500);
  box-shadow:0 2px 6px rgba(16,18,40,.2); transition:transform .15s var(--ease)}
.range::-moz-range-thumb{width:24px; height:24px; border-radius:50%; background:#fff;
  border:2px solid var(--indigo-500); box-shadow:0 2px 6px rgba(16,18,40,.2)}
.range:hover::-webkit-slider-thumb{transform:scale(1.1)}
.range:active::-webkit-slider-thumb{transform:scale(.95)}
.range:focus-visible::-webkit-slider-thumb{outline:2px solid var(--indigo-500); outline-offset:3px}

/* вертикальный: нужен для «сколько трафика отдать» и подобных настроек */
.range--v{writing-mode:vertical-lr; direction:rtl; width:var(--s5); height:160px}
.range--v::-webkit-slider-runnable-track{width:8px; height:100%;
  background:linear-gradient(0deg,var(--indigo-500) var(--fill,50%),#E6E9F1 var(--fill,50%))}
.range--v::-webkit-slider-thumb{margin-top:0; margin-left:-8px}

.range-row{display:flex; align-items:center; gap:var(--s4)}
.range-ticks{display:flex; justify-content:space-between; margin-top:var(--s2)}
.range-ticks span{font-size:var(--t1); color:var(--muted); cursor:pointer; padding:var(--s1) var(--s2);
  border-radius:var(--r1); transition:color .2s var(--ease), background .2s var(--ease)}
.range-ticks span:hover{color:var(--ink); background:var(--indigo-50)}
.range-ticks span.is-active{color:var(--indigo-600); font-weight:700; background:var(--indigo-50)}
.range-row__val{min-width:88px; text-align:right; font-family:var(--font-mono);
  font-size:var(--t3); font-weight:600; font-variant-numeric:tabular-nums}

/* ------------------------------------------------------- ВЫБОР ОДНОГО ----- */
/* Радио-карточки: выбран ровно один, остальные гаснут — видно, что выбор снят. */
.choices{display:grid; gap:var(--s3)}
.choice{position:relative; display:flex; align-items:flex-start; gap:var(--s3); padding:var(--s4);
  border:1.5px solid var(--border); border-radius:var(--r2); background:var(--surface); cursor:pointer;
  transition:border-color .25s var(--ease), background .25s var(--ease), opacity .25s var(--ease)}
.choice input{position:absolute; opacity:0; pointer-events:none; font-size:var(--t3)}
.choice__mark{width:20px; height:20px; flex:none; margin-top:2px; border-radius:50%;
  border:1.5px solid var(--border); background:#fff; position:relative;
  transition:border-color .25s var(--ease)}
.choice__mark::after{content:''; position:absolute; inset:4px; border-radius:50%;
  background:var(--indigo-600); transform:scale(0); transition:transform .25s var(--ease-out)}
.choice__body b{display:block; font-size:var(--t3); font-weight:600}
.choice__body span{font-size:var(--t2); color:var(--muted); line-height:1.5}
.choice:hover{border-color:var(--indigo-400)}
.choice input:checked ~ .choice__mark{border-color:var(--indigo-600)}
.choice input:checked ~ .choice__mark::after{transform:scale(1)}
.choice:has(input:checked){border-color:var(--indigo-600); background:var(--indigo-50)}
/* невыбранные приглушаются — сразу видно, что выбор переключился */
.choices:has(input:checked) .choice:not(:has(input:checked)){opacity:.55}
.choices:has(input:checked) .choice:not(:has(input:checked)):hover{opacity:1}

/* -------------------------------------------------- ПОДСКАЗКИ НОВИЧКУ ----- */
/* Человек не разбирается в сетях: там, где он может растеряться, рядом стоит
   пояснение, а не значок вопроса, который ещё надо догадаться нажать. */
.tip{position:relative; display:inline-flex; align-items:center; justify-content:center;
  width:20px; height:20px; border-radius:50%; background:#EFF0F6; color:var(--muted);
  font-size:var(--t1); font-weight:700; cursor:help; flex:none}
.tip:hover{background:var(--indigo-50); color:var(--indigo-600)}
.tip__box{position:absolute; bottom:calc(100% + 10px); left:0; right:0; transform:translateY(4px);
  width:auto; padding:var(--s3); border-radius:var(--r2); background:var(--ink); color:#fff;
  font-size:var(--t2); font-weight:400; line-height:1.5; text-align:left;
  opacity:0; pointer-events:none; transition:opacity .2s var(--ease), transform .2s var(--ease-out); z-index:60}
.tip__box::after{content:''; position:absolute; top:100%; left:16px;
  border:6px solid transparent; border-top-color:var(--ink)}
.tip:hover .tip__box,.tip:focus-visible .tip__box{opacity:1; transform:none}

/* указатель со стрелкой: «нажмите сюда» на первом запуске */
.coach{position:relative; display:flex; gap:var(--s3); padding:var(--s4);
  border-radius:var(--r2); background:var(--ink); color:#fff; font-size:var(--t2); line-height:1.5;
  box-shadow:var(--shadow-2); max-width:320px}
.coach b{display:block; font-size:var(--t3); margin-bottom:var(--s1)}
.coach::after{content:''; position:absolute; border:8px solid transparent}
.coach--up::after{bottom:100%; left:24px; border-bottom-color:var(--ink)}
.coach--down::after{top:100%; left:24px; border-top-color:var(--ink)}
.coach--left::after{right:100%; top:20px; border-right-color:var(--ink)}
.coach--right::after{left:100%; top:20px; border-left-color:var(--ink)}
.coach__step{font-family:var(--font-mono); font-size:var(--t1); color:rgba(255,255,255,.6)}

/* пульсирующая метка — притягивает взгляд к нужной кнопке */
.pulse{position:relative; display:inline-flex}
.pulse::before{content:''; position:absolute; inset:-6px; border-radius:inherit;
  border:2px solid var(--indigo-400); opacity:0; animation:pulseRing 2.4s ease-out infinite}
@keyframes pulseRing{0%{opacity:.8; transform:scale(.94)}100%{opacity:0; transform:scale(1.06)}}

/* легенда цветов — что означает каждый цвет в этой панели */
.legend{display:flex; flex-wrap:wrap; gap:var(--s4); padding:var(--s4);
  background:#F6F7FC; border-radius:var(--r2)}
.legend span{display:inline-flex; align-items:center; gap:var(--s2); font-size:var(--t2); color:var(--muted)}

/* ------------------------------------------------------------ МОБИЛЬНОЕ --- */
/* Нижняя шторка вместо окна: на телефоне окно посередине неудобно —
   до кнопок далеко, а шторка приходит снизу, под большой палец. */
.sheet{position:fixed; left:0; right:0; bottom:0; z-index:90; max-height:88vh; overflow:auto;
  background:#fff; border-radius:var(--r3) var(--r3) 0 0; box-shadow:var(--shadow-2);
  padding:var(--s3) var(--s4) calc(var(--s5) + env(safe-area-inset-bottom));
  animation:sheetIn .3s var(--ease-out)}
@keyframes sheetIn{from{transform:translateY(100%)}to{transform:none}}
.sheet__grip{width:44px; height:4px; border-radius:2px; background:#DFE2EC; margin:0 auto var(--s4)}

/* липкая панель действий — кнопка шага всегда под рукой */
.actionbar{position:sticky; bottom:0; z-index:30; display:flex; gap:var(--s3);
  padding:var(--s3) 0 calc(var(--s3) + env(safe-area-inset-bottom));
  background:linear-gradient(180deg,rgba(247,248,251,0),var(--bg) 40%)}
.actionbar .btn{flex:1}

/* тап-цель: всё кликаемое на телефоне не меньше 44px */
@media (pointer:coarse){
  .btn--sm{height:var(--h-md)}
  .switch__track{width:52px; height:30px}
  .switch__track::after{width:26px; height:26px}
  .switch input:checked + .switch__track::after{transform:translateX(22px)}
  .check__box{width:24px; height:24px}
  .list__row,.country{padding:var(--s4) 0}
  .modal__close{width:var(--h-md); height:var(--h-md)}
}

/* --------------------------------------------------------------- АДАПТИВ --
   Здесь только оболочка страниц-витрин (.wrap, .appbar): она живёт в окне
   браузера, поэтому ей @media подходит.

   Компоненты приложения — карточки, сетки, кнопки, плитки — перестроены выше
   контейнерными запросами @container app. Дублировать их здесь нельзя: в
   Electron ширина окна не равна ширине экрана, и два набора правил начинают
   спорить (кнопка получала width:100% от @media, хотя по контейнеру должна
   была делить строку). */
@media (max-width:600px){
  .wrap{padding:var(--s4) var(--s3)}
  .appbar{height:var(--h-md); padding:0 var(--s2) 0 var(--s3); margin-bottom:var(--s4)}
}

/* ----------------------------------------------------- ПОИСК ПО МОДЕЛЯМ --- */
/* Совпавшая часть названия подсвечивается — человек видит, почему строка тут. */
.hl{background:var(--indigo-50); color:var(--indigo-700); border-radius:4px; padding:0 2px}
/* Результаты появляются по очереди: это читается как «ищем», а не «мигнуло». */
.stagger > *{animation:riseIn .28s var(--ease) both}
.stagger > *:nth-child(1){animation-delay:.02s}
.stagger > *:nth-child(2){animation-delay:.06s}
.stagger > *:nth-child(3){animation-delay:.1s}
.stagger > *:nth-child(4){animation-delay:.14s}
.stagger > *:nth-child(5){animation-delay:.18s}
@keyframes riseIn{from{opacity:0; transform:translateY(6px)}to{opacity:1; transform:none}}
/* Кружок пути слева: индиго — ставим сами, янтарь — по инструкции,
   красный — не тянет. Зелёный не трогаем: он занят живым «VPN работает». */
.way{width:10px; height:10px; flex:none; border-radius:50%; background:var(--indigo-600);
  align-self:flex-start; margin-top:6px}
.way--manual{background:var(--warn)}
.way--no{background:var(--err)}
.searchbig .input{height:var(--h-lg); font-size:var(--t4); padding-left:var(--s7)}
.searchbig{position:relative}
.searchbig__ico{position:absolute; left:var(--s4); top:50%; transform:translateY(-50%);
  width:20px; height:20px; color:var(--muted-2); pointer-events:none}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important}
  .grad-text{animation:none}
}

/* ------------------------------------------- УТИЛИТЫ ВМЕСТО style="" ---
   Инлайновые стили в разметке заставляют разрешать их правилом безопасности
   целиком — а это лазейка, через которую подменяют вид кнопки «оплатить» или
   кладут невидимую накладку поверх формы. Эти классы закрывают всё типовое;
   вычисляемые значения ставит код после отрисовки. */
.t3{font-size:var(--t3)} .t4{font-size:var(--t4)} .t5{font-size:var(--t5)}
.t6{font-size:var(--t6)} .t22{font-size:22px}
.gap2{gap:var(--s2)} .gap3{gap:var(--s3)} .gap4{gap:var(--s4)}
.mt2{margin-top:var(--s2)} .mt3{margin-top:var(--s3)}
.mt4{margin-top:var(--s4)} .mt5{margin-top:var(--s5)} .mt6{margin-top:6px}
.mb2{margin-bottom:var(--s2)}
.py2{padding:var(--s2) 0} .p4{padding:var(--s4)}
.pt3{padding-top:var(--s3)} .pt4{padding-top:var(--s4)}
.to-right{justify-content:flex-end}
.align-top{align-items:flex-start} .align-center{align-items:center}
.centered{text-align:center}
.block{display:block} .medium{font-weight:500} .bold{font-weight:600}
.display{font-family:var(--font-display); letter-spacing:-.03em}
.clickable{cursor:pointer}
.danger{color:var(--err-dot)} .dim{color:var(--muted)}
.grow{flex:1} .grow220{flex:1 1 220px} .no-flex{flex:none} .shrink{min-width:0}
.w110{max-width:110px} .w120{max-width:120px} .w160{max-width:160px}
.w180{max-width:180px} .w200{max-width:200px} .w460{max-width:460px}
.mt4-auto{margin:var(--s4) auto 0}
.prewrap{white-space:pre-wrap} .va-2{vertical-align:-2px}
.topline{border-top:1px solid var(--border-2)}
.pad-bottom{padding:0 var(--s5) var(--s5)}
.ic14{width:14px; height:14px}
.dot20{width:20px; height:20px; border-radius:50%; flex:0 0 auto}
.dot20--on{background:var(--accent); display:inline-flex; align-items:center; justify-content:center}
.dot20--off{border:2px solid var(--indigo-200,#d7d3f7); display:inline-block}
.to-center{justify-content:center}
.above{position:relative; z-index:1}
.pt6{padding-top:var(--s6)}
