/* DTsoCk-VPN: оформление панели.
   Взято из проекта DTsoCk-VPN (panel.rats.dtsock.ru) — единый стиль с прежней панелью.
   Ниже — дополнения для страницы замера скорости. */
:root{
  --bg:#0b0e13; --bg2:#111621; --card:#151b26; --card2:#1d2532; --card3:#232c3b;
  --line:#252e3d; --line2:#333e50;
  --txt:#e9eef7; --muted:#8e9cb3; --dim:#6b7789;
  --acc:#4cc2ff; --acc2:#2a8fd0; --ok:#35c07f; --bad:#e0655f; --warn:#e0b64a;
  --r:18px; --rl:12px;
  --sh:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.6);
}
*{box-sizing:border-box}
html,body{margin:0;padding:0;max-width:100%;overflow-x:hidden}
body{
  background:
    radial-gradient(60% 40% at 25% 0%, rgba(151,117,250,.09), transparent 60%),
    radial-gradient(50% 50% at 88% 8%, rgba(34,211,238,.07), transparent 55%),
    var(--bg);
  background-attachment:fixed;
  color:var(--txt);font:15px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  padding-bottom:calc(74px + env(safe-area-inset-bottom));-webkit-text-size-adjust:100%;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--acc);text-decoration:none}
h1{font-size:21px;margin:18px 0 12px;line-height:1.25;letter-spacing:-.2px}
h2{font-size:12.5px;margin:0 0 12px;color:#a9b6c9;letter-spacing:.9px;text-transform:uppercase;font-weight:650}
h3{font-size:14px;margin:16px 0 6px}
.muted{color:var(--muted)}
.small{font-size:12.5px}
.mono{font-family:ui-monospace,"SF Mono",Consolas,monospace}
.wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}

.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding:11px 14px;background:rgba(11,14,19,.80);backdrop-filter:blur(12px) saturate(1.4);
  border-bottom:1px solid rgba(255,255,255,.055);border-radius:0 0 16px 16px}
.brand{font-weight:680;display:flex;align-items:center;gap:9px;letter-spacing:-.2px}
.dot{width:10px;height:10px;border-radius:50%;background:var(--acc);
  box-shadow:0 0 0 3px rgba(76,194,255,.14), 0 0 14px rgba(76,194,255,.75)}
.who{display:flex;align-items:center;gap:10px;min-width:0}
.who>span{max-width:38vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.who form{display:inline}
.content{padding:14px;max-width:1180px;margin:0 auto;min-width:0}

.card{background:linear-gradient(180deg,rgba(255,255,255,.022),rgba(255,255,255,0)) ,var(--card);
  border:1px solid var(--line);border-radius:var(--r);padding:16px;margin:14px 0;box-shadow:var(--sh)}
.card.tight{padding:14px}
.card.narrow{max-width:430px;margin:0}
/* вход: карточка по центру экрана и по горизонтали, и по вертикали */
.loginwrap{min-height:calc(100dvh - 130px);display:flex;flex-direction:column;
  justify-content:center;align-items:center;padding:18px 0}
.loginwrap .card{width:100%;margin:0}
.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:14px 0}
.stat{position:relative;background:linear-gradient(180deg,rgba(255,255,255,.03),rgba(255,255,255,0)),var(--card);
  border:1px solid var(--line);border-radius:var(--r);padding:14px;min-width:0;box-shadow:var(--sh);overflow:hidden}
.stat::after{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(180deg,var(--acc),transparent)}
.stat.acc{background:linear-gradient(135deg,rgba(34,211,238,.10) 0%,rgba(6,182,212,.05) 100%),var(--card);border-color:rgba(34,211,238,.28)}
.stat.acc::after{background:linear-gradient(180deg,#22d3ee,transparent)}
.stat.ok{background:linear-gradient(135deg,rgba(64,192,87,.10) 0%,rgba(55,178,77,.05) 100%),var(--card);border-color:rgba(64,192,87,.28)}
.stat.ok::after{background:linear-gradient(180deg,#40c057,transparent)}
.stat.warn{background:linear-gradient(135deg,rgba(250,176,5,.10) 0%,rgba(245,159,0,.05) 100%),var(--card);border-color:rgba(250,176,5,.28)}
.stat.warn::after{background:linear-gradient(180deg,#fab005,transparent)}
.stat.bad{background:linear-gradient(135deg,rgba(250,82,82,.10) 0%,rgba(224,49,49,.05) 100%),var(--card);border-color:rgba(250,82,82,.28)}
.stat.bad::after{background:linear-gradient(180deg,#fa5252,transparent)}
.stat.violet{background:linear-gradient(135deg,rgba(151,117,250,.10) 0%,rgba(132,94,247,.05) 100%),var(--card);border-color:rgba(151,117,250,.28)}
.stat.violet::after{background:linear-gradient(180deg,#9775fa,transparent)}
.stat .n{font-size:22px;font-weight:680;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.4px}
.stat .l{color:var(--muted);font-size:11.5px;margin-top:3px;text-transform:uppercase;letter-spacing:.5px}
.row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;min-width:0}
.row.between{justify-content:space-between}
.row.end{justify-content:flex-end}
.pill{display:inline-flex;align-items:center;gap:6px;background:var(--card2);border:1px solid var(--line);
  border-radius:999px;padding:4px 11px;margin:4px 6px 0 0;font-size:12.5px;white-space:nowrap;color:#c6d1e0}
.pill.ok{border-color:#1f6f43;background:rgba(53,192,127,.10);color:#8ee0b0}
.pill.bad{border-color:#7a3230;background:rgba(224,101,95,.10);color:#f0a6a4}
.pill.warn{border-color:#7a6a20;background:rgba(224,182,74,.10);color:#e8d38a}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;background:var(--card2);color:var(--txt);
  border:1px solid var(--line2);border-radius:var(--rl);padding:10px 15px;font-size:14px;font-weight:550;cursor:pointer;
  min-height:44px;white-space:nowrap;transition:border-color .15s, background .15s, transform .06s, filter .15s}
.btn:hover{border-color:#41506a;background:var(--card3)}
.btn:active{transform:translateY(1px)}
.btn.primary{background:linear-gradient(180deg,#38a9e2,#1e7aa8);border-color:#3ba6dd;color:#fff;font-weight:640;
  box-shadow:0 4px 14px -6px rgba(56,169,226,.8)}
.btn.primary:hover{filter:brightness(1.08)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--muted)}
.btn.ghost:hover{background:var(--card2);color:var(--txt)}
.btn.danger{border-color:#7a3230;color:#f0a6a4;background:transparent}
.btn.danger:hover{background:rgba(224,101,95,.10)}
.btn.small{padding:7px 11px;min-height:38px;font-size:13px}
.btn.wide{width:100%}
.btn.icon{padding:7px 10px;min-width:38px}
.btn[disabled]{opacity:.5;cursor:default}

/* ── переключатель «через шлюз / напрямую» ───────────────────────────── */
.seg{position:relative;display:inline-grid;grid-template-columns:1fr 1fr;background:#0a0e14;border:1px solid var(--line2);
  border-radius:999px;padding:4px;box-shadow:inset 0 2px 6px rgba(0,0,0,.55);isolation:isolate}
.seg::before{content:"";position:absolute;z-index:0;top:4px;left:4px;width:calc(50% - 4px);height:calc(100% - 8px);
  border-radius:999px;background:linear-gradient(180deg,#3aa9e0,#1f7ba8);
  box-shadow:0 2px 10px -2px rgba(58,169,224,.75), inset 0 1px 0 rgba(255,255,255,.25);
  transition:transform .24s cubic-bezier(.4,0,.2,1), background .24s, box-shadow .24s}
.seg.dir::before{transform:translateX(100%);background:linear-gradient(180deg,#e6bd52,#b08a1c);
  box-shadow:0 2px 10px -2px rgba(224,182,74,.7), inset 0 1px 0 rgba(255,255,255,.25)}
.seg button{position:relative;z-index:1;min-width:0;border:0;background:transparent;color:var(--muted);font-size:12.5px;
  font-weight:620;padding:8px 15px;border-radius:999px;cursor:pointer;min-height:36px;white-space:nowrap;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:color .18s}
.seg button:hover{color:#dbe4f0}
.seg button.on{color:#06131d;font-weight:700}
.seg .ico{font-size:13px;line-height:1}
.seg button[disabled]{cursor:default}
@media(max-width:520px){
  .seg{width:100%}
  .seg button{padding:8px 8px}
}

/* FIELD SELECTOR: единый вид всех полей ввода — и внутри .form, и вне её
   (поиск, имена подключений и т.п. раньше оставались «сырыми» браузерными) */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=file]),
select, textarea{
  background:#0a0e14;color:var(--txt);border:1px solid var(--line2);border-radius:var(--rl);
  padding:11px 13px;font-size:15px;font-family:inherit;min-height:44px;line-height:1.35;
  transition:border-color .15s, box-shadow .15s, background .15s;
}
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=file]):hover,
select:hover, textarea:hover{border-color:#41506a}
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=file]):focus,
select:focus, textarea:focus{outline:0;border-color:var(--acc2);background:#0c1219;
  box-shadow:0 0 0 3px rgba(42,143,208,.18)}
input::placeholder, textarea::placeholder{color:#66748a}
input[type=search]::-webkit-search-cancel-button{filter:invert(.7)}
.form label{display:block;margin:12px 0;color:var(--muted);font-size:13px}
.form input,.form select,.form textarea{width:100%;margin-top:6px;background:#0a0e14;color:var(--txt);
  border:1px solid var(--line2);border-radius:var(--rl);padding:12px;font-size:15px;min-height:44px;font-family:inherit;
  transition:border-color .15s, box-shadow .15s}
.form input:focus,.form textarea:focus,.form select:focus{outline:0;border-color:var(--acc2);
  box-shadow:0 0 0 3px rgba(42,143,208,.18)}
.form input[type=checkbox]{width:auto;min-height:0;margin:0 8px 0 0}
.checkline{display:flex;align-items:center;gap:10px;background:var(--card2);border:1px solid var(--line);
  border-radius:var(--rl);padding:11px 12px;margin:6px 0}
.checkline input{width:auto;min-height:0;margin:0}
.flag{width:22px;height:16px;border-radius:4px;flex:0 0 auto;box-shadow:0 0 0 1px rgba(255,255,255,.10), 0 1px 3px rgba(0,0,0,.5)}

.tbl{width:100%;border-collapse:collapse;font-size:13.5px}
.tbl th{text-align:left;color:var(--muted);font-weight:620;border-bottom:1px solid var(--line);padding:8px 6px;
  white-space:nowrap;font-size:12px;text-transform:uppercase;letter-spacing:.5px}
.tbl td{border-bottom:1px solid var(--line);padding:10px 6px;vertical-align:top}
.tbl tr:hover td{background:rgba(255,255,255,.014)}
.alert{border-radius:var(--rl);padding:12px 14px;margin:10px 0;border:1px solid var(--line);
  background:var(--card2);font-size:14px;display:flex;gap:10px;align-items:flex-start}
.alert.bad{border-color:#7a3230;background:rgba(224,101,95,.08)}
.alert.ok{border-color:#1f6f43;background:rgba(53,192,127,.08)}
.alert.warn{border-color:#7a6a20;background:rgba(224,182,74,.08)}
code{font-family:ui-monospace,Consolas,monospace;background:#0a0e14;border:1px solid var(--line);
  border-radius:6px;padding:1px 5px;font-size:12.5px;word-break:break-all}

.bottomnav{position:fixed;left:0;right:0;bottom:0;z-index:30;display:flex;justify-content:flex-start;
  gap:2px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:none;
  background:rgba(20,26,36,.94);backdrop-filter:blur(14px);border-top:1px solid var(--line);
  padding:6px 4px calc(6px + env(safe-area-inset-bottom))}
.bottomnav::-webkit-scrollbar{display:none}
.bottomnav a{display:flex;flex-direction:column;align-items:center;gap:3px;font-size:10.5px;color:var(--muted);
  padding:6px 8px;border-radius:14px;min-width:64px;flex:0 0 auto;transition:color .15s, background .15s}
.bottomnav a i{font-size:17px;line-height:1;font-style:normal;opacity:.85}
.bottomnav a.on{color:var(--acc);background:linear-gradient(180deg,rgba(76,194,255,.16),rgba(76,194,255,.04))}
.bottomnav a.on i{opacity:1}
.sidenav{display:none}

.qrbox{background:#fff;padding:12px;border-radius:16px;display:inline-block;max-width:100%;
  box-shadow:0 10px 30px -12px rgba(0,0,0,.8)}
.qrbox img{display:block;width:220px;height:220px}
.suburl{background:#0a0e14;border:1px solid var(--line2);border-radius:var(--rl);padding:11px 13px;
  font-size:12.5px;word-break:break-all;font-family:ui-monospace,Consolas,monospace}

.tabs{display:flex;gap:6px;overflow-x:auto;padding-bottom:4px;-webkit-overflow-scrolling:touch}
.tabs button{flex:0 0 auto;background:var(--card2);border:1px solid var(--line);color:var(--muted);
  border-radius:999px;padding:8px 15px;font-size:13.5px;min-height:40px;cursor:pointer;font-weight:560;transition:.15s}
.tabs button:hover{color:var(--txt)}
.tabs button.on{background:linear-gradient(180deg,#38a9e2,#1e7aa8);border-color:#3ba6dd;color:#fff;font-weight:650}
.ospane{display:none}
.ospane.on{display:block}
/* Старое правило .step (display:flex) удалено: на новой странице оно превращало
   .step-body во flex-элемент, а тот по умолчанию сжимается по содержимому —
   из-за этого карточки приложений были узкими и разной ширины. Номер шага здесь
   позиционируется абсолютно, поэтому flex не нужен. */
.step b{flex:0 0 24px;height:24px;border-radius:50%;background:var(--card2);border:1px solid var(--line2);
  display:grid;place-items:center;font-size:12px;font-weight:680;color:var(--acc)}
.spinner{width:16px;height:16px;border:2px solid var(--line2);border-top-color:var(--acc);border-radius:50%;
  animation:spin .8s linear infinite;display:inline-block;vertical-align:-3px}
@keyframes spin{to{transform:rotate(360deg)}}
.htmx-request .hide-during{display:none}

/* ── карточка апстрима ───────────────────────────────────────────────── */
.up-head{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;min-width:0}
.up-id{display:flex;gap:11px;align-items:center;min-width:0;flex:1}
.up-name{font-weight:620;display:flex;align-items:center;gap:7px;flex-wrap:wrap;line-height:1.35}
.up-host{color:var(--dim);font-size:12px;word-break:break-all;margin-top:2px}
.up-metrics{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;margin:0}
.up-metrics .pill{margin:0}
.up-foot{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap;
  margin-top:14px;padding-top:13px;border-top:1px solid var(--line)}
.up-actions{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.up-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.up-off{opacity:.62}
@media(max-width:640px){
  .up-head{flex-direction:column;gap:10px}
  .up-metrics{justify-content:flex-start}
  .up-foot{flex-direction:column;align-items:stretch}
  .up-foot .seg{order:-1}
  .up-actions{justify-content:space-between}
}
@media(min-width:900px){
  body{padding-bottom:0}
  .bottomnav{display:none}
  .sidenav{display:flex;flex-direction:column;gap:3px;position:fixed;left:0;top:55px;bottom:0;width:222px;
    padding:18px 14px;background:linear-gradient(180deg,rgba(255,255,255,.015),transparent),var(--card);
    border-right:1px solid var(--line)}
  .sidenav a{color:var(--muted);padding:11px 13px;border-radius:var(--rl);font-size:14px;font-weight:550;
    transition:background .15s, color .15s;border-left:2px solid transparent}
  .sidenav a.on{background:rgba(76,194,255,.10);color:var(--txt);border-left-color:var(--acc)}
  .sidenav a:hover{background:var(--card2);color:var(--txt)}
  .content{margin-left:237px;padding:22px 26px}
  /* страницы без бокового меню (вход): отступа под меню нет, блок по центру */
  .content.nonav{margin-left:auto;margin-right:auto;max-width:560px;padding:22px 20px}
  .grid{grid-template-columns:repeat(4,minmax(0,1fr))}
  h1{font-size:25px}
}

body.hide-off .up-off{display:none}

/* ── просмотр QR и всплывающие сообщения ─────────────────────────────── */
.lightbox{position:fixed;inset:0;z-index:100;background:rgba(4,6,9,.93);backdrop-filter:blur(8px);
  display:grid;place-items:center;padding:18px;cursor:zoom-out}
.lightbox[hidden]{display:none}
.lightbox img{width:min(86vw,86vh);height:min(86vw,86vh);background:#fff;border-radius:20px;padding:16px;
  box-shadow:0 24px 70px -24px #000}
.lightbox-hint{position:absolute;bottom:calc(22px + env(safe-area-inset-bottom));left:0;right:0;text-align:center;
  color:var(--muted);font-size:13px}
.toast{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(90px + env(safe-area-inset-bottom));z-index:120;
  background:#eef3fa;color:#0b0e13;font-weight:620;font-size:13.5px;padding:11px 18px;border-radius:999px;
  box-shadow:0 12px 34px -10px rgba(0,0,0,.75);max-width:88vw;text-align:center;animation:toastIn .18s ease-out}
.toast[hidden]{display:none}
@keyframes toastIn{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%,0)}}
@media(min-width:900px){.toast{bottom:28px}}

/* ── список серверов, полоса квоты, блоки AWG ────────────────────────── */
.srvlist{margin:8px 0 0 18px;padding:0;max-height:220px;overflow:auto}
.srvlist li{margin:2px 0;word-break:break-word}
.bar{height:8px;border-radius:999px;background:#0a0e14;border:1px solid var(--line2);overflow:hidden;margin:9px 0 6px}
.bar i{display:block;height:100%;background:linear-gradient(90deg,#38a9e2,#4cc2ff)}
.awl{border-top:1px solid var(--line);padding-top:12px;margin-top:12px}
.awl:first-of-type{border-top:0;padding-top:0;margin-top:0}
.awl .qrbox{margin-top:10px}

/* ── карточка пользователя ───────────────────────────────────────────── */
.avatar{width:40px;height:40px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  font-weight:700;font-size:16px;color:#06131d;
  background:linear-gradient(135deg,#4cc2ff,#9775fa);box-shadow:0 2px 10px -4px rgba(76,194,255,.8)}

/* ── подключения AWG (устройства пользователя) ───────────────────────── */
.dev{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap;
  background:var(--card2);border:1px solid var(--line);border-radius:var(--rl);padding:9px 12px;margin:8px 0}
.devname{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis}
.devacts{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.ren summary{list-style:none;cursor:pointer}
.ren summary::-webkit-details-marker{display:none}
.ren input{min-height:38px}

/* поле имени подключения: тянется, но не ломает кнопку рядом */
.search{flex:1 1 auto;min-width:0}
.devinput{flex:1 1 auto;min-width:0;max-width:280px}
@media(max-width:640px){
  .awl .row.between{flex-direction:column;align-items:stretch}
  .awl form.row{flex-wrap:wrap!important}
  .devinput{max-width:none;width:100%}
  .dev{flex-direction:column;align-items:stretch}
  .devacts{justify-content:flex-start}
}

/* ── вкладка «Трафик» ────────────────────────────────────────────────── */
#c-traffic,#c-conns{width:100%;display:block}
.legend{display:flex;gap:14px;align-items:center;color:var(--muted);font-size:12.5px;margin-top:8px}
.lg{width:10px;height:10px;border-radius:3px;display:inline-block}
.lg-down{background:#4cc2ff}
.lg-up{background:#9775fa}

/* ── поля пароля и переключатели блоков ─────────────────────────────── */
.pwblock{display:block;position:static;margin:0}
.pwblock label{margin:10px 0 0}
.pwblock .pwrules{margin:10px 0 16px}          /* запас снизу: кнопка не налезает на чипы */
.pwwrap{position:relative;display:block}
.pwwrap input{padding-right:46px}
.eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);background:transparent;border:0;
  font-size:17px;cursor:pointer;color:var(--muted);padding:6px 8px;line-height:1}
.eye:hover{color:var(--txt)}
.pwrules{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;max-width:100%;position:static}
.pwrules [data-rule]{font-size:12px;color:var(--muted);border:1px solid var(--line);border-radius:999px;
  padding:3px 10px;background:var(--card2)}
.pwrules [data-rule].ok{color:#8ee0b0;border-color:#1f6f43;background:rgba(53,192,127,.10)}
.pwcount{font-size:12px;color:var(--muted);align-self:center;flex:0 0 100%}
.pwsubmit{display:flex;width:100%;margin-top:4px}
.pwcount.bad{color:#f0a6a4}
.pwequal{font-size:12.5px;color:#f0a6a4;margin-top:6px}
.panesw{display:inline-flex;background:#0a0e14;border:1px solid var(--line2);border-radius:999px;padding:4px;gap:2px}
.panesw button{border:0;background:transparent;color:var(--muted);font-size:13.5px;font-weight:600;
  padding:9px 18px;border-radius:999px;cursor:pointer;min-height:38px}
.panesw button.on{background:linear-gradient(180deg,#38a9e2,#1e7aa8);color:#fff}

/* ── справка по способам подключения ────────────────────────────────── */
.cinfo-row{display:flex;gap:12px;align-items:flex-start;padding:12px 0;border-top:1px solid var(--line)}
.cinfo-row:first-child{border-top:0;padding-top:0}
.cinfo-ico{width:34px;height:34px;flex:0 0 auto;display:grid;place-items:center;border-radius:10px;
  background:var(--card2);border:1px solid var(--line);font-size:16px}

/* ── группы серверов по подпискам ───────────────────────────────────── */
.srcgroup{margin:14px 0;border:1px solid var(--line);border-radius:var(--r);background:var(--card);
  box-shadow:var(--sh);overflow:hidden}
.srcgroup>summary{cursor:pointer;list-style:none;display:flex;gap:10px;align-items:center;
  flex-wrap:wrap;padding:13px 16px;background:linear-gradient(180deg,rgba(255,255,255,.03),transparent);
  transition:background .15s}
.srcgroup>summary:hover{background:linear-gradient(180deg,rgba(76,194,255,.10),transparent)}
.srcgroup>summary::-webkit-details-marker{display:none}
/* Стрелка нарисована стилями, а не символом: символьные маркеры зависят от шрифта
   и легко превращаются в мусор. Вниз — можно развернуть, вверх — уже развёрнуто. */
.srcgroup>summary::before{content:"";flex:0 0 auto;width:9px;height:9px;
  border-right:2.5px solid var(--acc);border-bottom:2.5px solid var(--acc);
  transform:rotate(45deg);transition:transform .18s;margin:0 5px 3px 3px}
.srcgroup[open]>summary::before{transform:rotate(-135deg);margin:0 7px 0 1px}
.srcgroup[open]>summary{background:linear-gradient(180deg,rgba(76,194,255,.06),transparent);
  border-bottom:1px solid var(--line)}
.srcname{font-weight:650}
.srclist{padding:0 12px 12px}
.srclist .card{margin:10px 0}

/* живой индикатор на вкладке «Трафик» */
.livedot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#35c07f;
  box-shadow:0 0 0 0 rgba(53,192,127,.6);animation:pulse 1.6s infinite;vertical-align:middle}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(53,192,127,.55)}70%{box-shadow:0 0 0 9px rgba(53,192,127,0)}100%{box-shadow:0 0 0 0 rgba(53,192,127,0)}}

/* ── страница замера скорости ───────────────────────────────────────── */
.speedwrap{display:grid;gap:14px}
.gauge{position:relative;height:12px;border-radius:999px;background:#0a0e14;border:1px solid var(--line2);overflow:hidden}
.gauge i{display:block;height:100%;width:0;background:linear-gradient(90deg,#38a9e2,#4cc2ff);transition:width .18s linear}
.gauge.up i{background:linear-gradient(90deg,#7a5cf0,#9775fa)}
.speedbig{font-size:40px;font-weight:700;letter-spacing:-1px;line-height:1.05}
.speedbig small{font-size:15px;font-weight:600;color:var(--muted);letter-spacing:0}
.speedgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
@media(min-width:900px){.speedgrid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.spin-fade{color:var(--muted);font-size:13px;min-height:18px}

/* ── вкладки-подчёркивания (без «полусферы» вокруг надписей) ─────────── */
.tabsline{display:flex;gap:20px;border-bottom:1px solid var(--line);margin:4px 0 14px;overflow-x:auto;
  -webkit-overflow-scrolling:touch;scrollbar-width:none}
.tabsline::-webkit-scrollbar{display:none}
.tabsline button{background:none;border:0;border-bottom:2px solid transparent;color:var(--muted);
  font-size:14px;font-weight:600;padding:10px 2px;cursor:pointer;white-space:nowrap;
  display:inline-flex;align-items:center;gap:7px;transition:color .15s, border-color .15s}
.tabsline button:hover{color:var(--txt)}
.tabsline button.on{color:var(--txt);border-bottom-color:var(--acc)}
.dl{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap;
  background:var(--card2);border:1px solid var(--line);border-radius:var(--rl);padding:11px 13px;margin:8px 0}
.dl .t{min-width:0}
.dl .t b{display:block}
.dl .acts{display:flex;gap:6px;flex-wrap:wrap}

/* скрытые вкладки должны быть скрыты, что бы ни говорили другие правила */
[hidden]{display:none !important}

/* ── графики на обзоре ─────────────────────────────────────────────────
   Размер задаём через CSS: если менять только атрибуты canvas, на экранах
   с высокой плотностью (devicePixelRatio > 1) элемент раздувается вдвое.
   Одна колонка и overflow:hidden — чтобы ничто не могло распереть страницу. */
.chart{display:block;width:100%;max-width:100%;height:80px}
.chartwrap{display:block;margin:12px 0;min-width:0}
.chartbox{background:linear-gradient(180deg,rgba(255,255,255,.022),rgba(255,255,255,0)),var(--card);
  border:1px solid var(--line);border-radius:var(--r);padding:10px 12px;box-shadow:var(--sh);
  min-width:0;max-width:100%;overflow:hidden;margin-bottom:10px}
.chartbox h2{margin-bottom:6px}
.nowrow{display:flex;flex-wrap:wrap;gap:4px 14px;align-items:center;margin-top:6px;
  color:var(--muted);font-size:12px;min-width:0;max-width:100%}
.nowrow b{color:var(--txt);font-weight:650}
.nowrow span{min-width:0;max-width:100%;overflow-wrap:anywhere}

/* ── содержимое набора адресов ───────────────────────────────────────── */
.entries{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 2px;max-height:260px;overflow:auto;
  padding:2px}
.entry{display:inline-flex;align-items:center;gap:6px;background:var(--card2);border:1px solid var(--line);
  border-radius:999px;padding:4px 6px 4px 11px;font-size:12.5px;max-width:100%}
.entry .mono{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:280px}
.entry form{display:inline;margin:0}
.entry-x{background:none;border:0;color:var(--muted);font-size:15px;line-height:1;cursor:pointer;
  padding:2px 5px;border-radius:50%}
.entry-x:hover{color:var(--bad);background:rgba(224,101,95,.12)}
/* ═══ СТРАНИЦА «ПОДКЛЮЧЕНИЕ» (/connect) ═══════════════════════════════════
   Отдельная страница-инструкция: выбор устройства и три шага. Основная
   страница «Мои подключения» (/me) не тронута — можно сравнивать.

   Стили опираются на существующие токены (--card, --acc, --line), поэтому
   тёмная тема и общий вид панели не меняются. */

/* ── выбор устройства ─────────────────────────────────────────────────── */
/* ВАЖНО: без flex-wrap. На iPhone и Mac при переносе список вставал второй
   строкой и расползался — метка сверху, поле снизу во всю ширину. */
.osrow{display:flex;align-items:center;gap:10px}
.oslabel{color:var(--muted);font-size:12.5px;letter-spacing:.4px;text-transform:uppercase;
  font-weight:650;flex:0 0 auto}
.ossel{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  background-color:var(--card2);color:var(--txt);
  border:1px solid var(--line2);border-radius:var(--rl);
  /* line-height обязателен: Safari на iPhone иначе раздувает высоту поля */
  padding:10px 40px 10px 14px;font:inherit;font-weight:600;line-height:1.2;
  flex:1 1 auto;min-width:0;max-width:280px;cursor:pointer;
  /* стрелка нарисована фоном: не нужен лишний элемент и не съезжает на iOS */
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),
                   linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:right 19px center, right 13px center;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat;
  text-overflow:ellipsis;
}
.ossel:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(76,194,255,.14)}
#osguess{color:var(--muted)}

/* ── таймлайн шагов ───────────────────────────────────────────────────── */
.steps{position:relative;padding:6px 0 2px 52px;margin:14px 0 0}
.steps-line{position:absolute;left:17px;top:26px;bottom:34px;width:2px;border-radius:2px;
  background:linear-gradient(180deg,var(--acc) 0%,rgba(76,194,255,.35) 45%,var(--line) 100%)}
.step{position:relative;padding:0 0 22px}
.step:last-child{padding-bottom:4px}
.step-num{
  position:absolute;left:-52px;top:-2px;
  width:36px;height:36px;border-radius:50%;
  background:var(--card2);border:1px solid var(--line2);
  display:grid;place-items:center;
  font-weight:700;font-size:14px;color:var(--acc);
  box-shadow:0 0 0 4px var(--bg);
}
.step-body{
  background:linear-gradient(180deg,rgba(255,255,255,.022),rgba(255,255,255,0)),var(--card);
  border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;box-shadow:var(--sh);min-width:0;width:100%;
}
.step-title{font-weight:660;font-size:15.5px;margin-bottom:6px}
.step-text{margin:0 0 12px;color:var(--muted);font-size:13.5px;line-height:1.5}
.step-acts{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.step-note{margin:10px 0 0}

/* на узком экране убираем отступ под кружки: место дороже */

/* ═══ ИСПРАВЛЕНИЕ: иконки шагов сжимались на телефоне ═══════════════════════
   Причина: в мобильной раскладке .step-num становился обычным элементом flex-строки
   без запрета на сжатие, и браузер сжимал кружок до овала. Задаём жёсткий размер. */
.step-num{flex:0 0 auto}

@media(max-width:560px){
  .steps{padding-left:0}
  .steps-line{display:none}
  .step-num{position:static;margin-bottom:10px;width:34px;height:34px;font-size:14px;
    flex:0 0 34px;min-width:34px}
  /* на узком экране список занимает всю ширину, но остаётся в одну строку с меткой */
  .ossel{max-width:none;width:100%;flex:1 1 100%}
  .osrow{flex-wrap:wrap}
  .oslabel{flex:0 0 auto}
}

/* ═══ выбор способа подключения (Happ / AmneziaWG) ═════════════════════════
   Две крупные кнопки: это главное решение на странице, поэтому они заметные
   и с пояснением внутри, а не просто подписи. */
/* Колонки подстраиваются под число вариантов: три кнопки встают в ряд
   на широком экране, в две колонки на среднем и в столбик на телефоне. */
.pick{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px}
.pick-btn{
  display:flex;gap:12px;align-items:center;text-align:left;
  background:var(--card2);color:var(--txt);
  border:1px solid var(--line2);border-radius:var(--r);
  padding:14px 16px;font:inherit;cursor:pointer;
  transition:border-color .15s,background .15s,box-shadow .15s;
}
.pick-btn:hover{border-color:var(--brand)}
.pick-btn.on{border-color:var(--brand);
  background:linear-gradient(180deg,var(--brand-bg),transparent 70%),var(--card2);
  box-shadow:0 0 0 3px var(--brand-ring)}

/* Значок приложения — в его собственных цветах, чтобы люди узнавали программу
   ещё до чтения названия. Цвета сняты с настоящих иконок из App Store. */
.pick-ico{
  width:44px;height:44px;border-radius:12px;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  font-size:20px;font-weight:800;line-height:1;letter-spacing:-.02em;
}

/* Happ: серебристая «H» на тёмном — как на иконке приложения */
.pick-btn[data-tp-btn="happ"]{
  --brand:#d7dbe2;--brand-bg:rgba(215,219,226,.10);--brand-ring:rgba(215,219,226,.15)}
.pick-btn[data-tp-btn="happ"] .pick-ico{
  background:linear-gradient(160deg,#f5f7fa,#9aa3af 52%,#e8ebf0);
  color:#151920;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}

/* INCY: зелёный с переходом в лайм — как на иконке и в самом приложении */
.pick-btn[data-tp-btn="incy"]{
  --brand:#a9da4b;--brand-bg:rgba(169,218,75,.12);--brand-ring:rgba(169,218,75,.18)}
.pick-btn[data-tp-btn="incy"] .pick-ico{
  background:linear-gradient(135deg,#30cc5f 0%,#7fd44f 55%,#b8da48 100%);
  color:#08150c;box-shadow:inset 0 0 0 2px rgba(8,21,12,.40)}

/* AmneziaWG: синий, зелёный, оранжевый и розовый — цвета его знака */
.pick-btn[data-tp-btn="awg"]{
  --brand:#8b9ee0;--brand-bg:rgba(139,158,224,.13);--brand-ring:rgba(139,158,224,.20)}
.pick-btn[data-tp-btn="awg"] .pick-ico{
  background:conic-gradient(from 215deg at 50% 50%,
    #576dc0,#82d048,#c0e557,#fbb836,#c496bb,#576dc0);
  color:#0b0e13;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
.pick-txt{min-width:0}
.pick-txt b{display:block;font-weight:650}
.pick-txt i{display:block;font-style:normal;color:var(--muted);font-size:12.5px;margin-top:2px}

@media(max-width:560px){
  .pick{grid-template-columns:1fr}
}

/* ═══ свёрнутый блок «Мои подключения и настройки» ═════════════════════════
   Нужен, чтобы основное (инструкция) оставалось коротким, а управление не
   пропадало. details/summary — без JS и работает с клавиатуры. */
.more summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:center;gap:10px;
  font-weight:650;font-size:14px;color:var(--txt);
}
.more summary::-webkit-details-marker{display:none}
.more summary::before{
  content:"▸";color:var(--acc);font-size:13px;transition:transform .15s;
  display:inline-block;
}
.more[open] summary::before{transform:rotate(90deg)}
.more summary .pill{margin-left:auto}
/* ═══ ИСПРАВЛЕНИЯ И ДОБАВЛЕНИЯ К СТРАНИЦЕ «ПОДКЛЮЧЕНИЕ» ════════════════════ */

/* ── убираю «полукруг» вокруг пояснения под названием способа ──
   Пояснение («проще всего», «устойчивее к блокировкам») — это <i>. Браузер по
   умолчанию делает его курсивом, и вместе с подложкой кнопки это выглядело как
   некрасивый полукруг вокруг текста. Делаем обычный прямой текст. */
.pick-txt i{
  font-style:normal;
  font-weight:500;
  color:var(--muted);
  font-size:12.5px;
  line-height:1.35;
  margin-top:3px;
  display:block;
}
/* у выбранной кнопки пояснение чуть светлее — видно, что это активный вариант */
.pick-btn.on .pick-txt i{color:#a9b6c9}

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


/* ── разделитель и заголовок раздела внутри шага 3 ── */
.innersep{
  height:1px;background:var(--line);
  margin:16px 0 14px;
}
.sec-head{
  display:flex;align-items:center;gap:8px;
  font-weight:660;font-size:15.5px;margin-bottom:10px;
}
.sec-head .pill{margin-left:auto}

/* заголовки h3 внутри шага 3 — компактнее обычных */
.step-body h3{
  font-size:13px;letter-spacing:.4px;text-transform:uppercase;
  color:#a9b6c9;font-weight:650;margin:14px 0 8px;
  display:flex;align-items:center;gap:8px;
}
.step-body h3 .pill{margin-left:0}
/* ═══ ВЫРАВНИВАНИЕ КАРТОЧЕК ПРИЛОЖЕНИЙ ═════════════════════════════════════
   Было: название, пояснение и кнопки лежали в одной flex-строке, и карточки с
   длинным текстом («iPhone / iPad») выглядели иначе, чем соседние. Теперь у
   карточки фиксированная структура: слева текстовый блок, справа кнопки;
   название и пояснение стоят в один столбец, поэтому карточки ровные. */

/* запасная ссылка под карточкой (когда в магазине может не быть) */


/* ═══ ИМЯ УСТРОЙСТВА КАК КНОПКА ПЕРЕИМЕНОВАНИЯ ═════════════════════════════
   Имя само открывает поле правки — отдельная кнопка «Имя» больше не нужна.
   Выглядит как текст, но подсвечивается и показывает, что нажимается. */
.devname-btn{
  background:none;border:0;padding:0;margin:0;
  font:inherit;font-weight:600;color:var(--txt);
  cursor:pointer;text-align:left;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  border-bottom:1px dashed transparent;
}
.devname-btn:hover,.devname-btn:focus-visible{
  color:var(--acc);border-bottom-color:var(--acc);outline:none;
}
.devname-btn::after{
  content:"✎";font-size:11px;color:var(--dim);margin-left:6px;
  vertical-align:1px;
}
.devname-btn:hover::after{color:var(--acc)}

.renform{width:100%}

/* ═══ СВОРАЧИВАЕМЫЙ QR У КАЖДОГО ТУННЕЛЯ ══════════════════════════════════
   QR занимает много места, а нужен редко — прячем в раскрывающийся пункт
   со стрелочкой, как просил заказчик. */
.qrfold{display:inline-block}
.qrfold summary{
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;
}
.qrfold summary::-webkit-details-marker{display:none}
.fold-ar{font-size:9px;color:var(--muted);transition:transform .15s;display:inline-block}
.qrfold[open] .fold-ar{transform:rotate(180deg)}
.qrfold .qrbox{padding:8px;background:var(--card3);border:1px solid var(--line);
  border-radius:var(--rl)}
/* ═══ QR ПО ЦЕНТРУ, БЕЗ ПРЫЖКОВ ИНТЕРФЕЙСА ═════════════════════════════════
   Было: QR прижат влево и выглядел случайным. Ставим по центру.
   Чтобы интерфейс не «прыгал», контейнер резервирует место заранее
   (min-height), а картинка не влияет на ширину строки. */
.qrwrap{
  display:flex;justify-content:center;
  margin:14px 0;min-height:216px;   /* 200px картинка + рамка: место занято всегда */
}
.qrwrap .qrbox{margin:0}

/* кнопки под QR — тоже по центру, чтобы совпадали с ним */
.step-acts.center{justify-content:center}

/* свёрнутый QR в списке устройств: место резервируем только когда раскрыт,
   поэтому список не дёргается при закрытии */
.qrfold .qrbox{display:flex;justify-content:center}

@media(max-width:560px){
  .qrwrap{min-height:0}
}
/* ═══ КАРТОЧКИ ПРИЛОЖЕНИЙ: РОВНЫЕ, БЕЗ ПРЫЖКОВ ══════════════════════════════
   Что было не так:
   1) карточка лежала внутри обёртки <div data-os-act>, а обёртка — не flex,
      поэтому выравнивание flex-строки не работало;
   2) у карточек с двумя кнопками текст сжимался сильнее, чем у карточек с одной,
      и левая колонка получалась разной ширины — карточки «прыгали».

   Как сделано:
   1) обёртки нет — data-os-act висит на самой карточке (в шаблоне);
   2) кнопки выровнены по сетке фиксированной ширины, поэтому правая колонка
      одинаковая у всех карточек, а текст занимает всё оставшееся место;
   3) высота карточки фиксированная, пояснение занимает ровно две строки. */


/* ═══ РАСКРЫВАЕМЫЙ БЛОК «ПОДКЛЮЧИТЬ» С QR И ФАЙЛОМ ═════════════════════════
   Нужен, чтобы список подключений оставался компактным: QR и кнопки скачивания
   показываются только у того туннеля, который пользователь раскрыл. */
.qrpanel{
  margin:-2px 0 10px;
  background:var(--card3);border:1px solid var(--line2);
  border-radius:var(--rl);padding:14px;
}
.qrpanel-in{display:flex;flex-direction:column;align-items:center;gap:12px}
.qrpanel .qrbox{margin:0}
.qrpanel-acts{display:flex;gap:8px;flex-wrap:wrap;justify-content:center}

/* стрелка в кнопке «Подключить» */
.qrfold{display:inline-block}
.qrfold summary{
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
}
.qrfold summary::-webkit-details-marker{display:none}
.fold-ar{font-size:9px;transition:transform .15s;display:inline-block}
.qrfold[open] .fold-ar{transform:rotate(180deg)}

/* подпись под QR по центру — чтобы совпадала с картинкой */
.step-note.center{text-align:center}

/* ═══ КАРТОЧКИ ПРИЛОЖЕНИЙ ═══════════════════════════════════════════════════
   Один набор правил на всю страницу. Раньше их было три подряд (от нескольких
   правок), и работало последнее — это путало. Правила:

   1. data-os-act висит на самой карточке, обёртки нет — иначе рушится flex;
   2. высота фиксированная, пояснение ровно 2 строки — карточки одной высоты;
   3. область кнопок фиксированной ширины, колонки 1fr — карточка с одной
      кнопкой и с двумя получаются ОДИНАКОВОЙ ширины. */
.appc{
  display:flex;align-items:center;gap:12px;
  background:var(--card2);border:1px solid var(--line);
  border-radius:var(--rl);padding:10px 13px;margin:8px 0;
  height:64px;box-sizing:border-box;
}
.appc-main{flex:1 1 auto;min-width:0;overflow:hidden}
.appc-t{font-weight:620;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.appc-n{color:var(--muted);font-size:12.5px;line-height:1.3;margin-top:2px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.appc-a{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:6px;flex:0 0 auto;width:248px}
.appc-a .btn{justify-content:center;text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

@media(max-width:600px){
  .appc{height:auto;flex-direction:column;align-items:stretch;gap:8px}
  .appc-a{grid-auto-flow:row;grid-auto-columns:auto;width:100%}
  .appc-a .btn{width:100%}
}

/* ── шапка страницы подключений ──
   Верхняя строка: имя человека и значок состояния. Ниже четыре плитки в ряд.
   На телефоне плитки встают по две, а имя со значком переносится. */
.headcard{padding:16px 18px}
.headtop{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px}
.headname{font-size:22px;font-weight:700;letter-spacing:-.4px;line-height:1.2}
.headbadge{font-size:11.5px;font-weight:650;letter-spacing:.3px;padding:4px 11px;
  border-radius:999px;border:1px solid var(--line2);color:var(--muted);background:var(--card2);
  white-space:nowrap}
.headbadge.ok{color:#7fe0a8;border-color:rgba(53,192,127,.45);background:rgba(53,192,127,.10)}
.headbadge.bad{color:#f0a6a4;border-color:rgba(232,110,108,.45);background:rgba(232,110,108,.10)}
.headrow{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.headtile{min-width:0;border:1px solid var(--line);border-radius:var(--rl);
  padding:13px 15px;background:var(--card2);box-shadow:var(--sh)}
.headtile.accent{border-color:rgba(139,120,232,.45);
  background:linear-gradient(180deg,rgba(139,120,232,.13),rgba(139,120,232,.04))}
.headtile .headv{font-size:23px;font-weight:700;letter-spacing:-.5px;line-height:1.15;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.headtile .headl{color:var(--muted);font-size:10.5px;letter-spacing:.7px;
  text-transform:uppercase;margin-top:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.footline{margin-top:12px;padding-top:11px;border-top:1px solid var(--line)}
@media(max-width:760px){
  .headname{font-size:19px}
  .headrow{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .headtile{padding:11px 13px}
  .headtile .headv{font-size:19px}
}
