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

603 lines
43 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-mass.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.6% 0.0015 215);
--surface: oklch(100% 0 0);
--surface-2: oklch(98.4% 0.003 215);
--ink: oklch(24% 0.04 204);
--ink-2: oklch(45% 0.03 204);
--ink-3: oklch(60% 0.025 204);
--border: oklch(92% 0.014 200);
--accent: oklch(48% 0.105 178);
--accent-hover: oklch(41% 0.1 178);
--accent-soft: oklch(95.5% 0.032 180);
--sel: oklch(96.5% 0.016 190);
--on-accent: oklch(99% 0.01 180);
--glow-1: oklch(86% 0.085 190);
--glow-2: oklch(88% 0.075 205);
--glow-3: oklch(89% 0.07 172);
--veil: oklch(100% 0 0 / 0.55);
--land: oklch(95% 0.012 196);
--land-line: oklch(90% 0.018 196);
--shadow: 0 1px 2px oklch(24% 0.04 204 / 0.05), 0 12px 32px -12px oklch(24% 0.04 204 / 0.14);
}
:root[data-veilix-theme="dark"]{
--bg: oklch(23% 0.026 210);
--surface: oklch(26.5% 0.028 210);
--surface-2: oklch(30% 0.03 210);
--ink: oklch(96% 0.012 196);
--ink-2: oklch(80% 0.02 196);
--ink-3: oklch(65% 0.025 196);
--border: oklch(36% 0.04 204);
--accent: oklch(76% 0.105 190);
--accent-hover: oklch(83% 0.09 190);
--accent-soft: oklch(31% 0.05 190);
--sel: oklch(30% 0.03 195);
--on-accent: oklch(20% 0.04 204);
--glow-1: oklch(52% 0.09 200);
--glow-2: oklch(47% 0.085 215);
--glow-3: oklch(50% 0.08 180);
--veil: oklch(100% 0 0 / 0.07);
--land: oklch(31% 0.035 204);
--land-line: oklch(37% 0.04 204);
--shadow: 0 1px 2px oklch(12% 0.03 204 / 0.4), 0 16px 40px -16px oklch(9% 0.03 204 / 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="#e3f4f1">
<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="#00705e" />
<rect x="570" y="360" width="150" height="150" rx="48" fill="#ffffff" fill-opacity="0.62" stroke="#00705e" 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="MassMain.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: 132px; 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="MassPrice.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Цены</a>
<a href="#top" style="color: var(--ink);">Локации</a>
<a href="MassSupport.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="MassApp.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="MassOrder.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="MassPrice.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="MassSupport.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="MassApp.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="MassOrder.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>
Скоро
</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;">Одна цена за всё: 699 ₽ в месяц или 6 990 ₽ в год.</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: 8px; flex: none; min-height: 32px; 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.badge }}
</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>
</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, который не нужно отключать. Работаем с 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="MassPrice.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="MassSupport.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 = 106;
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 statusG = g.append("g").attr("transform", "translate(20, 78)");
statusG.append("circle").attr("cx", 5).attr("cy", -4).attr("r", 4)
.attr("fill", d.ready ? "var(--accent)" : "var(--bg)")
.attr("stroke", d.ready ? "none" : "var(--ink-3)").attr("stroke-width", d.ready ? 0 : 1.5);
statusG.append("text").attr("x", 17).attr("font-size", 13).attr("font-family", FONT)
.attr("fill", d.ready ? "var(--accent)" : "var(--ink-3)")
.text(d.ready ? "Доступно в подписке" : "Скоро");
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(--sel)";
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 ? "Доступно в подписке" : "Скоро",
badge: d.ready ? "Включено" : "Скоро",
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 = "MassOrder.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>