Files
veilix.app/design/handoff/project/MassOrder.dc.html
T
2026-10-21 03:30:38 +02:00

297 lines
22 KiB
HTML
Raw 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>
<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);
--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);
--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); }
input::placeholder, textarea::placeholder{ color: var(--ink-3); }
</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="border-bottom: 1px solid var(--border); background: var(--bg);">
<div style="max-width: 1080px; margin: 0 auto; padding: 16px 24px; display: flex; flex-wrap: wrap; align-items: center; gap: 14px 24px;">
<a href="MassMain.dc.html" style="display: flex; align-items: center; gap: 10px; color: var(--ink); flex: none;">
<span style="position: relative; width: 26px; height: 26px; display: block; flex: none;">
<span style="position: absolute; left: 0; top: 3px; width: 19px; height: 19px; 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: 19px; height: 19px; 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: 16px; letter-spacing: -0.02em;">ВейликсВПН</span>
</a>
<div style="margin-left: auto; display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--ink-3);">
<button type="button" onClick="{{ toggleLang }}" title="{{ langTitle }}" style="display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; border-radius: 10px; border: 1px solid var(--border); 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>
<span>Оформление заказа</span>
<a href="MassPrice.dc.html" style="color: var(--ink-2);" style-hover="color: var(--ink);">Отменить</a>
</div>
</div>
</header>
<main style="max-width: 1080px; margin: 0 auto; padding: 40px 24px 80px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 32px; align-items: start;">
<div style="display: grid; gap: 16px;">
<div style="border: 1px solid {{ step1Border }}; border-radius: 20px; background: var(--surface); box-shadow: var(--shadow); overflow: hidden;">
<div style="display: flex; align-items: center; gap: 14px; padding: 22px 24px;">
<span style="display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; background: {{ step1Dot }}; color: {{ step1DotInk }}; font-size: 13px; font-weight: 500; flex: none;">1</span>
<span style="flex: 1; font-size: 18px; font-weight: 500; letter-spacing: -0.02em;">Почта</span>
<span hidden="{{ emailNotDone }}" style="font-size: 14px; color: var(--ink-2);">{{ emailValue }}</span>
<button type="button" hidden="{{ emailNotDone }}" onClick="{{ editEmail }}" style="border: 0; background: transparent; color: var(--accent); font-family: inherit; font-size: 14px; cursor: pointer; padding: 0;">Изменить</button>
</div>
<div hidden="{{ step1Off }}" style="padding: 0 24px 24px;">
<p style="margin: 0 0 16px; max-width: 46em; font-size: 15px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">Введите почту — пришлём одноразовый код. Отдельной регистрации нет: если вы у нас уже были, попадёте в свой кабинет, если нет — он создастся сам.</p>
<div hidden="{{ codeSent }}" style="display: flex; flex-wrap: wrap; gap: 10px;">
<input type="email" value="{{ emailValue }}" onInput="{{ onEmail }}" placeholder="you@example.com" style="flex: 1; min-width: 220px; height: 50px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px;" />
<button type="button" onClick="{{ sendCode }}" style="height: 50px; 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);">Прислать код</button>
</div>
<div hidden="{{ codeNotSent }}" style="display: grid; gap: 12px;">
<div style="font-size: 14px; color: var(--ink-2);">{{ codeLine }}</div>
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
<input type="text" inputmode="numeric" placeholder="6 цифр" style="flex: 1; min-width: 180px; height: 50px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 17px; letter-spacing: 0.28em; font-variant-numeric: tabular-nums;" />
<button type="button" onClick="{{ confirmCode }}" style="height: 50px; 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);">Продолжить</button>
</div>
<button type="button" onClick="{{ editEmail }}" style="justify-self: start; border: 0; background: transparent; color: var(--ink-3); font-family: inherit; font-size: 14px; cursor: pointer; padding: 0;">Другая почта</button>
</div>
</div>
</div>
<div style="border: 1px solid {{ step2Border }}; border-radius: 20px; background: var(--surface); box-shadow: var(--shadow); overflow: hidden;">
<div style="display: flex; align-items: center; gap: 14px; padding: 22px 24px;">
<span style="display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; background: {{ step2Dot }}; color: {{ step2DotInk }}; font-size: 13px; font-weight: 500; flex: none;">2</span>
<span style="flex: 1; font-size: 18px; font-weight: 500; letter-spacing: -0.02em;">Оплата</span>
</div>
<div hidden="{{ step2Off }}" style="padding: 0 24px 24px; display: grid; gap: 16px;">
<div style="display: flex; flex-wrap: wrap; gap: 8px;">
<button type="button" onClick="{{ payCard }}" style="flex: 1; min-width: 140px; padding: 14px 16px; border-radius: 14px; border: 1px solid {{ cardBorder }}; background: {{ cardBg }}; color: var(--ink); font-family: inherit; font-size: 15px; text-align: left; cursor: pointer;">Карта</button>
<button type="button" onClick="{{ payMir }}" style="flex: 1; min-width: 140px; padding: 14px 16px; border-radius: 14px; border: 1px solid {{ mirBorder }}; background: {{ mirBg }}; color: var(--ink); font-family: inherit; font-size: 15px; text-align: left; cursor: pointer;">Карта МИР</button>
<button type="button" onClick="{{ payCrypto }}" style="flex: 1; min-width: 140px; padding: 14px 16px; border-radius: 14px; border: 1px solid {{ cryptoBorder }}; background: {{ cryptoBg }}; color: var(--ink); font-family: inherit; font-size: 15px; text-align: left; cursor: pointer;">Криптовалюта</button>
</div>
<div hidden="{{ cryptoChosen }}" style="display: grid; gap: 10px;">
<input type="text" placeholder="Номер карты" style="height: 50px; 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%; font-variant-numeric: tabular-nums;" />
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
<input type="text" placeholder="ММ / ГГ" style="flex: 1; min-width: 120px; height: 50px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; font-variant-numeric: tabular-nums;" />
<input type="text" placeholder="CVC" style="flex: 1; min-width: 120px; height: 50px; padding: 0 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--ink); font-family: inherit; font-size: 15px; font-variant-numeric: tabular-nums;" />
</div>
<div style="font-size: 13px; color: var(--ink-3); line-height: 1.5;">Карта сохранится для продления. Отменить или заменить её можно в кабинете в любой момент.</div>
</div>
<div hidden="{{ cardChosen }}" style="display: grid; gap: 10px; padding: 18px; border-radius: 14px; background: var(--surface-2); border: 1px solid var(--border);">
<div style="font-size: 15px;">USDT, BTC или ETH</div>
<div style="font-size: 14px; line-height: 1.55; color: var(--ink-2); font-weight: 300;">После нажатия покажем адрес и сумму. При оплате криптой продление не автоматическое — пришлём напоминание за три дня до конца периода.</div>
</div>
<label style="display: flex; align-items: flex-start; gap: 10px; font-size: 14px; color: var(--ink-2); font-weight: 300; line-height: 1.5; cursor: pointer;">
<input type="checkbox" style="margin-top: 3px; width: 16px; height: 16px; accent-color: var(--accent);" />
<span>Согласен с условиями использования и политикой конфиденциальности</span>
</label>
</div>
</div>
</div>
<aside style="position: sticky; top: 24px; display: grid; gap: 16px;">
<div style="padding: clamp(20px, 4.6vw, 26px); border-radius: 20px; background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);">
<div style="font-size: 13px; color: var(--ink-3); margin-bottom: 16px;">Ваш заказ</div>
<div style="display: grid; gap: 6px; margin-bottom: 20px;">
<div style="font-size: 20px; font-weight: 600; letter-spacing: -0.025em;">Подписка ВейликсВПН</div>
<div style="font-size: 15px; color: var(--ink-2);">30 стран и российский адрес</div>
<div style="display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--accent);">
<span style="width: 6px; height: 6px; border-radius: 50%; background: var(--accent); display: block;"></span>
Доступ открывается сразу после оплаты
</div>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 18px;">
<button type="button" onClick="{{ pickMonth }}" style="flex: 1; padding: 12px 14px; border-radius: 12px; border: 1px solid {{ planMonthBorder }}; background: {{ planMonthBg }}; color: var(--ink); font-family: inherit; font-size: 14px; cursor: pointer;">Месяц · 699 ₽</button>
<button type="button" onClick="{{ pickYear }}" style="flex: 1; padding: 12px 14px; border-radius: 12px; border: 1px solid {{ planYearBorder }}; background: {{ planYearBg }}; color: var(--ink); font-family: inherit; font-size: 14px; cursor: pointer;">Год · 6 990 ₽</button>
</div>
<div style="display: grid; gap: 10px; padding-top: 18px; border-top: 1px solid var(--border); font-size: 15px;">
<div style="display: flex; justify-content: space-between; gap: 12px; color: var(--ink-2);"><span>Локации</span><span>все 30</span></div>
<div style="display: flex; justify-content: space-between; gap: 12px; color: var(--ink-2);"><span>RU-адрес</span><span>включён</span></div>
<div style="display: flex; justify-content: space-between; gap: 12px; color: var(--ink-2);"><span>Устройств</span><span>до 5</span></div>
</div>
<div style="display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--border);">
<span style="font-size: 16px; font-weight: 500;">К оплате сегодня</span>
<span style="font-size: 26px; font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums;">{{ payTotal }}</span>
</div>
<div style="margin-top: 8px; font-size: 13px; color: var(--ink-3);">{{ nextChargeLine }}</div>
<button type="button" onClick="{{ pay }}" disabled="{{ payDisabled }}" style="margin-top: 20px; width: 100%; height: 52px; border-radius: 14px; border: 0; background: {{ payBg }}; color: {{ payInk }}; font-family: inherit; font-size: 16px; font-weight: 500; cursor: {{ payCursor }};">{{ payLabel }}</button>
<div hidden="{{ paidOff }}" style="margin-top: 14px; padding: 14px; border-radius: 12px; background: var(--accent-soft); font-size: 14px; line-height: 1.5; color: var(--ink);">Оплачено. Подписка уже в кабинете — <a href="MassApp.dc.html">открыть</a>.</div>
</div>
</aside>
</main>
</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 = { plan: "year", theme: null, sysDark: false, email: "", sent: false, authed: false, method: "card", paid: false, lang: "ru" };
componentDidMount() {
const mq = window.matchMedia("(prefers-color-scheme: dark)");
this.mq = mq;
this.onSys = () => this.setState({ sysDark: mq.matches });
mq.addEventListener("change", this.onSys);
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(); });
}
applyLang() {
const lang = this.state.lang || "ru";
if (window.VEILIX_APPLY_LANG) window.VEILIX_APPLY_LANG(document.body, lang);
else setTimeout(() => this.applyLang(), 150);
}
setLang(l) {
try { localStorage.setItem("veilix.lang", l); } catch (e) {}
this.setState({ lang: l }, () => this.applyLang());
}
componentWillUnmount() { if (this.mq) this.mq.removeEventListener("change", this.onSys); }
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");
}
renderVals() {
const s = this.state;
const authed = s.authed;
const nd = new Date();
nd.setMonth(nd.getMonth() + 1);
const months = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"];
const monthsEn = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const en = s.lang === "en";
const sel = "var(--sel)";
const yearly = s.plan === "year";
const total = yearly ? "6 990 ₽" : "699 ₽";
return {
pickMonth: () => this.setState({ plan: "month" }),
pickYear: () => this.setState({ plan: "year" }),
planMonthBg: yearly ? "transparent" : sel,
planYearBg: yearly ? sel : "transparent",
planMonthBorder: yearly ? "var(--border)" : "var(--accent)",
planYearBorder: yearly ? "var(--accent)" : "var(--border)",
payTotal: total,
emailValue: s.email,
toggleLang: () => this.setLang(s.lang === "en" ? "ru" : "en"),
langLabel: s.lang === "en" ? "EN" : "RU",
langTitle: s.lang === "en" ? "Язык: английский" : "Язык: русский",
onEmail: (e) => this.setState({ email: e.target.value }),
sendCode: () => this.setState({ sent: true }),
confirmCode: () => this.setState({ authed: true }),
editEmail: () => this.setState({ sent: false, authed: false }),
codeSent: s.sent,
codeNotSent: !s.sent,
emailNotDone: !authed,
step1Off: authed,
step1Border: authed ? "var(--border)" : "var(--accent)",
step1Dot: authed ? "var(--accent)" : "var(--accent-soft)",
step1DotInk: authed ? "var(--on-accent)" : "var(--accent)",
step2Off: !authed,
step2Border: authed ? "var(--accent)" : "var(--border)",
step2Dot: authed ? "var(--accent-soft)" : "var(--surface-2)",
step2DotInk: authed ? "var(--accent)" : "var(--ink-3)",
payCard: () => this.setState({ method: "card" }),
payMir: () => this.setState({ method: "mir" }),
payCrypto: () => this.setState({ method: "crypto" }),
cardBg: s.method === "card" ? sel : "transparent",
mirBg: s.method === "mir" ? sel : "transparent",
cryptoBg: s.method === "crypto" ? sel : "transparent",
cardBorder: s.method === "card" ? "var(--accent)" : "var(--border)",
mirBorder: s.method === "mir" ? "var(--accent)" : "var(--border)",
cryptoBorder: s.method === "crypto" ? "var(--accent)" : "var(--border)",
cardChosen: s.method !== "crypto",
cryptoChosen: s.method === "crypto",
nextCharge: "первое списание " + nd.getDate() + " " + months[nd.getMonth()],
nextChargeLine: yearly
? (en ? "Renews yearly, next charge in 12 months" : "Продление раз в год, следующее списание через 12 месяцев")
: (en ? "Renews monthly, next charge on " + nd.getDate() + " " + monthsEn[nd.getMonth()] : "Продление раз в месяц, следующее списание " + nd.getDate() + " " + months[nd.getMonth()]),
codeLine: en
? "The code has been sent to " + s.email + ". It is valid for 10 minutes."
: "Код отправлен на " + s.email + ". Он действует 10 минут.",
pay: () => { if (authed) this.setState({ paid: true }); },
payDisabled: !authed,
payBg: authed ? "var(--accent)" : "var(--surface-2)",
payInk: authed ? "var(--on-accent)" : "var(--ink-3)",
payCursor: authed ? "pointer" : "not-allowed",
payLabel: s.paid ? "Оплачено" : (s.method === "crypto" ? "Показать адрес для оплаты" : "Оплатить " + total),
paidOff: !s.paid
};
}
}
</script>
</body>
</html>