Files
2026-10-21 03:30:38 +02:00

612 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
<link href="https://fonts.googleapis.com/css2?family=Commissioner:wght@300;400;500;600&family=Unbounded:wght@500;600&display=swap" rel="stylesheet" />
<script>(function(){if(window.__veilixI18nSrc)return;window.__veilixI18nSrc="./i18n.js?v="+Date.now().toString(36)+Math.random().toString(36).slice(2,8);var s=document.createElement("script");s.src=window.__veilixI18nSrc;document.head.appendChild(s);})();</script>
<script src="https://unpkg.com/d3@7.9.0/dist/d3.min.js" integrity="sha384-CjloA8y00+1SDAUkjs099PVfnY2KmDC2BZnws9kh8D/lX1s46w6EPhpXdqMfjK6i" crossorigin="anonymous"></script>
<script src="https://unpkg.com/topojson-client@3.1.0/dist/topojson-client.min.js" integrity="sha384-Ukv1p/xTma6P4/2bY5KzWBw+ydSpXmhCMtyciIQVDJ1RmOxtCYNMF1uXT9T63H67" crossorigin="anonymous"></script>
<style>
:root{
--bg: oklch(99% 0.005 296);
--surface: oklch(100% 0 0);
--surface-2: oklch(97.5% 0.01 296);
--ink: oklch(24% 0.04 296);
--ink-2: oklch(45% 0.03 296);
--ink-3: oklch(60% 0.025 296);
--border: oklch(92% 0.014 296);
--accent: oklch(45% 0.17 296);
--accent-hover: oklch(38% 0.17 296);
--accent-soft: oklch(95.5% 0.028 296);
--on-accent: oklch(99% 0.01 296);
--glow-1: oklch(86% 0.1 296);
--glow-2: oklch(89% 0.09 266);
--glow-3: oklch(91% 0.08 332);
--veil: oklch(100% 0 0 / 0.55);
--land: oklch(93% 0.015 296);
--land-line: oklch(87% 0.02 296);
--shadow: 0 1px 2px oklch(24% 0.04 296 / 0.05), 0 12px 32px -12px oklch(24% 0.04 296 / 0.14);
}
:root[data-veilix-theme="dark"]{
--bg: oklch(17% 0.022 296);
--surface: oklch(21% 0.026 296);
--surface-2: oklch(24% 0.03 296);
--ink: oklch(96% 0.01 296);
--ink-2: oklch(79% 0.02 296);
--ink-3: oklch(63% 0.025 296);
--border: oklch(31% 0.032 296);
--accent: oklch(74% 0.15 296);
--accent-hover: oklch(80% 0.13 296);
--accent-soft: oklch(27% 0.05 296);
--on-accent: oklch(17% 0.03 296);
--glow-1: oklch(45% 0.16 296);
--glow-2: oklch(40% 0.14 266);
--glow-3: oklch(42% 0.13 332);
--veil: oklch(100% 0 0 / 0.07);
--land: oklch(27% 0.03 296);
--land-line: oklch(34% 0.035 296);
--shadow: 0 1px 2px oklch(10% 0.02 296 / 0.4), 0 16px 40px -16px oklch(8% 0.02 296 / 0.7);
}
*{ box-sizing: border-box; }
input, textarea, select{ font-size: 16px; }
[hidden]{ display: none !important; }
body{ margin:0; background: var(--bg); color: var(--ink); font-family:"Commissioner", system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
a{ color: var(--accent); text-decoration: none; }
a:hover{ color: var(--accent-hover); }
@keyframes veilPulse{
0%{ transform: scale(1); opacity: 0.55; }
70%{ transform: scale(2.6); opacity: 0; }
100%{ transform: scale(2.6); opacity: 0; }
}
</style>
</helmet>
<template id="__bundler_thumbnail" data-bg-color="#efeaf8">
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg">
<rect x="480" y="290" width="150" height="150" rx="48" fill="#5b32c9" />
<rect x="570" y="360" width="150" height="150" rx="48" fill="#ffffff" fill-opacity="0.62" stroke="#5b32c9" stroke-width="6" />
</svg>
</template>
<div style="background: var(--bg); color: var(--ink); font-family: 'Commissioner', system-ui, sans-serif; font-weight: 400; letter-spacing: -0.01em; min-height: 100vh;">
<header style="position: sticky; top: 0; z-index: 40; background: color-mix(in oklab, var(--bg) 82%, transparent); backdrop-filter: blur(20px) saturate(1.4); -webkit-backdrop-filter: blur(20px) saturate(1.4); border-bottom: 1px solid var(--border);">
<div style="max-width: 1200px; margin: 0 auto; padding: 14px 24px; min-height: 66px; display: flex; flex-wrap: nowrap; align-items: center; gap: 14px 40px;">
<a href="Main.dc.html" style="display: flex; align-items: center; gap: 10px; color: var(--ink); flex: none;">
<span style="position: relative; width: 28px; height: 28px; display: block; flex: none;">
<span style="position: absolute; left: 0; top: 3px; width: 21px; height: 21px; border-radius: 7px; background: linear-gradient(140deg, var(--accent), color-mix(in oklab, var(--accent) 55%, var(--glow-3))); display: block;"></span>
<span style="position: absolute; right: 0; bottom: 3px; width: 21px; height: 21px; border-radius: 7px; background: var(--veil); border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent); backdrop-filter: blur(2px); display: block;"></span>
</span>
<span style="font-family: 'Unbounded', 'Commissioner', sans-serif; font-weight: 600; font-size: 17px; letter-spacing: -0.02em; width: 88px; flex: none; white-space: nowrap;">Вейликс</span>
</a>
<nav hidden="{{ navOff }}" style="display: flex; flex-wrap: wrap; gap: 10px 28px; font-size: 15px; font-weight: 500; color: var(--ink-2);">
<a href="Price.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Цены</a>
<a href="#top" style="color: var(--ink);">Локации</a>
<a href="Support.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Поддержка</a>
</nav>
<div style="margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 8px;">
<div hidden="{{ navOff }}" style="position: relative;">
<button type="button" onClick="{{ toggleLangMenu }}" title="Язык" style="display: flex; align-items: center; gap: 7px; height: 38px; padding: 0 11px; border: 1px solid var(--border); border-radius: 10px; background: transparent; color: var(--ink-2); font-family: inherit; font-size: 14px; cursor: pointer;" style-hover="color: var(--ink); border-color: var(--ink-3);">
<span style="position: relative; width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid currentColor; display: block; flex: none;">
<span style="position: absolute; left: -1.5px; top: 5.75px; width: 16px; height: 1.5px; background: currentColor; display: block;"></span>
<span style="position: absolute; left: 3.25px; top: -1.5px; width: 8px; height: 16px; border-radius: 50%; border: 1.5px solid currentColor; display: block;"></span>
</span>
<span style="font-variant-numeric: tabular-nums;">{{ langLabel }}</span>
</button>
<div hidden="{{ langMenuOff }}" style="position: absolute; right: 0; top: 46px; width: 172px; padding: 6px; background: var(--surface); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow); font-size: 14px;">
<button type="button" onClick="{{ setRu }}" style="display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; padding: 9px 10px; border: 0; border-radius: 9px; background: {{ ruBg }}; color: var(--ink); font-family: inherit; font-size: 14px; text-align: left; cursor: pointer;">
<span>Русский</span>
<span style="color: var(--accent);">{{ ruCheck }}</span>
</button>
<button type="button" onClick="{{ setEn }}" style="display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; padding: 9px 10px; border: 0; border-radius: 9px; background: {{ enBg }}; color: var(--ink); font-family: inherit; font-size: 14px; text-align: left; cursor: pointer;">
<span>English</span>
<span style="color: var(--accent);">{{ enCheck }}</span>
</button>
</div>
</div>
<a href="App.dc.html" hidden="{{ navOff }}" style="display: flex; align-items: center; justify-content: center; height: 38px; width: 78px; flex: none; box-sizing: border-box; border-radius: 10px; color: var(--ink-2); font-size: 15px;" style-hover="color: var(--ink); background: var(--surface-2);">Войти</a>
<a href="Order.dc.html" hidden="{{ navOff }}" style="display: flex; align-items: center; justify-content: center; height: 38px; width: 142px; flex: none; box-sizing: border-box; border-radius: 10px; background: var(--accent); color: var(--on-accent); font-size: 15px; font-weight: 500; box-shadow: 0 6px 18px -8px var(--accent);" style-hover="background: var(--accent-hover); color: var(--on-accent);">Получить VPN</a>
<button type="button" hidden="{{ burgerOff }}" onClick="{{ toggleMenu }}" title="Меню" style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; width: 42px; height: 38px; border: 1px solid var(--border); border-radius: 10px; background: transparent; color: var(--ink); cursor: pointer;" style-hover="border-color: var(--ink-3);">
<span style="width: 18px; height: 2px; border-radius: 2px; background: currentColor; display: block;"></span>
<span style="width: 18px; height: 2px; border-radius: 2px; background: currentColor; display: block;"></span>
<span style="width: 18px; height: 2px; border-radius: 2px; background: currentColor; display: block;"></span>
</button>
</div>
</div>
<div hidden="{{ menuOff }}" style="position: absolute; left: 0; right: 0; top: 100%; z-index: 45; padding: 10px 20px 18px; background: var(--bg); border-bottom: 1px solid var(--border); box-shadow: var(--shadow); display: grid; gap: 2px;">
<a href="Price.dc.html" onClick="{{ closeMenu }}" style="padding: 13px 6px; font-size: 17px; color: var(--ink);">Цены</a>
<a href="#top" onClick="{{ closeMenu }}" style="padding: 13px 6px; font-size: 17px; color: var(--ink);">Локации</a>
<a href="Support.dc.html" onClick="{{ closeMenu }}" style="padding: 13px 6px; font-size: 17px; color: var(--ink);">Поддержка</a>
<div style="display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 6px; margin-top: 6px; border-top: 1px solid var(--border);">
<a href="App.dc.html" onClick="{{ closeMenu }}" style="padding: 13px 6px; font-size: 17px; color: var(--ink);">Войти</a>
<div style="display: flex; gap: 6px; flex: none;">
<button type="button" onClick="{{ setRu }}" style="padding: 9px 13px; border: 1px solid var(--border); border-radius: 10px; background: {{ ruBg }}; color: var(--ink); font-family: inherit; font-size: 13px; cursor: pointer; white-space: nowrap;">Русский</button>
<button type="button" onClick="{{ setEn }}" style="padding: 9px 13px; border: 1px solid var(--border); border-radius: 10px; background: {{ enBg }}; color: var(--ink); font-family: inherit; font-size: 13px; cursor: pointer; white-space: nowrap;">English</button>
</div>
</div>
<a href="Order.dc.html" onClick="{{ closeMenu }}" style="display: flex; align-items: center; justify-content: center; height: 50px; margin-top: 12px; border-radius: 12px; background: var(--accent); color: var(--on-accent); font-size: 16px; font-weight: 500;">Получить VPN</a>
</div>
</header>
<main id="top" style="max-width: 1200px; margin: 0 auto; padding: 0 clamp(14px, 4vw, 24px) 80px;">
<section style="position: relative; isolation: isolate; margin-top: clamp(14px, 3vw, 40px); border-radius: 28px; border: 1px solid var(--border); background: var(--surface); box-shadow: var(--shadow);">
<div style="position: absolute; inset: 0; border-radius: 28px; overflow: hidden; pointer-events: none; -webkit-mask-image: -webkit-radial-gradient(white, black); mask-image: radial-gradient(white, black);">
<div style="position: absolute; right: min(-90px, calc(-150px + 11vw)); top: min(-130px, calc(-190px + 11vw)); width: clamp(190px, 40vw, 440px); height: clamp(190px, 40vw, 440px); border-radius: 50%; background: radial-gradient(circle at 50% 50%, var(--glow-1) 0%, color-mix(in oklab, var(--glow-1) 35%, transparent) 55%, transparent 78%); filter: blur(80px); opacity: 0.45;"></div>
<div style="position: absolute; left: min(-70px, calc(-130px + 11vw)); bottom: min(-150px, calc(-210px + 11vw)); width: clamp(160px, 34vw, 380px); height: clamp(160px, 34vw, 380px); border-radius: 50%; background: radial-gradient(circle at 50% 50%, var(--glow-3) 0%, color-mix(in oklab, var(--glow-3) 35%, transparent) 55%, transparent 78%); filter: blur(80px); opacity: 0.35;"></div>
</div>
<div style="position: relative; padding: clamp(22px, 5vw, 48px) clamp(14px, 3.5vw, 40px) clamp(20px, 4vw, 36px);">
<h1 style="margin: 0 0 12px; font-size: clamp(34px, 4.4vw, 52px); font-weight: 600; letter-spacing: -0.035em;">Локации</h1>
<p style="margin: 0 0 28px; max-width: 46em; font-size: 17px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">30 стран на выбор и российский адрес в комплекте с любым тарифом.</p>
<div id="veilix-map" style="width: 100%; min-height: 240px;"></div>
<div style="margin-top: 10px; font-size: 13px; color: var(--ink-3);">Нажмите точку на карте — покажем страну и цену</div>
<div hidden="{{ swipeOff }}" style="margin-top: 4px; font-size: 13px; color: var(--ink-3);">Карту можно прокрутить в сторону</div>
<div style="display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 20px; font-size: 14px; color: var(--ink-2);">
<span style="display: inline-flex; align-items: center; gap: 8px;">
<span style="width: 9px; height: 9px; border-radius: 50%; background: var(--accent); display: block;"></span>
Серверы в наличии
</span>
<span style="display: inline-flex; align-items: center; gap: 8px;">
<span style="width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--ink-3); display: block;"></span>
Установим за 24 часа
</span>
<span style="display: inline-flex; align-items: center; gap: 8px;">
<span style="width: 9px; height: 9px; border-radius: 2px; background: var(--ink-2); display: block;"></span>
RU-адрес входит в каждый тариф
</span>
</div>
</div>
</section>
<section style="padding: 56px 0 0;">
<h2 style="margin: 0 0 10px; font-size: clamp(26px, 2.8vw, 34px); font-weight: 600; letter-spacing: -0.03em;">Выберите страну</h2>
<p style="margin: 0 0 24px; max-width: 52em; font-size: 15px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">Базовая цена — 4 900 ₽ первый месяц и 2 499 ₽ далее. В редких локациях она выше и указана на карточке.</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px;">
<sc-for list="{{ items }}" as="loc" hint-placeholder-count="12">
<div role="button" tabindex="0" onClick="{{ loc.pick }}" style="display: grid; align-content: start; gap: 14px; padding: 22px; border-radius: 22px; border: 1px solid {{ loc.border }}; background: {{ loc.bg }}; color: var(--ink); cursor: pointer;" style-hover="border-color: var(--ink-3);">
<span style="display: flex; align-items: center; justify-content: space-between; gap: 14px;">
{{ loc.flag }}
<span style="display: flex; align-items: center; gap: 12px; flex: none; min-height: 32px;">
<span onClick="{{ loc.buy }}" hidden="{{ loc.buyOff }}" style="display: flex; align-items: center; justify-content: center; height: 32px; padding: 0 16px; border-radius: 10px; background: var(--accent); color: var(--on-accent); font-size: 14px; font-weight: 500; cursor: pointer;">Купить</span>
<span hidden="{{ loc.dotOff }}" style="width: 11px; height: 11px; border-radius: 50%; background: {{ loc.dot }}; display: block; flex: none;"></span>
</span>
</span>
<span style="display: grid; gap: 5px;">
<span style="font-size: 19px; font-weight: 500; letter-spacing: -0.02em;">{{ loc.country }}</span>
<span style="font-size: 14px; color: var(--ink-3);">{{ loc.city }}</span>
</span>
<span style="display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: {{ loc.statusInk }};">
<span style="width: 6px; height: 6px; border-radius: 50%; background: {{ loc.statusDot }}; border: {{ loc.statusRing }}; display: block;"></span>
{{ loc.status }}
</span>
<span style="display: grid; gap: 12px; padding-top: 14px; border-top: 1px solid var(--border);">
<span style="display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums;">
<span style="font-size: 17px; font-weight: 500; color: var(--ink);">{{ loc.setup }}</span>
первый месяц · далее
<span style="font-weight: 500; color: var(--ink);">{{ loc.month }}</span>
</span>
</span>
</div>
</sc-for>
</div>
</section>
<section style="padding: 56px 0 0;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px;">
<div style="padding: clamp(20px, 5vw, 32px); border-radius: 22px; background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);">
<h3 style="margin: 0 0 10px; font-size: 22px; font-weight: 600; letter-spacing: -0.025em;">Российский адрес в каждом тарифе</h3>
<p style="margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">Он работает в обе стороны: из России банки и госуслуги видят обычное местное подключение, из другой страны те же сервисы открываются так, будто вы дома.</p>
</div>
<div style="padding: clamp(20px, 5vw, 32px); border-radius: 22px; background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);">
<h3 id="lead" style="margin: 0 0 10px; font-size: 22px; font-weight: 600; letter-spacing: -0.025em; scroll-margin-top: 90px;">Нужны индивидуальные условия</h3>
<p style="margin: 0 0 18px; font-size: 15px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">Нужной страны нет в списке, нужно много адресов или свой сценарий маршрутизации — напишите, скажем сроки и установим под вас.</p>
<button type="button" onClick="{{ openLead }}" hidden="{{ leadOpen }}" style="display: inline-flex; align-items: center; height: 46px; padding: 0 20px; border-radius: 12px; border: 1px solid var(--accent); background: transparent; color: var(--accent); font-family: inherit; font-size: 15px; font-weight: 500; cursor: pointer;" style-hover="background: var(--accent-soft);">Оставить заявку</button>
<div hidden="{{ leadClosed }}" style="display: grid; gap: 10px; max-width: 460px;">
<input type="text" placeholder="Имя" style="height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; width: 100%;" />
<input type="email" placeholder="Email" style="height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; width: 100%;" />
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;">
<input type="text" placeholder="Telegram" style="height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; width: 100%;" />
<input type="text" placeholder="WhatsApp" style="height: 48px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; width: 100%;" />
</div>
<textarea rows="3" placeholder="Коротко о задаче" style="padding: 12px 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; resize: vertical; width: 100%;"></textarea>
<button type="button" onClick="{{ sendLead }}" style="display: inline-flex; align-items: center; justify-content: center; height: 48px; padding: 0 22px; border-radius: 12px; border: 0; background: var(--accent); color: var(--on-accent); font-family: inherit; font-size: 15px; font-weight: 500; cursor: pointer;" style-hover="background: var(--accent-hover);">{{ leadButton }}</button>
</div>
</div>
</div>
</section>
</main>
<footer style="border-top: 1px solid var(--border); background: var(--surface-2);">
<div style="max-width: 1200px; margin: 0 auto; padding: 48px clamp(16px, 4vw, 24px) 32px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 32px;">
<div>
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 14px;">
<span style="position: relative; width: 24px; height: 24px; display: block; flex: none;">
<span style="position: absolute; left: 0; top: 3px; width: 18px; height: 18px; border-radius: 6px; background: linear-gradient(140deg, var(--accent), color-mix(in oklab, var(--accent) 55%, var(--glow-3))); display: block;"></span>
<span style="position: absolute; right: 0; bottom: 3px; width: 18px; height: 18px; border-radius: 6px; background: var(--veil); border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent); display: block;"></span>
</span>
<span style="font-family: 'Unbounded', 'Commissioner', sans-serif; font-weight: 600; font-size: 15px; letter-spacing: -0.02em;">Вейликс</span>
</div>
<p style="margin: 0 0 20px; max-width: 26em; font-size: 14px; line-height: 1.55; color: var(--ink-3); font-weight: 300;">Персональные VPN-серверы с индивидуальным IP. Работаем с 2022 года.</p>
<div style="display: flex; flex-wrap: wrap; gap: 6px;">
<span style="display: flex; align-items: center; justify-content: center; width: 60px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-3);">VISA</span>
<span style="display: flex; align-items: center; justify-content: center; width: 60px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-3);">MC</span>
<span style="display: flex; align-items: center; justify-content: center; width: 60px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-3);">МИР</span>
<span style="display: flex; align-items: center; justify-content: center; width: 60px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); font-size: 11px; letter-spacing: 0.06em; color: var(--ink-3);">CRYPTO</span>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(130px, 1fr)); gap: 24px 32px; align-content: start;">
<div style="display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-content: start; font-size: 14px;">
<div style="font-size: 13px; color: var(--ink-3); margin-bottom: 2px;">Сервис</div>
<a href="Price.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Цены</a>
<a href="#top" style="color: var(--ink-2);" style-hover="color: var(--ink);">Локации</a>
<a href="Support.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Поддержка</a>
</div>
<div style="display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-content: start; font-size: 14px;">
<div style="font-size: 13px; color: var(--ink-3); margin-bottom: 2px;">Документы</div>
<a href="#top" style="color: var(--ink-2);" style-hover="color: var(--ink);">Условия использования</a>
<a href="#top" style="color: var(--ink-2);" style-hover="color: var(--ink);">Политика конфиденциальности</a>
<a href="#top" style="color: var(--ink-2);" style-hover="color: var(--ink);">Возврат средств</a>
</div>
</div>
</div>
<div style="max-width: 1200px; margin: 0 auto; padding: 0 clamp(16px, 4vw, 24px) 40px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;">
<div style="font-size: 13px; color: var(--ink-3);">© 2026 Вейликс</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div style="display: flex; padding: 2px; border-radius: 9px; border: 1px solid var(--border); background: var(--surface); flex: none;">
<button type="button" onClick="{{ setLight }}" title="Светлая тема" style="display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; border-radius: 7px; background: {{ lightBg }}; color: {{ lightInk }}; cursor: pointer;"><span style="position: relative; width: 14px; height: 14px; display: block;"><span style="position: absolute; left: 3px; top: 3px; width: 8px; height: 8px; border-radius: 50%; background: currentColor; display: block;"></span><span style="position: absolute; left: 0; top: 0; width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid currentColor; opacity: 0.45; display: block;"></span></span></button>
<button type="button" onClick="{{ setDark }}" title="Тёмная тема" style="display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; border-radius: 7px; background: {{ darkBg }}; color: {{ darkInk }}; cursor: pointer;"><span style="width: 14px; height: 14px; border-radius: 50%; box-shadow: inset -5px -1.5px 0 0 currentColor; display: block;"></span></button>
<button type="button" onClick="{{ setSystem }}" title="Как в системе" style="display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; border-radius: 7px; background: {{ systemBg }}; color: {{ systemInk }}; cursor: pointer;"><span style="width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid currentColor; background: linear-gradient(90deg, currentColor 50%, transparent 50%); display: block;"></span></button>
</div>
<div style="display: flex; padding: 2px; border-radius: 9px; border: 1px solid var(--border); background: var(--surface); flex: none;">
<button type="button" onClick="{{ setRu }}" style="padding: 0 10px; height: 28px; border: 0; border-radius: 7px; background: {{ ruBg }}; color: {{ ruInk }}; font-family: inherit; font-size: 12px; cursor: pointer;">RU</button>
<button type="button" onClick="{{ setEn }}" style="padding: 0 10px; height: 28px; border: 0; border-radius: 7px; background: {{ enBg }}; color: {{ enInk }}; font-family: inherit; font-size: 12px; cursor: pointer;">EN</button>
</div>
</div>
</div>
</footer>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{&quot;defaultTheme&quot;:{&quot;editor&quot;:&quot;enum&quot;,&quot;options&quot;:[&quot;light&quot;,&quot;dark&quot;,&quot;system&quot;],&quot;default&quot;:&quot;light&quot;,&quot;tsType&quot;:&quot;'light' | 'dark' | 'system'&quot;,&quot;section&quot;:&quot;Тема&quot;}}">
class Component extends DCLogic {
state = { theme: null, sysDark: false, lang: "ru", langMenu: false, narrow: false, menu: false, loc: 0, lead: false, leadSent: false };
data() {
const base = { setup: "4 900 ₽", month: "2 499 ₽" };
const rare = { setup: "6 900 ₽", month: "3 499 ₽" };
const far = { setup: "9 900 ₽", month: "4 999 ₽" };
const L = (country, city, code, lng, lat, ready, tier) => ({ country, city, code, lng, lat, ready, setup: tier.setup, month: tier.month, rare: tier !== base });
return [
L("Нидерланды", "Амстердам", "nl", 4.9, 52.37, true, base),
L("Германия", "Франкфурт", "de", 8.68, 50.11, true, base),
L("США", "Нью-Йорк", "us", -74.01, 40.71, true, base),
L("Великобритания", "Лондон", "gb", -0.13, 51.51, true, base),
L("Франция", "Париж", "fr", 2.35, 48.86, true, base),
L("Финляндия", "Хельсинки", "fi", 24.94, 60.17, true, base),
L("Швеция", "Стокгольм", "se", 18.07, 59.33, true, base),
L("Норвегия", "Осло", "no", 10.75, 59.91, false, base),
L("Дания", "Копенгаген", "dk", 12.57, 55.68, false, base),
L("Швейцария", "Цюрих", "ch", 8.54, 47.37, true, rare),
L("Австрия", "Вена", "at", 16.37, 48.21, true, base),
L("Испания", "Мадрид", "es", -3.7, 40.42, true, base),
L("Италия", "Милан", "it", 9.19, 45.46, true, base),
L("Польша", "Варшава", "pl", 21.01, 52.23, true, base),
L("Чехия", "Прага", "cz", 14.44, 50.08, true, base),
L("Румыния", "Бухарест", "ro", 26.1, 44.43, false, base),
L("Литва", "Вильнюс", "lt", 25.28, 54.69, true, base),
L("Латвия", "Рига", "lv", 24.11, 56.95, true, base),
L("Эстония", "Таллин", "ee", 24.75, 59.44, false, base),
L("Турция", "Стамбул", "tr", 28.98, 41.01, true, base),
L("Казахстан", "Алматы", "kz", 76.89, 43.24, false, base),
L("Армения", "Ереван", "am", 44.51, 40.18, false, base),
L("Грузия", "Тбилиси", "ge", 44.8, 41.72, false, base),
L("ОАЭ", "Дубай", "ae", 55.27, 25.2, true, rare),
L("Сингапур", "Сингапур", "sg", 103.82, 1.35, true, rare),
L("Япония", "Токио", "jp", 139.69, 35.69, true, rare),
L("Южная Корея", "Сеул", "kr", 126.98, 37.57, false, rare),
L("Канада", "Торонто", "ca", -79.38, 43.65, true, base),
L("Австралия", "Сидней", "au", 151.21, -33.87, false, far),
L("Бразилия", "Сан-Паулу", "br", -46.63, -23.55, false, far)
];
}
componentDidMount() {
const mq = window.matchMedia("(prefers-color-scheme: dark)");
this.mq = mq;
this.onSys = () => this.setState({ sysDark: mq.matches });
mq.addEventListener("change", this.onSys);
this.onResize = () => {
const n = window.innerWidth < 900;
if (n !== this.state.narrow) this.setState({ narrow: n, menu: false });
};
window.addEventListener("resize", this.onResize);
this.onResize();
let saved = null;
try { saved = localStorage.getItem("veilix.theme"); } catch (e) {}
let savedLang = null;
try { savedLang = localStorage.getItem("veilix.lang"); } catch (e) {}
this.setState({ sysDark: mq.matches, theme: saved || this.props.defaultTheme || "light", lang: savedLang || "ru" }, () => {
this.apply();
this.applyLang();
});
this.drawMap();
}
componentWillUnmount() {
if (this.mq) this.mq.removeEventListener("change", this.onSys);
if (this.onResize) window.removeEventListener("resize", this.onResize);
}
componentDidUpdate() { this.apply(); this.applyLang(); }
apply() {
const theme = this.state.theme || this.props.defaultTheme || "light";
const dark = theme === "dark" || (theme === "system" && this.state.sysDark);
document.documentElement.setAttribute("data-veilix-theme", dark ? "dark" : "light");
}
applyLang() {
const lang = this.state.lang || "ru";
if (window.VEILIX_APPLY_LANG) window.VEILIX_APPLY_LANG(document.body, lang);
else setTimeout(() => this.applyLang(), 150);
}
setTheme(t) {
try { localStorage.setItem("veilix.theme", t); } catch (e) {}
this.setState({ theme: t }, () => this.apply());
}
setLang(l) {
try { localStorage.setItem("veilix.lang", l); } catch (e) {}
this.setState({ lang: l, langMenu: false }, () => this.applyLang());
}
async drawMap() {
const host = document.getElementById("veilix-map");
if (!host) return;
if (!window.d3 || !window.topojson) { setTimeout(() => this.drawMap(), 200); return; }
const d3 = window.d3;
let topo;
try {
topo = await d3.json("https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json");
} catch (e) { return; }
const land = window.topojson.feature(topo, topo.objects.countries);
const W = 1200, H = 520;
const projection = d3.geoNaturalEarth1().fitExtent([[10, 10], [W - 10, H - 10]], land);
const path = d3.geoPath(projection);
host.innerHTML = "";
const center = () => {
const extra = host.scrollWidth - host.clientWidth;
if (extra > 0) host.scrollLeft = extra / 2;
};
this.centerMap = center;
if (!this.mapCentering) {
this.mapCentering = true;
window.addEventListener("resize", () => this.centerMap && this.centerMap());
}
host.style.overflowX = "auto";
host.style.overflowY = "hidden";
host.style.borderRadius = "18px";
const svg = d3.select(host).append("svg")
.attr("viewBox", "0 0 " + W + " " + H)
.attr("width", "100%")
.style("display", "block")
.style("min-width", "820px")
.style("overflow", "visible");
svg.append("g").selectAll("path").data(land.features).join("path")
.attr("d", path)
.attr("fill", "var(--land)")
.attr("stroke", "var(--land-line)")
.attr("stroke-width", 0.8);
const ru = projection([37.62, 55.75]);
if (ru) {
svg.append("rect")
.attr("x", ru[0] - 5).attr("y", ru[1] - 5)
.attr("width", 10).attr("height", 10).attr("rx", 2.5)
.attr("fill", "var(--ink-2)");
svg.append("text")
.attr("x", ru[0] + 12).attr("y", ru[1] + 4)
.attr("fill", "var(--ink-2)")
.attr("font-size", 15)
.attr("font-family", "Commissioner, system-ui, sans-serif")
.text("RU");
}
const FONT = "Commissioner, system-ui, sans-serif";
const closePopup = () => { if (this.popupG) { this.popupG.remove(); this.popupG = null; } };
this.closePopup = closePopup;
svg.on("click", closePopup);
const popup = (d, p) => {
closePopup();
const pw = 268, ph = 138;
const x = Math.max(8, Math.min(W - pw - 8, p[0] - pw / 2));
let y = p[1] - ph - 16;
if (y < 8) y = Math.min(H - ph - 8, p[1] + 18);
const g = svg.append("g").attr("transform", "translate(" + x + "," + y + ")");
this.popupG = g;
g.on("click", (ev) => ev.stopPropagation());
g.append("rect").attr("width", pw).attr("height", ph).attr("rx", 16)
.attr("fill", "var(--surface)").attr("stroke", "var(--border)");
g.append("text").attr("x", 20).attr("y", 33).attr("fill", "var(--ink)")
.attr("font-size", 17).attr("font-weight", 500).attr("font-family", FONT).text(d.country);
g.append("text").attr("x", 20).attr("y", 55).attr("fill", "var(--ink-3)")
.attr("font-size", 13).attr("font-family", FONT).text(d.city);
const price = g.append("text").attr("x", 20).attr("y", 83).attr("font-size", 13).attr("font-family", FONT);
price.append("tspan").attr("fill", "var(--ink)").attr("font-weight", 500).text(d.setup);
price.append("tspan").attr("dx", 6).attr("fill", "var(--ink-2)").text("первый месяц · далее");
price.append("tspan").attr("dx", 6).attr("fill", "var(--ink)").attr("font-weight", 500).text(d.month);
const link = g.append("a").attr("href", "Order.dc.html").style("cursor", "pointer");
link.append("rect").attr("x", 20).attr("y", 97).attr("width", 108).attr("height", 30).attr("rx", 10).attr("fill", "var(--accent)");
link.append("text").attr("x", 74).attr("y", 117).attr("text-anchor", "middle")
.attr("fill", "var(--on-accent)").attr("font-size", 13).attr("font-weight", 500).attr("font-family", FONT).text("Купить");
const close = g.append("g").style("cursor", "pointer").on("click", (ev) => { ev.stopPropagation(); closePopup(); });
close.append("rect").attr("x", pw - 44).attr("y", 14).attr("width", 30).attr("height", 30).attr("rx", 9).attr("fill", "transparent");
close.append("text").attr("x", pw - 29).attr("y", 35).attr("text-anchor", "middle")
.attr("fill", "var(--ink-3)").attr("font-size", 18).attr("font-family", FONT).text("×");
this.applyLang();
};
this.data().forEach((d, i) => {
const p = projection([d.lng, d.lat]);
if (!p) return;
const g = svg.append("g").attr("transform", "translate(" + p[0] + "," + p[1] + ")").style("cursor", "pointer");
g.append("circle").attr("r", 12).attr("fill", "transparent");
if (d.ready) {
g.append("circle").attr("r", 6).attr("fill", "var(--accent)").attr("opacity", 0.32)
.style("transform-box", "fill-box")
.style("transform-origin", "center")
.style("animation", "veilPulse 3.2s ease-out infinite");
g.append("circle").attr("r", 5).attr("fill", "var(--accent)")
.attr("stroke", "var(--surface)").attr("stroke-width", 1.4);
} else {
g.append("circle").attr("r", 5).attr("fill", "var(--bg)")
.attr("stroke", "var(--ink-3)").attr("stroke-width", 2);
}
g.append("title").text(d.country + " · " + d.city);
g.on("click", (ev) => { ev.stopPropagation(); this.setState({ loc: i }); popup(d, p); });
});
requestAnimationFrame(center);
setTimeout(center, 120);
}
flagSpecs() {
return {
nl: { rows: ["#AE1C28", "#FFFFFF", "#21468B"] },
de: { rows: ["#000000", "#DD0000", "#FFCE00"] },
us: { rows: ["#B22234", "#FFFFFF", "#B22234", "#FFFFFF", "#B22234", "#FFFFFF"], marks: [{ l: 0, t: 0, w: 22, h: 17, bg: "#3C3B6E" }] },
gb: { bg: "#012169", marks: [{ l: 17, t: 0, w: 12, h: 32, bg: "#FFFFFF" }, { l: 0, t: 10, w: 46, h: 12, bg: "#FFFFFF" }, { l: 20, t: 0, w: 6, h: 32, bg: "#C8102E" }, { l: 0, t: 13, w: 46, h: 6, bg: "#C8102E" }] },
fr: { cols: ["#002395", "#FFFFFF", "#ED2939"] },
fi: { bg: "#FFFFFF", marks: [{ l: 13, t: 0, w: 8, h: 32, bg: "#003580" }, { l: 0, t: 12, w: 46, h: 8, bg: "#003580" }] },
se: { bg: "#006AA7", marks: [{ l: 13, t: 0, w: 6, h: 32, bg: "#FECC00" }, { l: 0, t: 13, w: 46, h: 6, bg: "#FECC00" }] },
no: { bg: "#BA0C2F", marks: [{ l: 12, t: 0, w: 10, h: 32, bg: "#FFFFFF" }, { l: 0, t: 11, w: 46, h: 10, bg: "#FFFFFF" }, { l: 15, t: 0, w: 4, h: 32, bg: "#00205B" }, { l: 0, t: 14, w: 46, h: 4, bg: "#00205B" }] },
dk: { bg: "#C8102E", marks: [{ l: 13, t: 0, w: 6, h: 32, bg: "#FFFFFF" }, { l: 0, t: 13, w: 46, h: 6, bg: "#FFFFFF" }] },
ch: { bg: "#D52B1E", marks: [{ l: 20, t: 8, w: 6, h: 16, bg: "#FFFFFF" }, { l: 15, t: 13, w: 16, h: 6, bg: "#FFFFFF" }] },
at: { rows: ["#ED2939", "#FFFFFF", "#ED2939"] },
es: { rows: ["#AA151B", "#F1BF00", "#AA151B"], sizes: "1fr 2fr 1fr" },
it: { cols: ["#008C45", "#F4F5F0", "#CD212A"] },
pl: { rows: ["#FFFFFF", "#DC143C"] },
cz: { rows: ["#FFFFFF", "#D7141A"], marks: [{ l: 0, t: 0, w: 18, h: 32, bg: "#11457E", clip: "polygon(0 0, 100% 50%, 0 100%)" }] },
ro: { cols: ["#002B7F", "#FCD116", "#CE1126"] },
lt: { rows: ["#FDB913", "#006A44", "#C1272D"] },
lv: { rows: ["#9E3039", "#FFFFFF", "#9E3039"], sizes: "2fr 1fr 2fr" },
ee: { rows: ["#0072CE", "#000000", "#FFFFFF"] },
tr: { bg: "#E30A17", marks: [{ l: 11, t: 8, w: 16, h: 16, r: "50%", bg: "#FFFFFF" }, { l: 16, t: 8, w: 16, h: 16, r: "50%", bg: "#E30A17" }] },
kz: { bg: "#00AFCA", marks: [{ l: 16, t: 8, w: 15, h: 15, r: "50%", bg: "#FEC50C" }] },
am: { rows: ["#D90012", "#0033A0", "#F2A800"] },
ge: { bg: "#FFFFFF", marks: [{ l: 20, t: 0, w: 6, h: 32, bg: "#FF0000" }, { l: 0, t: 13, w: 46, h: 6, bg: "#FF0000" }] },
ae: { rows: ["#00732F", "#FFFFFF", "#000000"], marks: [{ l: 0, t: 0, w: 11, h: 32, bg: "#FF0000" }] },
sg: { rows: ["#EF3340", "#FFFFFF"], marks: [{ l: 5, t: 3, w: 11, h: 11, r: "50%", bg: "#FFFFFF" }, { l: 9, t: 3, w: 11, h: 11, r: "50%", bg: "#EF3340" }] },
jp: { bg: "#FFFFFF", marks: [{ l: 16, t: 9, w: 14, h: 14, r: "50%", bg: "#BC002D" }] },
kr: { bg: "#FFFFFF", marks: [{ l: 16, t: 9, w: 14, h: 14, r: "50%", bg: "#CD2E3A" }, { l: 16, t: 9, w: 14, h: 14, r: "50%", bg: "#0047A0", clip: "polygon(0 50%, 100% 50%, 100% 100%, 0 100%)" }] },
ca: { cols: ["#D80621", "#FFFFFF", "#D80621"], sizes: "1fr 2fr 1fr", marks: [{ l: 20, t: 9, w: 7, h: 13, bg: "#D80621", clip: "polygon(50% 0, 100% 100%, 0 100%)" }] },
au: { bg: "#00247D", marks: [{ l: 9, t: 0, w: 4, h: 16, bg: "#FFFFFF" }, { l: 0, t: 6, w: 22, h: 4, bg: "#FFFFFF" }, { l: 30, t: 19, w: 7, h: 7, r: "50%", bg: "#FFFFFF" }] },
br: { bg: "#009739", marks: [{ l: 9, t: 4, w: 28, h: 24, bg: "#FEDD00", clip: "polygon(50% 0, 100% 50%, 50% 100%, 0 50%)" }, { l: 18, t: 11, w: 10, h: 10, r: "50%", bg: "#012169" }] }
};
}
flag(code) {
const h = React.createElement;
const spec = this.flagSpecs()[code] || {};
const style = {
width: "46px", height: "32px", borderRadius: "6px", overflow: "hidden",
display: "grid", border: "1px solid var(--border)", position: "relative", flex: "none"
};
let bands = [];
if (spec.rows) {
bands = spec.rows;
style.gridTemplateRows = spec.sizes || "repeat(" + bands.length + ", 1fr)";
} else if (spec.cols) {
bands = spec.cols;
style.gridAutoFlow = "column";
style.gridTemplateColumns = spec.sizes || "repeat(" + bands.length + ", 1fr)";
} else {
style.background = spec.bg || "var(--surface-2)";
}
const kids = bands.map((c, i) => h("span", { key: "b" + i, style: { background: c, display: "block" } }));
(spec.marks || []).forEach((m, i) => kids.push(h("span", {
key: "m" + i,
style: {
position: "absolute", left: m.l + "px", top: m.t + "px", width: m.w + "px", height: m.h + "px",
borderRadius: m.r || 0, background: m.bg, clipPath: m.clip || "none", display: "block"
}
})));
return h("span", { style: style }, kids);
}
renderVals() {
const s = this.state;
const sel = "var(--accent-soft)";
const theme = s.theme || this.props.defaultTheme || "light";
const rows = this.data();
const cur = rows[s.loc];
return {
items: rows.map((d, i) => ({
country: d.country,
city: d.city,
flag: this.flag(d.code),
status: d.ready ? "Серверы в наличии" : "Установим за 24 часа",
statusInk: d.ready ? "var(--accent)" : "var(--ink-3)",
statusDot: d.ready ? "var(--accent)" : "transparent",
statusRing: d.ready ? "0" : "1.5px solid var(--ink-3)",
bg: s.loc === i ? sel : "var(--surface)",
border: s.loc === i ? "var(--accent)" : "var(--border)",
dot: s.loc === i ? "var(--accent)" : "transparent",
dotOff: s.loc === i,
buy: (e) => { e.stopPropagation(); window.location.href = "Order.dc.html"; },
setup: d.setup,
month: d.month,
buyOff: s.loc !== i,
pick: () => this.setState({ loc: i })
})),
openLead: () => this.setState({ lead: true }),
sendLead: () => this.setState({ leadSent: true }),
leadOpen: this.state.lead,
leadClosed: !this.state.lead,
leadButton: this.state.leadSent ? "Заявка отправлена" : "Отправить",
swipeOff: !s.narrow,
navOff: s.narrow,
burgerOff: !s.narrow,
menuOff: !(s.narrow && s.menu),
toggleMenu: () => this.setState(st => ({ menu: !st.menu, langMenu: false })),
closeMenu: () => this.setState({ menu: false }),
toggleLangMenu: () => this.setState(st => ({ langMenu: !st.langMenu })),
langMenuOff: !s.langMenu,
setRu: () => this.setLang("ru"),
setEn: () => this.setLang("en"),
langLabel: s.lang === "en" ? "EN" : "RU",
ruBg: s.lang === "en" ? "transparent" : sel,
enBg: s.lang === "en" ? sel : "transparent",
ruInk: s.lang === "en" ? "var(--ink-3)" : "var(--ink)",
enInk: s.lang === "en" ? "var(--ink)" : "var(--ink-3)",
ruCheck: s.lang === "en" ? "" : "✓",
enCheck: s.lang === "en" ? "✓" : "",
setLight: () => this.setTheme("light"),
setDark: () => this.setTheme("dark"),
setSystem: () => this.setTheme("system"),
lightBg: theme === "light" ? sel : "transparent",
darkBg: theme === "dark" ? sel : "transparent",
systemBg: theme === "system" ? sel : "transparent",
lightInk: theme === "light" ? "var(--ink)" : "var(--ink-3)",
darkInk: theme === "dark" ? "var(--ink)" : "var(--ink-3)",
systemInk: theme === "system" ? "var(--ink)" : "var(--ink-3)"
};
}
}
</script>
</body>
</html>