/* Шрифты (Onest + Fira Mono, самохост, OFL). Пути assets/fonts/ — для веба/кабинета. */
@font-face{font-family:'Fira Mono';font-style:normal;font-weight:400;font-display:swap;src:url('assets/fonts/firamono-400-cyrillic.woff2') format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}
@font-face{font-family:'Fira Mono';font-style:normal;font-weight:400;font-display:swap;src:url('assets/fonts/firamono-400-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
/* Шрифт дизайн-системы — Onest (самохост, OFL; woff2 взяты с fonts.gstatic.com / Google Fonts).
   Файл ВАРИАТИВНЫЙ: одна пара woff2 (латиница+кириллица) несёт ось wght, объявленную 400 700 —
   и 400/500/600/700 берутся из неё точно, и 800/900 из разметки матчатся на верхнюю границу (700)
   по правилам CSS, как раньше на статический жир. Отдельных файлов на вес больше нет. */
@font-face{font-family:'Onest';font-style:normal;font-weight:400 700;font-display:swap;src:url('assets/fonts/onest-vf-cyrillic.woff2') format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;}
@font-face{font-family:'Onest';font-style:normal;font-weight:400 700;font-display:swap;src:url('assets/fonts/onest-vf-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
/* ЗАПАСНОЙ ШРИФТ С ТЕМИ ЖЕ МЕТРИКАМИ. У нас font-display:swap — значит первый кадр страница рисует
   системным шрифтом и перевёрстывает его, когда доедет Onest. Onest на ~4% шире Arial, и без этой
   перебивки прыжок видно глазами. Множители: ascent 970/1000 и descent 305/1000 у Onest, делённые
   на size-adjust. Та же пара уже стоит в pay/styles.css — держать одинаковой. */
@font-face{font-family:'Onest Fallback';src:local('Arial'),local('Helvetica'),local('Liberation Sans');
  size-adjust:103.93%;ascent-override:93.33%;descent-override:29.35%;line-gap-override:0%}

/* ============================================================================
   МАЯК VPN — ДИЗАЙН-СИСТЕМА (единая для админки, лендинга и кабинета).
   Токены и паттерны сняты с дизайн-системы Remnawave-панели (Mantine-тема, theme.ts):
   тёмная «GitHub-dark» палитра, шрифт Onest + Fira Mono, акцент cyan, радиус 8px.
   Полное описание паттернов и как применять — docs/DESIGN-SYSTEM.md.
   Подключать ПЕРВЫМ (до частных стилей страницы). Не редактировать точечно под одну страницу —
   правки токенов здесь распространяются на весь проект.
   ============================================================================ */

:root {
  /* 🔴 color-scheme: dark — одна строка, которая чинит ВСЕ системные элементы браузера (25-08).
     Пока схема не объявлена, Chrome рисует их в СВЕТЛОЙ теме: чекбокс согласия на регистрации
     выходил ярко-белым квадратом — единственным светлым пятном на всей тёмной карточке, ровно
     на последнем экране перед созданием аккаунта. Тем же не объявлением портились полосы
     прокрутки, календари и автозаполнение (Chrome кладёт светло-жёлтый фон поверх нашего
     тёмного поля на форме входа). Чинить это перерисовкой контролов по одному — работа без
     конца; браузеру достаточно сказать, какую схему мы поддерживаем. */
  color-scheme: dark;

  /* ---- ПАЛИТРА: тёмная «GitHub-dark» (Remnawave dark[0..9]) ---- */
  --dark-0:#c9d1d9; --dark-1:#b1bac4; --dark-2:#8b949e; --dark-3:#6e7681; --dark-4:#484f58;
  --dark-5:#30363d; --dark-6:#21262d; --dark-7:#161b22; --dark-8:#0d1117; --dark-9:#010409;

  /* ---- РОЛИ (семантика) ---- */
  --ds-bg:var(--dark-7);            /* фон страницы = body (Mantine --mantine-color-body=dark-7 #161b22, сверено с panel.demidov.info) */
  --ds-bg-deep:var(--dark-8);       /* dark-8 #0d1117 — старт градиента сайдбара / «глубокий» фон */
  --ds-surface:var(--dark-6);       /* сплошные контролы (инпуты, subtle-кнопки) */
  --ds-surface-2:var(--dark-8);     /* «утопленный» фон полей */
  /* 🔴 dark-3, а не dark-5 (16-09, по слову владельца «да делай»). Рамка поля и кнопки — это
     граница ЭЛЕМЕНТА УПРАВЛЕНИЯ, у неё порог 3,0 (WCAG 1.4.11), а не 4,5 как у текста. Замер на
     нашей палитре: dark-5 #30363d даёт 1,42 на фоне страницы и 1,25 на поверхности, dark-4 #484f58
     — 2,09 и 1,84, то есть оба проваливают порог. Первый тон шкалы, который его берёт, —
     dark-3 #6e7681: 3,77 на странице, 3,31 на поверхности, 4,12 на утопленном поле. Второстепенная
     кнопка (.ds-btn--outline) до этой правки опознавалась ТОЛЬКО по тексту: её рамку видно не было.
     ⚠️ Рамки светлеют ВЕЗДЕ — это цена, названная владельцу заранее. */
  --ds-border:var(--dark-3);        /* бордеры */
  --ds-border-soft:rgba(255,255,255,.08);
  --ds-text:var(--dark-0);          /* основной текст */
  --ds-dimmed:var(--dark-2);        /* приглушённый текст/подписи */

  /* ---- АКЦЕНТ: cyan (Mantine cyan, primaryShade 8) ---- */
  --cyan-4:#3bc9db; --cyan-5:#22b8cf; --cyan-6:#15aabf; --cyan-7:#1098ad; --cyan-8:#0c8599; --cyan-9:#0b7285;
  /* Заливка главной кнопки — cyan-9, а не унаследованный от Remnawave cyan-8: белый текст на cyan-8
     даёт 4.35 при пороге AA 4.5 (замер 02-08), на cyan-9 — 5.59. Ховер НЕ из шкалы: cyan-7 (3.43) и
     cyan-8 (4.35) оба проваливают порог, поэтому взят промежуточный тон 4.70 — кнопка при наведении
     по-прежнему светлеет, но текст на ней читается. Значение общее для кабинета, /tools/ip и панели
     (там зеркало в internal/admin/static/style.css) — менять только во всех сразу. */
  --ds-primary:var(--cyan-9); --ds-primary-hover:#0d7f92; --ds-primary-ink:#fff;

  /* ---- СТАТУСЫ (для нод/линий/бейджей): tailwind-оттенки как в Remnawave ---- */
  --st-alive:#2dd4bf;   /* бирюза — живо/онлайн */
  --st-error:#ef4444;   /* красный — ошибка/недоступно */
  --st-off:#6b7280;     /* серый — выключено/в пуле */
  --st-warn:#f59e0b;    /* янтарь — переходное */
  --ok:#40c057; --bad:#fa5252; --warn:#d29922;

  /* ---- ЧЕРНИЛА СТАТУСОВ: цветной ТЕКСТ на тёмной поверхности ----
     Заливочные --st-* держат узнаваемость (точка, рамка, подложка), но ТЕКСТОМ они не добирают
     контраст: #ef4444 на dark-6/dark-7 даёт 3,76–4,04 при пороге AA 4,5 — и хуже всего читается
     ровно то, что обязано читаться первым (заголовок отказа, «опасная зона», ошибка под полем).
     Приём был заведён только для красного (--red-ink жил в cabinet/styles.css), а светлые зелёный
     и янтарный изобретались по месту: одна роль — три разных значения в трёх файлах. Теперь роль
     одна, токен один. Значения взяты те, что уже стояли в кабинете и в .ds-badge-- ниже, — вид
     не меняется. */
  --red-ink:#fca5a5;    /* красный текст: отказ, ошибка, опасная зона */
  --ok-ink:#5eead4;     /* бирюзовый текст: «всё хорошо», активный тариф */
  --warn-ink:#fcd34d;   /* янтарный текст: предупреждение, «скоро кончится» */

  /* ---- ТИПОГРАФИКА ---- */
  --font:'Onest', 'Onest Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono:'Fira Mono', 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-xs:12px; --fs-sm:14px; --fs-md:16px; --fs-lg:18px; --fs-xl:20px;
  --lh:1.55; --fw-heading:600;

  /* ---- РАДИУСЫ (Mantine, default md) ---- */
  --r-xs:2px; --r-sm:4px; --r-md:8px; --r-lg:16px; --r-xl:32px; --r:var(--r-md);

  /* ---- ОТСТУПЫ (Mantine spacing) ---- */
  --sp-xs:10px; --sp-sm:12px; --sp-md:16px; --sp-lg:20px; --sp-xl:32px;

  /* ---- ТЕНИ ---- */
  --sh-sm:0 1px 3px rgba(0,0,0,.3); --sh-md:0 4px 12px rgba(0,0,0,.35); --sh-lg:0 8px 24px rgba(0,0,0,.4);
  --dur:.2s;
  /* Кривые движения. Встроенные ease и linear слишком вялые, чтобы движение читалось осмысленно:
     --ease-out — появление и исчезновение (стартует быстро, поэтому ощущается отзывчивым),
     --ease-in-out — для того, что ездит по экрану. Файл общий для кабинета, лендинга и админки,
     поэтому токены только добавляем, существующие значения не трогаем. */
  --ease-out:cubic-bezier(.23,1,.32,1);
  --ease-in-out:cubic-bezier(.77,0,.175,1);
}

/* ============================ БАЗА ============================ */
.ds, body.ds { background:var(--ds-bg); color:var(--ds-text);
  font-family:var(--font); font-size:var(--fs-md); line-height:var(--lh); }
.ds h1,.ds h2,.ds h3,.ds h4 { font-weight:var(--fw-heading); color:var(--ds-text); }
.ds a { color:var(--cyan-5); text-decoration:none; }
.ds a:hover { text-decoration:underline; }
.ds .mono, .ds code, .ds kbd { font-family:var(--font-mono); }
.ds .dimmed { color:var(--ds-dimmed); }

/* ============================ КАРТОЧКА ============================ */
/* Паттерн Remnawave Card: полупрозрачная поверхность + мягкий бордер, радиус md, fade-in. */
.ds-card { background:rgba(255,255,255,.02); border:1px solid var(--ds-border-soft);
  border-radius:var(--r-md); padding:var(--sp-md); animation:ds-fade var(--dur) linear both; }
.ds-card--solid { background:var(--ds-surface); border-color:var(--ds-border); }
@keyframes ds-fade { from{opacity:0} to{opacity:1} }

/* ============================ БЕЙДЖ ============================ */
/* Дефолт Remnawave: radius md, variant outline. Плюс light-варианты по семантике. */
.ds-badge { display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:var(--r-md);
  font-size:var(--fs-xs); font-weight:600; line-height:1.4; border:1px solid var(--ds-border); color:var(--ds-dimmed); }
.ds-badge--primary { border-color:var(--cyan-7); color:var(--cyan-4); background:rgba(21,170,191,.10); }
.ds-badge--alive   { border-color:rgba(45,212,191,.4); color:var(--ok-ink); background:rgba(45,212,191,.12); }
.ds-badge--error   { border-color:rgba(239,68,68,.4); color:var(--red-ink); background:rgba(239,68,68,.12); }
.ds-badge--off     { border-color:var(--ds-border); color:var(--ds-dimmed); background:rgba(255,255,255,.05); }

/* ============================ КНОПКА ============================ */
/* Дефолт Remnawave: radius md, variant light, плавный transition. */
.ds-btn { display:inline-flex; align-items:center; justify-content:center; gap:6px; cursor:pointer;
  padding:8px 16px; border-radius:var(--r-md); font-family:var(--font); font-size:var(--fs-sm); font-weight:600;
  border:1px solid transparent; transition:all var(--dur) ease; text-decoration:none; }
.ds-btn--primary { background:var(--ds-primary); color:var(--ds-primary-ink); }
.ds-btn--primary:hover { background:var(--ds-primary-hover); }
.ds-btn--light { background:rgba(21,170,191,.12); color:var(--cyan-4); }
.ds-btn--light:hover { background:rgba(21,170,191,.20); }
.ds-btn--outline { background:transparent; border-color:var(--ds-border); color:var(--ds-text); }
.ds-btn--outline:hover { border-color:var(--cyan-7); }

/* ============================ ПОЛЕ ВВОДА ============================ */
.ds-input, .ds-select { width:100%; padding:9px 12px; border-radius:var(--r-md);
  background:var(--ds-surface-2); border:1px solid var(--ds-border); color:var(--ds-text);
  font-family:var(--font); font-size:var(--fs-sm); transition:border-color var(--dur); }
.ds-input:focus, .ds-select:focus { outline:none; border-color:var(--cyan-7); }
.ds-label { display:block; font-size:var(--fs-xs); font-weight:600; color:var(--ds-dimmed); margin-bottom:4px; }

/* ============================ ТАБЛИЦА ============================ */
.ds-table { width:100%; border-collapse:collapse; font-size:var(--fs-sm); }
.ds-table th { text-align:left; padding:10px 12px; color:var(--ds-dimmed); font-weight:600;
  font-size:var(--fs-xs); text-transform:uppercase; letter-spacing:.03em; border-bottom:1px solid var(--ds-border); }
.ds-table td { padding:11px 12px; border-bottom:1px solid var(--ds-border-soft); }
.ds-table tbody tr:hover { background:rgba(255,255,255,.03); }

/* ============================ СТАТУС-ИНДИКАТОР ============================ */
/* Точка статуса: 🟢 alive / 🔴 error / ⚪️ off — цвет + мягкое кольцо. Для карточек нод/линий.
   Зарево-glow снято 15-08 (решение владельца): цветное свечение — только у логотипа-маяка. */
.ds-dot { width:10px; height:10px; border-radius:50%; display:inline-block; background:var(--st-off); }
.ds-dot--alive { background:var(--st-alive); box-shadow:0 0 0 3px rgba(45,212,191,.18); }
.ds-dot--error { background:var(--st-error); box-shadow:0 0 0 3px rgba(239,68,68,.18); }

/* Карточка-строка со статус-подсветкой градиентом (паттерн Remnawave NodeCard). */
.ds-row { border-radius:var(--r-md); padding:12px 16px; border:1px solid var(--ds-border);
  background:linear-gradient(135deg, rgba(107,114,128,.10) 0%, var(--dark-7) 100%); transition:border-color var(--dur); }
.ds-row--alive { border-color:rgba(45,212,191,.30); background:linear-gradient(135deg, rgba(45,212,191,.15) 0%, var(--dark-7) 100%); }
.ds-row--error { border-color:rgba(239,68,68,.30); background:linear-gradient(135deg, rgba(239,68,68,.15) 0%, var(--dark-7) 100%); }
.ds-row--off   { border-color:rgba(107,114,128,.30); background:linear-gradient(135deg, rgba(107,114,128,.15) 0%, var(--dark-7) 100%); }
.ds-row:hover { border-color:var(--cyan-7); }

/* ============================ СКРОЛЛБАР ============================ */
.ds ::-webkit-scrollbar { width:8px; height:8px; }
.ds ::-webkit-scrollbar-thumb { background:var(--dark-5); border-radius:4px; }
.ds ::-webkit-scrollbar-track { background:transparent; }
