Калькулятор программы наставничества
Собирает программу из четырёх параметров и сразу показывает стоимость целиком, цену месяца, количество встреч и список того, что входит в эту сумму.
<section class="vbkpn">
<div class="vbkpn-wrap">
<div class="vbkpn-head">
<h2 class="vbkpn-h2">Соберите программу под свою задачу</h2>
<p class="vbkpn-lead">Формат, срок, частота встреч и дополнения. Справа сразу видно, сколько стоит участие целиком, во сколько выходит месяц и что входит в эту сумму.</p>
</div>
<div class="vbkpn-grid">
<div class="vbkpn-panel">
<div class="vbkpn-f">
<span class="vbkpn-lbl">Формат работы</span>
<div class="vbkpn-seg" id="vbkpn-fmt"></div>
<p class="vbkpn-fmt-note" id="vbkpn-fmt-note"></p>
</div>
<div class="vbkpn-f">
<span class="vbkpn-lbl vbkpn-lbl--row">Длительность <b id="vbkpn-mon">6 месяцев</b></span>
<input type="range" id="vbkpn-range" min="3" max="12" step="1" value="6" aria-label="Длительность программы в месяцах">
<div class="vbkpn-ticks"><i>3 месяца</i><i>12 месяцев</i></div>
</div>
<div class="vbkpn-f">
<label class="vbkpn-lbl" for="vbkpn-freq">Частота встреч</label>
<select id="vbkpn-freq" class="vbkpn-sel"></select>
</div>
<div class="vbkpn-f">
<span class="vbkpn-lbl">Дополнения</span>
<label class="vbkpn-sw"><input type="checkbox" id="vbkpn-fin"><i></i><span><b>Разбор финмодели</b>Собираем модель по вашим цифрам за две недели и держим её в работе весь срок.</span></label>
<label class="vbkpn-sw"><input type="checkbox" id="vbkpn-chat" checked><i></i><span><b>Поддержка в переписке</b>Пишете между встречами, отвечаю в течение рабочего дня.</span></label>
</div>
</div>
<aside class="vbkpn-out">
<span class="vbkpn-out__lbl">Стоимость программы</span>
<b class="vbkpn-sum" id="vbkpn-sum">0 ₽</b>
<div class="vbkpn-mo"><span>В месяц</span><b id="vbkpn-permo">0 ₽</b></div>
<div class="vbkpn-mo vbkpn-mo--alt"><span>Встреч за срок</span><b id="vbkpn-meets">0</b></div>
<p class="vbkpn-disc" id="vbkpn-disc" hidden></p>
<span class="vbkpn-out__lbl vbkpn-out__lbl--2">Что входит</span>
<ul class="vbkpn-inc" id="vbkpn-inc"></ul>
<a class="vbkpn-cta" href="#diagnostika">Обсудить программу на диагностике</a>
<p class="vbkpn-note">Расчёт ориентировочный. Итоговые условия фиксируем после встречи, когда понятно, с чем именно работаем и сколько времени это займёт.</p>
</aside>
</div>
</div>
</section>
<style>
.vbkpn, .vbkpn *, .vbkpn *::before, .vbkpn *::after { box-sizing: border-box; }
.vbkpn { --acc: #8a6a2e; --acc-l: #d3b06a; --ink: #1a1d23; --muted: #616874; --line: #e4e1d9; --soft: #f6f3ec; --deep: #20242b;
--f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
--fh: var(--t-headline-font, var(--f));
background: var(--soft); color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 82px) 20px; }
.vbkpn-wrap { max-width: 1160px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 36px); }
.vbkpn-head { max-width: 46em; margin-bottom: clamp(22px, 3vw, 36px); }
.vbkpn-h2 { font-family: var(--fh); font-size: clamp(25px, 3.3vw, 40px); line-height: 1.1; font-weight: 700; letter-spacing: -.022em; margin: 0 0 12px; }
.vbkpn-lead { font-size: 16px; line-height: 1.65; color: var(--muted); margin: 0; }
.vbkpn-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; align-items: start; }
.vbkpn-panel { background: #fff; border: 1px solid var(--line); border-radius: 22px; padding: clamp(20px, 2.6vw, 30px); display: grid; gap: 24px; }
.vbkpn-lbl { display: block; font-size: 14px; font-weight: 600; color: var(--ink); margin-bottom: 10px; }
.vbkpn-lbl--row { display: flex; justify-content: space-between; align-items: baseline; }
.vbkpn-lbl--row b { font-family: var(--fh); font-size: 18px; color: var(--acc); }
.vbkpn-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; background: var(--soft); border-radius: 13px; padding: 5px; }
.vbkpn-seg button { border: 0; margin: 0; padding: 12px 4px; -webkit-appearance: none; appearance: none; font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer; border-radius: 9px; background: transparent !important; color: var(--muted) !important; transition: .18s ease; }
.vbkpn-seg button:hover { color: var(--ink) !important; }
.vbkpn-seg .vbkpn-on, .vbkpn-seg .vbkpn-on:hover { background: var(--deep) !important; color: #fff !important; }
.vbkpn-fmt-note { margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--muted); }
.vbkpn input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 4px; border-radius: 4px; background: #e6e2d7; outline: none; }
.vbkpn input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; border-radius: 50%; background: var(--acc); border: 4px solid #fff; box-shadow: 0 1px 6px rgba(0,0,0,.2); cursor: pointer; }
.vbkpn input[type=range]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--acc); border: 3px solid #fff; cursor: pointer; }
.vbkpn-ticks { display: flex; justify-content: space-between; margin-top: 7px; font-size: 11.5px; color: #9a9382; }
.vbkpn-ticks i { font-style: normal; }
.vbkpn-sel { width: 100%; height: 54px; padding: 0 38px 0 15px; font: inherit; font-size: 16px; -webkit-appearance: none; appearance: none; border: 1.5px solid var(--line); border-radius: 12px; background: #fff; color: var(--ink); background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: calc(100% - 19px) 24px, calc(100% - 13px) 24px; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }
.vbkpn-sel:focus { outline: 2px solid var(--acc); outline-offset: -2px; }
.vbkpn-sw { display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 13px; align-items: start; cursor: pointer; padding: 13px 0; border-top: 1px solid var(--line); }
.vbkpn-sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.vbkpn-sw i { width: 46px; height: 26px; border-radius: 999px; background: #ddd8cb; position: relative; transition: background .2s ease; }
.vbkpn-sw i::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; transition: transform .2s ease; }
.vbkpn-sw input:checked + i { background: var(--acc); }
.vbkpn-sw input:checked + i::after { transform: translateX(20px); }
.vbkpn-sw span { font-size: 13px; line-height: 1.55; color: var(--muted); }
.vbkpn-sw b { display: block; font-size: 14.5px; color: var(--ink); margin-bottom: 3px; }
.vbkpn-out { background: var(--deep); color: #eef0f3; border-radius: 22px; padding: clamp(22px, 2.8vw, 32px); }
.vbkpn-out__lbl { display: block; font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: #8d95a2; margin-bottom: 8px; }
.vbkpn-out__lbl--2 { margin-top: 24px; }
.vbkpn-sum { display: block; font-family: var(--fh); font-size: clamp(32px, 4vw, 44px); line-height: 1; font-weight: 700; color: var(--acc-l); letter-spacing: -.02em; margin-bottom: 18px; }
.vbkpn-mo { display: flex; justify-content: space-between; align-items: baseline; background: #2a2f38; border-radius: 12px; padding: 13px 16px; margin-bottom: 8px; }
.vbkpn-mo span { font-size: 13px; color: #a9b0bb; }
.vbkpn-mo b { font-family: var(--fh); font-size: 18px; font-weight: 700; }
.vbkpn-mo--alt { background: transparent; border: 1px solid #333a44; }
.vbkpn-disc { margin: 10px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--acc-l); }
.vbkpn-inc { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.vbkpn-inc li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 11px; font-size: 13.5px; line-height: 1.5; color: #c3c9d2; }
.vbkpn-inc li::before { content: ''; width: 8px; height: 8px; margin-top: 6px; margin-left: 5px; border-radius: 50%; background: var(--acc-l); }
.vbkpn-cta, .vbkpn-cta:link, .vbkpn-cta:visited, .vbkpn-cta:active, .vbkpn-cta:focus { display: flex; align-items: center; justify-content: center; min-height: 56px; margin-top: 24px; padding: 0 22px; border-radius: 12px; font-size: 16px; font-weight: 600; text-align: center; background: var(--acc-l); color: #20242b !important; text-decoration: none !important; transition: background .2s ease; }
.vbkpn-cta:hover { background: #e0c184; color: #20242b !important; }
.vbkpn-note { margin: 14px 0 0; font-size: 11.5px; line-height: 1.55; color: #7d8593; }
@media (min-width: 1000px) { .vbkpn-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); } }
@media (prefers-reduced-motion: reduce) { .vbkpn * { transition: none !important; } }
</style>
<script>
(function () {
var RATES = {
fmt: {
solo: { n: 'Лично', base: 62000, note: 'Работаем вдвоём. Разбираем вашу компанию, решения и цифры, между встречами держим план на квартал.', meet: 'Личная встреча по видеосвязи, 90 минут' },
group: { n: 'Группа', base: 27000, note: 'Поток на шесть собственников. Каждую встречу разбираем одного участника при остальных.', meet: 'Групповая встреча, два часа' },
club: { n: 'Клуб', base: 11000, note: 'Годовое участие с регулярными встречами, мастермайндами и общим чатом.', meet: 'Встреча клуба и мастермайнд' }
},
freq: { w1: { n: 'Раз в неделю', k: 1.4, m: 4 }, w2: { n: 'Раз в две недели', k: 1, m: 2 }, m1: { n: 'Раз в месяц', k: 0.65, m: 1 } },
fin: 24000,
chat: 5500,
long: { 6: 0.95, 9: 0.92, 12: 0.88 }
};
var roots = document.querySelectorAll('.vbkpn');
for (var i = 0; i < roots.length; i++) init(roots[i]);
function init(root) {
if (root.__vb) return; root.__vb = 1;
var q = function (s) { return root.querySelector(s); };
var st = { fmt: 'solo', mon: 6, freq: 'w2' };
function money(n) { return String(Math.round(n / 100) * 100).replace(/\B(?=(\d{3})+(?!\d))/g, ' ') + ' ₽'; }
function word(n) {
var a = n % 10, b = n % 100;
if (a === 1 && b !== 11) return 'месяц';
if (a > 1 && a < 5 && (b < 10 || b > 20)) return 'месяца';
return 'месяцев';
}
var seg = q('#vbkpn-fmt'), html = '';
for (var k in RATES.fmt) html += '<button type="button" data-k="' + k + '">' + RATES.fmt[k].n + '<\/button>';
seg.innerHTML = html;
var opts = '';
for (var f in RATES.freq) opts += '<option value="' + f + '"' + (f === st.freq ? ' selected' : '') + '>' + RATES.freq[f].n + '<\/option>';
q('#vbkpn-freq').innerHTML = opts;
var segBtns = seg.querySelectorAll('button');
for (var b = 0; b < segBtns.length; b++) {
segBtns[b].addEventListener('click', function () {
st.fmt = this.getAttribute('data-k');
for (var m = 0; m < segBtns.length; m++) segBtns[m].className = segBtns[m] === this ? 'vbkpn-on' : '';
render();
});
}
q('#vbkpn-range').addEventListener('input', function () { st.mon = +this.value; render(); });
q('#vbkpn-freq').addEventListener('change', function () { st.freq = this.value; render(); });
q('#vbkpn-fin').addEventListener('change', render);
q('#vbkpn-chat').addEventListener('change', render);
function render() {
var F = RATES.fmt[st.fmt], R = RATES.freq[st.freq];
var fin = q('#vbkpn-fin').checked, chat = q('#vbkpn-chat').checked;
var perMo = F.base * R.k + (chat ? RATES.chat : 0);
var kf = 1;
for (var d in RATES.long) { if (st.mon >= +d) kf = RATES.long[d]; }
var total = perMo * st.mon * kf + (fin ? RATES.fin : 0);
var meets = Math.round(R.m * st.mon);
for (var s = 0; s < segBtns.length; s++) segBtns[s].className = segBtns[s].getAttribute('data-k') === st.fmt ? 'vbkpn-on' : '';
q('#vbkpn-fmt-note').textContent = F.note;
q('#vbkpn-mon').textContent = st.mon + ' ' + word(st.mon);
q('#vbkpn-sum').textContent = money(total);
q('#vbkpn-permo').textContent = money(total / st.mon);
q('#vbkpn-meets').textContent = meets;
var disc = q('#vbkpn-disc');
disc.hidden = kf === 1;
if (kf !== 1) disc.textContent = 'За срок от ' + (kf === RATES.long[12] ? 12 : (kf === RATES.long[9] ? 9 : 6)) + ' месяцев цена месяца ниже на ' + Math.round((1 - kf) * 100) + '%.';
var list = [
meets + ' встреч за программу: ' + F.meet,
'План на квартал и разбор задач на каждой встрече',
'Записи встреч и рабочие материалы остаются у вас'
];
if (st.fmt === 'club') list.push('Доступ к базе разборов и офлайн-встречам клуба');
if (fin) list.push('Финмодель по вашим цифрам с обновлением раз в месяц');
if (chat) list.push('Переписка между встречами с ответом в рабочий день');
list.push('Отчёт по итогам программы с планом на следующий период');
q('#vbkpn-inc').innerHTML = list.map(function (t) { return '<li>' + t + '<\/li>'; }).join('');
}
render();
}
})();
</script> Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.
Как вставить блок в Tilda
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
RATES.fmt в начале скрипта | названия форматов, базовая цена месяца и пояснения к ним |
RATES.freq | варианты частоты встреч, множитель цены и число встреч в месяц |
RATES.fin и RATES.chat | цена разбора финмодели и месячная цена поддержки в переписке |
RATES.long | насколько дешевле выходит месяц при сроке от 6, 9 и 12 месяцев |
массив list в функции render | пункты списка «что входит» и условия их появления |
атрибуты min и max у ползунка | границы срока программы в месяцах |
Калькулятор программы наставничества: зачем он нужен
Слева стоит панель с параметрами: формат работы переключается сегментами, длительность задаётся ползунком от трёх до двенадцати месяцев, частота встреч выбирается списком, два дополнения включаются переключателями. Это разбор финмодели, который считается разово, и поддержка в переписке с помесячной оплатой. Под сегментами меняется короткое пояснение к выбранному формату.
Справа лежит тёмная карточка с итогом. В ней стоимость программы, цена месяца, число встреч за срок и строка про скидку, которая появляется при длительности от полугода. Ниже собирается список того, что входит: он меняется вместе с параметрами, потому что дополнения и клубные пункты добавляются в него по условию. Все ставки и коэффициенты лежат в объекте RATES в начале скрипта: базовая цена месяца по форматам, множители частоты, цена дополнений и понижающие коэффициенты за срок.
Вопросы по этому блоку
-
Впишите новый ключ в RATES.fmt с полями n, base, note и meet. Кнопка в сегментах появится сама, поменяйте только grid-template-columns у vbkpn-seg с трёх колонок на четыре.
-
Да. Уберите из разметки vbkpn-sum и два блока vbkpn-mo, остальной расчёт продолжит работать. Список того, что входит, собирается независимо от сумм.
-
Функция money округляет сумму до сотен рублей, чтобы в карточке не появлялись цифры вроде 384 750. Замените множитель 100 на 1, если нужен точный результат.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbkpn, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие калькуляторы
Ещё блоки для коучинга и бизнес-клубов
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.