<!--КАЛЬКУЛЯТОР СТОИМОСТИ ТЕННИСИТА-->
<div id="tc-app" class="tc-app t-text">
	<label class="tc-label">Вид необходимых работ</label>
	<div class="tc-segmented">
		<button class="tc-seg-btn active" data-mode="repair" type="button">Ремонт</button>
		<button class="tc-seg-btn" data-mode="construction" type="button">Строительство</button>
	</div>
	<form class="tc-form" id="tc-form">
		<div class="tc-field">
			<label class="tc-label">Материал</label>
			<div class="tc-products" id="tc-products"></div>
		</div>
		<div class="tc-field">
			<label class="tc-label">Площадь корта</label>
			<div class="tc-input-row">
				<div class="tc-input-row-section">
					<input type="number" id="tc-area" class="tc-input" value="648" min="1"> <span class="tc-suffix">м²</span> </div>
				<button type="button" class="tc-chip" id="tc-preset">Стандарт: 18×36 м = 648 м²</button>
			</div>
		</div>
		<div class="tc-field tc-conditional" id="tc-thickness-field" hidden>
			<label class="tc-label">Толщина слоя после укатки</label>
			<div class="tc-slider-wrap">
				<input type="range" id="tc-thickness" class="tc-slider" min="30" max="70" value="45" step="5">
				<div class="tc-slider-fill"></div>
				<output class="tc-slider-val" for="tc-thickness">45 мм</output>
			</div>
			<p class="tc-hint" id="tc-thickness-hint">Неуплотнённый: <strong>70 мм</strong> → укатка: <strong>50 мм</strong></p>
			<p class="tc-hint"> (45 мм  - стандартный слой укладки)</p>
		</div>
		<div class="tc-field">
			<label class="tc-label">Фасовка <span class="tc-tooltip-wrapper">
<span class="tc-tooltip-icon">?</span>
				<div class="tc-tooltip-content"> <strong>Мешок 40 кг (ЛМТ СТРОЙ)</strong>
					<br> • Меньше мешков — быстрее укладка
					<br> • Оптимальный вес для профессиональной бригады
					<br> • Компактное хранение
					<br> • На одном поддоне помещается больше тоннажа
					<br> • Классическая фасовка 40 кг гарантирует сохранность фракции и проверена десятилетиями практики.
					<br> • Оптимальная нагрузка для равномерного рассева и комфортной работы бригады. </div>
				</span>
			</label>
			<div class="tc-toggle">
				<button type="button" class="tc-toggle-btn" data-packaging="bags">Мешки 40 кг</button>
				<button type="button" class="tc-toggle-btn active" data-packaging="bulk">Тонны</button>
			</div>
		</div>
		<div class="tc-field">
			<label class="tc-switch">
				<input type="checkbox" id="tc-superior" class="tc-switch-input"> <span class="tc-switch-track"><span class="tc-switch-thumb"></span></span> <span class="tc-switch-text">
Добавить финишный слой <strong>Extra</strong>
<small>Для профессионального покрытия</small>
</span> </label>
		</div>
	</form>
	<section class="tc-results" id="tc-results">
		<div class="tc-results-head">
			<h3 class="tc-results-title" id="tc-results-title">Результаты</h3>
			<button class="tc-reset" id="tc-reset" type="button">↺ Сброс</button>
		</div>
		<div class="tc-cards" id="tc-main-cards"></div>
		<div class="tc-superior-block" id="tc-superior-block" hidden> <span class="tc-superior-badge">Финишный слой</span>
			<div class="tc-cards" id="tc-superior-cards"></div>
		</div>
		<div class="tc-total" id="tc-total">
			<div> <span class="tc-total-label">Итого</span> <span class="tc-total-note">включая все материалы</span> </div> <span class="tc-total-amount" id="tc-total-amount">0 ₽</span> </div> <a href="#popup:calc-form" class="tc-cta" id="tc-cta">Оформить заказ</a>

		<div class="tc-opt-message" id="tc-opt-message" hidden>
			<p><strong>Специальные условия при покупке от 50 тонн!</strong></p>
			<p>Купив такой объем Вы можете стать нашим дилером и получить дополнительную скидку.</p>
		</div>
	</section>
	<div class="tc-empty" id="tc-empty" hidden>
		<p>Выберите материал и укажите площадь</p>
	</div>
</div>



<style>
.tc-app {
	--tc-yellow: #f9a825;
	--tc-yellow-hover: #e6991b;
	--tc-green: #333333;
	--tc-bg: #F5F5F7;
	--tc-card: #FFFFFF;
	--tc-text: #000000;
	--tc-text-secondary: #000;
	--tc-border: #E0E0E0;
	--tc-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
	--tc-shadow-hover: 0 8px 32px rgba(0, 0, 0, 0.12);
	--tc-radius: 16px;
	--tc-radius-sm: 12px;
	background: var(--tc-bg);
	border-radius: var(--tc-radius);
	padding: 24px;
	margin: 0 auto;
	color: var(--tc-text);
	box-sizing: border-box;
	background-color: #ecf1f7;
	box-shadow: 0 0 10px 0 rgb(0 0 0 / 25%);
}
.tc-app *, .tc-app *::before, .tc-app *::after {
	box-sizing: inherit;
	margin: 0;
	padding: 0;
}
.tc-segmented {
	display: flex;
	background: #fff;
	padding: 2px;
	border-radius: var(--tc-radius-sm);
	margin-bottom: 24px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
	position: relative;
	width: 50%;
}
.tc-segmented:before {
	content: "";
	width: 50%;
	height: 100%;
	position: absolute;
	left: 0;
	top: 0;
	background-color: var(--tc-yellow);
	border-radius: inherit;
	transition: all 0.4s ease-in-out;
}

/*ЦВЕТ ПЛАШЕК ДЛЯ МАТЕРИАЛОВ*/
button.tc-product:nth-child(1) .tc-product-tag {
    background-color: #22C55E; /*CLASSIC*/
}
button.tc-product:nth-child(2) .tc-product-tag {
    background-color: #ff8562; /*EXPERT*/
}
button.tc-product:nth-child(3) .tc-product-tag {
    background-color: #8770F9; /*PREMIUM*/
}
button.tc-product:nth-child(4) .tc-product-tag {
    background-color: #FF20FB; /*EXTRA*/
}




.tc-segmented:has(button.tc-seg-btn.active[data-mode="construction"]):before {
	left: 50%;
}

.tc-toggle {
	display: flex;
	gap: 0;
	background-color: #fff;
	border-radius: 12px;
	padding: 2px;
	width: 30%;
	position: relative;
}

.tc-toggle:before {
	content: "";
	width: 50%;
	height: 100%;
	position: absolute;
	left: 0;
	top: 0;
	background-color: var(--tc-yellow);
	border-radius: inherit;
	transition: all 0.4s ease-in-out;
}

.tc-toggle:has(button.tc-toggle-btn.active[data-packaging="bulk"]):before {
	left: 50%;
}

.tc-seg-btn, .tc-toggle-btn {
	position: relative;
	flex: 1;
	padding: 10px 12px;
	border: none;
	background: transparent;
	font-size: 13px;
	font-weight: 500;
	color: var(--tc-text-secondary);
	border-radius: var(--tc-radius-sm);
	cursor: pointer;
	transition: all 0.2s ease;
	z-index: 2;
}

.tc-seg-btn.active, .tc-toggle-btn.active {
	color: #000;
	font-weight: 600;
}

.tc-toggle-btn.disabled {
	opacity: 0.4;
	pointer-events: none;
	cursor: not-allowed;
}

.tc-form {
	margin-bottom: 24px;
}

.tc-field {
	margin-bottom: 20px;
}

.tc-label {
	display: block;
	font-size: 14px;
	font-weight: 400;
	color: #000;
	margin-bottom: 8px;
}

.tc-input-row {
	display: flex;
	align-items: center;
	gap: 20px;
}

.tc-input {
	flex: 1;
	padding: 14px 16px;
	border: 1px solid var(--tc-border);
	border-radius: var(--tc-radius-sm);
	font-size: 16px;
	font-weight: 500;
	background: #fff;
	transition: border-color 0.2s;
}

.tc-input:focus {
	outline: none;
	border-color: var(--tc-yellow);
}

.tc-suffix {
	color: var(--tc-text-secondary);
	font-weight: 500;
	margin-left: -30px;
}

.tc-chip {
	color: #000;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: all 0.2s;
	background: no-repeat;
	border: 1px solid #b2b2b2;
	border-radius: 12px;
	padding: 15px 10px;
}

.tc-hint {
	font-size: 12px;
	color: var(--tc-text-secondary);
	margin-top: 6px;
	font-weight: 400;
    display: inline-block;
}

.tc-hint strong {
	color: var(--tc-text);
}

.tc-slider-wrap {
	position: relative;
	margin: 8px 0 6px;
	height: 24px;
	display: flex;
	align-items: center;
}

.tc-slider {
	width: 100%;
	height: 6px;
	border-radius: 3px;
	background: var(--tc-border);
	appearance: none;
	cursor: pointer;
	position: relative;
	z-index: 3;
}

.tc-slider::-webkit-slider-thumb {
	appearance: none;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background: var(--tc-yellow);
	border: 3px solid #fff;
	box-shadow: var(--tc-shadow);
	cursor: pointer;
	z-index: 4;
}

.tc-slider-fill {
	position: absolute;
	top: 50%;
	left: 0;
	height: 6px;
	background: var(--tc-yellow);
	border-radius: 3px;
	transform: translateY(-50%);
	z-index: 5;
	pointer-events: none;
}

.tc-slider-val {
	position: absolute;
	right: 0;
	top: -26px;
	font-size: 14px;
	font-weight: 700;
	color: var(--tc-green);
	background: #fff;
	padding: 4px 10px;
	border-radius: 8px;
	box-shadow: var(--tc-shadow);
}

.tc-products {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: 12px;
}

.tc-product {
	padding: 14px;
	border: 1px solid var(--tc-border);
	border-radius: var(--tc-radius-sm);
	background: #fff;
	cursor: pointer;
	transition: all 0.2s;
	text-align: left;
	position: relative;
}

.tc-product:hover {
	border-color: var(--tc-yellow);
	transform: scale(1.03);
	box-shadow: var(--tc-shadow);
}

.tc-product.selected {
	border-color: var(--tc-yellow);
	background: linear-gradient(135deg, #FFF9E6 0%, #fff 100%);
	box-shadow: 0 0 0 1px var(--tc-yellow), var(--tc-shadow);
}

.tc-product-tag {
	display: inline-block;
	padding: 3px 8px;
	border-radius: 4px;
	font-size: 10px;
	font-weight: 700;
	text-transform: uppercase;
	margin-bottom: 8px;
	background: #ff8562;
	color: #fff;
	position: absolute;
	right: 0;
	top: 0;
	border-radius: 0 12px 0 4px;
}

button.tc-product {
	display: flex;
	flex-direction: column;
}

.tc-product-name {
	font-size: 14px;
	font-weight: 700;
	margin-bottom: 6px;
	line-height: 1.3;
	color: #000;
}

.tc-product-desc {
	font-size: 11px;
	color: var(--tc-text-secondary);
	margin-bottom: 10px;
	line-height: 1.4;
}

.tc-product-price {
	font-size: 13px;
	font-weight: 600;
	color: var(--tc-green);
	margin-top: auto;
}

.tc-product-opt {
	font-size: 10px;
	color: #22C55E;
	font-weight: 700;
	margin-left: 4px;
	background: #ECFDF5;
	padding: 2px 6px;
	border-radius: 4px;
}

.tc-switch {
	display: flex;
	align-items: center;
	gap: 20px;
	cursor: pointer;
	flex-direction: row-reverse;
	width: max-content;
}

.tc-switch-input {
	display: none;
}

.tc-switch-track {
	width: 36px;
	height: 50px;
	background: var(--tc-border);
	border-radius: 3px;
	position: relative;
	transition: background 0.2s;
	flex-shrink: 0;
	transform: rotate(-90deg);
}

.tc-switch-thumb {
	position: absolute;
	top: 0px;
	left: 0px;
	width: 17px;
	height: 50px;
	background: #fff;
	border-radius: 2px;
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
	transition: transform 0.2s;
}

.tc-switch-input:checked + .tc-switch-track {
	background: var(--tc-yellow);
}

.tc-switch-input:checked + .tc-switch-track .tc-switch-thumb {
	transform: translateX(20px);
}

.tc-switch-text {
	font-size: 14px;
	color: var(--tc-text);
}

.tc-switch-text strong {
	color: var(--tc-green);
}

.tc-switch-text small {
	display: block;
	font-size: 12px;
	color: var(--tc-text-secondary);
}

.tc-results {
	background: var(--tc-card);
	border-radius: var(--tc-radius);
	padding: 20px;
	box-shadow: var(--tc-shadow);
	margin-bottom: 24px;
	animation: tc-fadeIn 0.25s ease;
	display: flex;
	flex-wrap: wrap;
	gap: 0px;
}

.tc-results>div {
	width: 100%;
}

.modal-summary {
	background-color: #f3f3f3;
	padding: 5px 5px;
	margin-top: 12px;
	border-radius: 5px;
	display: flex;
	flex-direction: column;
	gap: 5px;
}

.modal-summary>p {
	display: flex;
	justify-content: space-between;
	background-color: #ffffff;
	padding: 3px 6px;
}

@keyframes tc-fadeIn {
	from {
		opacity: 0;
		transform: translateY(8px);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.tc-results-head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 16px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--tc-border);
}

.tc-results-title {
	font-size: 16px;
	font-weight: 700;
}

.tc-reset {
	padding: 6px 12px;
	background: var(--tc-bg);
	border: none;
	border-radius: 8px;
	font-size: 12px;
	font-weight: 500;
	color: var(--tc-text-secondary);
	cursor: pointer;
}

.tc-reset:hover {
	background: var(--tc-border);
}

.tc-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
	gap: 12px;
	margin-bottom: 16px;
}

.tc-card {
	padding: 14px;
	border-radius: var(--tc-radius-sm);
	background: var(--tc-bg);
	border: 1px solid var(--tc-border);
	text-align: center;
	position: relative;
}

.tc-card.primary {
	background: linear-gradient(135deg, #FFF9E6 0%, #fff 100%);
	border-color: var(--tc-yellow);
}

.tc-card.sup {
	background: linear-gradient(135deg, rgb(255 133 98 / 38%) 0%, #fff 100%);
	border-color: #ff8562;
}

.tc-card.accent {
	background: linear-gradient(135deg, #ECFDF5 0%, #fff 100%);
	border-color: #22C55E;
}

.tc-card-value {
	font-size: 20px;
	font-weight: 800;
	color: var(--tc-text);
	margin-bottom: 4px;
}

.tc-card.primary .tc-card-value, .tc-card.accent .tc-card-value {
	color: var(--tc-green);
}

.tc-card-label {
	font-size: 11px;
	color: var(--tc-text-secondary);
	line-height: 1.4;
}

.tc-opt-badge {
	position: absolute;
	top: 8px;
	right: 8px;
	padding: 3px 8px;
	background: #22C55E;
	color: #fff;
	font-size: 9px;
	font-weight: 700;
	border-radius: 4px;
}

.tc-superior-block {
	margin: 16px 0;
	padding-top: 16px;
	border-top: 2px dashed var(--tc-border);
}

.tc-superior-badge {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 4px 10px;
	background: linear-gradient(135deg, #ff8562, #f9a825);
	color: #fff;
	font-size: 11px;
	font-weight: 700;
	border-radius: 6px;
	margin-bottom: 12px;
}

.tc-total {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 16px 20px;
	background: var(--tc-green);
	border-radius: var(--tc-radius-sm);
	margin-bottom: 16px;
	color: #fff;
	height: 70px;
	flex-grow: 1;
	flex-basis: 50%;
}

.tc-total-label {
	font-size: 14px;
	font-weight: 500;
	opacity: 1;
}

.tc-total-note {
	font-size: 12px;
	opacity: 1;
	display: block;
}

.tc-total-amount {
	font-size: 28px;
	font-weight: 800;
}

.tc-cta {
	width: 300px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 10px;
	background: var(--tc-yellow);
	color: #000 !important;
	border: none;
	border-radius: var(--tc-radius-sm);
	font-size: 16px;
	font-weight: 700;
	cursor: pointer;
	transition: all 0.2s;
	text-decoration: none;
	text-align: center;
	height: 70px;
	margin-left: 10px;
}

.tc-cta:hover {
	background: var(--tc-yellow-hover);
	box-shadow: var(--tc-shadow-hover);
	transform: scale(1.03);
}

.tc-empty {
	text-align: center;
	padding: 40px 20px;
	color: var(--tc-text-secondary);
}

[hidden] {
	display: none !important;
}

.tc-conditional {
	animation: tc-slideDown 0.25s ease;
}

.uc-products-table, .uc-superior-table, .uc-constants-table {
	display: none;
}

@keyframes tc-slideDown {
	from {
		opacity: 0;
		transform: translateY(-8px);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}
/* Тултип для фасовки */
.tc-tooltip-wrapper {
	position: relative;
	display: none;
	align-items: center;
	margin-left: 2px;
	vertical-align: middle;
	cursor: help;
}

.tc-field:has(button.tc-toggle-btn[data-packaging="bags"].active) .tc-tooltip-wrapper {
	display: inline-flex;
}

.tc-tooltip-icon {
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--tc-border);
	color: var(--tc-text-secondary);
	font-size: 11px;
	font-weight: 700;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: all 0.2s;
}

.tc-tooltip-wrapper:hover .tc-tooltip-icon {
	background: var(--tc-yellow);
	color: #000;
}

.tc-tooltip-content {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%) translateY(6px);
	width: 300px;
	padding: 12px;
	background: #fff;
	border: 1px solid var(--tc-border);
	border-radius: 10px;
	box-shadow: 0 6px 20px rgba(0,0,0,0.12);
	font-size: 12px;
	line-height: 1.5;
	color: var(--tc-text);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: all 0.2s ease;
	z-index: 100;
	text-align: left;
	white-space: normal;
}

.tc-tooltip-content::after {
	content: '';
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translateX(-50%);
	border-width: 6px;
	border-style: solid;
	border-color: #fff transparent transparent transparent;
}

.tc-tooltip-wrapper:hover .tc-tooltip-content {
	opacity: 1;
	visibility: visible;
	transform: translateX(-50%) translateY(0);
}

@media (max-width: 480px) {
	.tc-tooltip-content {
		width: 220px;
		left: 0;
		transform: translateX(-20%) translateY(6px);
	}

	.tc-tooltip-wrapper:hover .tc-tooltip-content {
		transform: translateX(-20%) translateY(0);
	}

	.tc-tooltip-content::after {
		left: 20%;
		transform: translateX(0);
	}
}

@media (max-width: 480px) {
	.tc-app {
		padding: 16px;
	}

	.tc-total {
		flex-direction: column;
		gap: 8px;
		text-align: center;
	}

	.tc-products, .tc-cards {
		grid-template-columns: 1fr;
	}
}

@media screen and (max-width:650px) {
	.tc-input-row {
		flex-direction: column;
		align-items: flex-start;
		gap: 10px;
		margin-bottom: 10px;
	}
}

@media screen and (max-width:960px) {
	.tc-toggle {
		width: 40%;
	}
}

@media screen and (max-width:680px) {
	.tc-toggle, .tc-segmented, .tc-cta {
		width: 100%;
	}

	label.tc-switch {
		width: 100%;
		justify-content: left;
	}

	div#tc-total {
		height: auto;
	}

	a#tc-cta {
		margin-left: 0;
	}

	.tc-card-value {
		font-size: 15px;
	}

	.tc-total-amount {
		font-size: 20px;
	}

	.tc-cta {
		font-size: 14px;
	}

	h3#tc-results-title {
		font-size: 12px;
	}

	.modal-summary.t-text {
		font-size: 12px;
	}
}
/* Стили для сообщения ОПТ */
.tc-opt-message {
	background: linear-gradient(135deg, #ECFDF5 0%, #fff 100%);
	border: 1px solid #22C55E;
	color: #166534;
	padding: 12px 16px;
	border-radius: var(--tc-radius-sm);
	font-size: 13px;
	font-weight: 500;
	margin-top: 16px;
	text-align: center;
	line-height: 1.4;
	width: 100%;
	box-sizing: border-box;
}

.tc-opt-message p {
	margin: 0;
}

.tc-opt-message p:first-child {
	margin-bottom: 4px;
}
</style>


<script>
(() => {
	'use strict';
	const fmt = n => Number(n).toLocaleString('ru-RU');
	const ceil = n => Math.ceil(n);
	const OPT_DISPLAY_THRESHOLD = 50;
	const DEFAULT_CONFIG = {
		products: [
			{
				id: 'classic',
				name: 'CLASSIC',
				tag: null,
				bagPrice: null,
				prices: [6000, 5800, 5500],
				desc: 'Для массового бюджетного строительства (фракция 0.25–3.5 мм)'
			},
			{
				id: 'optima',
				name: 'EXPERT',
				tag: 'НОВИНКА!',
				tagClass: 'new',
				bagPrice: null,
				prices: [8500, 8000, 7700],
				desc: 'Идеален для ремонта и подготовки к сезону. Улучшенная формула. Легко укатывается (фракция 0.25–3.0 мм)'
			},
			{
				id: 'comfort',
				name: 'PREMIUM',
				tag: null,
				bagPrice: 500,
				prices: [11000, 10500, 10000],
				desc: 'С повышенным содержанием карьерной глины для профессиональных теннисных кортов (фракция 0.25–3.5 мм)'
			},
			{
				id: 'premium',
				name: 'EXTRA',
				tag: null,
				bagPrice: 800,
				prices: [15000, 15000, 15000],
				desc: 'Элитный финишный слой для идеального отскока. фракция (0.25–1.0 мм)'
			}
		],
		superior: {
			name: 'Extra',
			bagPrice: 525,
			prices: [15000, 14400, 14400]
		},
		constants: {
			STANDARD_AREA: 648,
			BAG_KG: 40,
			COMPACTION: 1.4,
			WASTE: 1.205
		}
	};
	function parseTildaTable(selector) {
		const container = document.querySelector(selector);
		if (!container) {
			return null;
		}
		const headerEl = container.querySelector('.t431__data-part1');
		const dataEl = container.querySelector('.t431__data-part2');
		if (!headerEl || !dataEl) {
			return null;
		}
		const headerText = headerEl.textContent.trim();
		const rowsText = dataEl.textContent.trim();
		if (!headerText || !rowsText) {
			return null;
		}
		const headers = headerText.split(';').map(header => header.trim());
		const rows = rowsText.split(/\r?\n/).map(row => row.trim()).filter(Boolean);
		return rows.map(row => {
			const values = row.split(';').map(value => value.trim());
			const result = {};
			headers.forEach((header, index) => {
				let value = values[index];
				if (value === undefined || value === '' || value === 'null') {
					value = null;
				} else if (!Number.isNaN(Number(value))) {
					value = Number(value);
				}
				result[header] = value;
			});
			return result;
		});
	}
	function buildConfig() {
		const p = parseTildaTable('.uc-products-table');
		const s = parseTildaTable('.uc-superior-table')?.[0];
		const c = parseTildaTable('.uc-constants-table')?.[0];
		const products = p && p.length ? p.map(prod => ({
			id: String(prod.name || '').toLowerCase().replace(/\s+/g, '-').replace(/[^a-zа-яё0-9-]/gi, ''),
			name: prod.name,
			tag: prod.tag || null,
			tagClass: prod.tag ? 'new' : null,
			bagPrice: prod.bagPrice,
			prices: [
				prod['prices(1-20)'] || 0,
				prod['prices(20-100)'] || 0,
				prod['prices(100)'] || 0
			],
			desc: prod.desc || ''
		})) : DEFAULT_CONFIG.products;
		const superior = s ? {
			name: s.name || 'Extra',
			bagPrice: s.bagPrice,
			prices: [
				s['prices(1-20)'] || 0,
				s['prices(20-100)'] || 0,
				s['prices(100)'] || 0
			]
		} : DEFAULT_CONFIG.superior;
		const constants = c ? {
			STANDARD_AREA: Number(c.STANDARD_AREA) || 648,
			BAG_KG: Number(c.BAG_KG) || 40,
			COMPACTION: Number(c.COMPACTION) || 1.4,
			WASTE: Number(c.WASTE) || 1.2
		} : DEFAULT_CONFIG.constants;
		return {
			products,
			superior,
			constants
		};
	}
	function waitForPriceData(timeout = 10000) {
		return new Promise(resolve => {
			const start = Date.now();
			const check = () => {
				const app = document.querySelector('#tc-app');
				const products = document.querySelector('.uc-products-table .t431__data-part2');
				const superior = document.querySelector('.uc-superior-table .t431__data-part2');
				const constants = document.querySelector('.uc-constants-table .t431__data-part2');
				const isReady = app && products?.textContent.trim() && superior?.textContent.trim() && constants?.textContent.trim();
				if (isReady) {
					resolve(true);
					return;
				}
				if (Date.now() - start >= timeout) {
					resolve(false);
					return;
				}
				setTimeout(check, 50);
			};
			check();
		});
	}
	let CONFIG = DEFAULT_CONFIG;
	const state = {
		mode: 'repair',
		area: DEFAULT_CONFIG.constants.STANDARD_AREA,
		thickness: 45,
		productId: DEFAULT_CONFIG.products[0]?.id || 'classic',
		packaging: 'bulk',
		superior: false
	};
	const calcTons = () => {
		const { mode, area, thickness } = state;
		const { STANDARD_AREA, COMPACTION, WASTE } = CONFIG.constants;
		if (mode === 'repair') {
			return ceil(area / STANDARD_AREA);
		}
		return ceil(area * (thickness * COMPACTION / 1000) * WASTE);
	};
	const calcSuperiorTons = () => ceil(state.area / CONFIG.constants.STANDARD_AREA * 2);
	const calcBags = tons => ceil(tons / (CONFIG.constants.BAG_KG / 1000));
	const getTierInfo = tons => {
		if (tons <= 20) {
			return { idx: 0, label: '1–20 т' };
		}
		if (tons <= 100) {
			return { idx: 1, label: '20–100 т' };
		}
		return { idx: 2, label: 'Свыше 100 т' };
	};
	const calcResult = p => {
		const tons = calcTons();
		const bags = calcBags(tons);
		const tier = getTierInfo(tons);
		const pricePerTon = p.prices[tier.idx];
		const isBags = state.packaging === 'bags' && p.bagPrice !== null;
		const totalCost = isBags ? Math.round(bags * p.bagPrice) : Math.round(tons * pricePerTon);
		return {
			tons,
			bags,
			pricePerTon,
			tierLabel: tier.label,
			isBags,
			totalCost,
			supportsBags: p.bagPrice !== null
		};
	};
	const calcSuperiorResult = () => {
		const tons = calcSuperiorTons();
		const bags = calcBags(tons);
		const tier = getTierInfo(tons);
		const p = CONFIG.superior;
		const pricePerTon = p.prices[tier.idx];
		const isBags = state.packaging === 'bags' && p.bagPrice !== null;
		const totalCost = isBags ? Math.round(bags * p.bagPrice) : Math.round(tons * pricePerTon);
		return {
			tons,
			bags,
			pricePerTon,
			tierLabel: tier.label,
			isBags,
			totalCost,
			supportsBags: p.bagPrice !== null
		};
	};
	const updateToggleUI = () => {
		const product = CONFIG.products.find(p => p.id === state.productId);
		const bagsBtn = document.querySelector('[data-packaging="bags"]');
		if (!bagsBtn) return;
		const disabled = !product?.bagPrice;
		bagsBtn.classList.toggle('disabled', disabled);
		if (disabled && state.packaging === 'bags') {
			state.packaging = 'bulk';
			document.querySelectorAll('.tc-toggle-btn').forEach(b => {
				b.classList.toggle('active', b.dataset.packaging === 'bulk');
			});
		}
	};
	const renderProducts = () => {
		const grid = document.querySelector('#tc-products');
		if (!grid) return;
		const tons = calcTons();
		const tierIdx = getTierInfo(tons).idx;
		grid.innerHTML = CONFIG.products.map(p => {
			const tag = p.tag ? `<span class="tc-product-tag ${p.tagClass}">${p.tag}</span>` : '';
			const currentPrice = p.prices[tierIdx];
			const optLabel = tons >= OPT_DISPLAY_THRESHOLD ? `<span class="tc-product-opt">ОПТ</span>` : '';
			const priceText = p.bagPrice ? `${fmt(currentPrice)} ₽/т ${optLabel} · ${fmt(p.bagPrice)} ₽/мешок` : `${fmt(currentPrice)} ₽/т ${optLabel}`;
			return `<button class="tc-product ${p.id === state.productId ? 'selected' : ''}" data-id="${p.id}" type="button">${tag}<div class="tc-product-name">${p.name}</div><div class="tc-product-desc">${p.desc}</div><div class="tc-product-price">${priceText}</div></button>`;
		}).join('');
		grid.onclick = e => {
			const card = e.target.closest('.tc-product');
			if (!card) return;
			state.productId = card.dataset.id;
			grid.querySelectorAll('.tc-product').forEach(c => {
				c.classList.toggle('selected', c === card);
			});
			updateToggleUI();
			renderResults();
		};
		updateToggleUI();
	};
	const renderResultCards = (res, product, variant) => {
		const cards = [];
		const isOpt = res.tons >= OPT_DISPLAY_THRESHOLD;
		const optBadge = isOpt ? `<span class="tc-opt-badge">ОПТ</span>` : '';
		if (res.isBags) {
			cards.push(`<div class="tc-card ${variant}"><div class="tc-card-value">${fmt(res.bags)}</div><div class="tc-card-label">Мешков 40 кг</div></div>`);
			cards.push(`<div class="tc-card"><div class="tc-card-value">${res.tons} т</div><div class="tc-card-label">Итого тонн</div></div>`);
			cards.push(`<div class="tc-card ${variant}" style="position:relative">${optBadge}<div class="tc-card-value">${fmt(product.bagPrice)} ₽</div><div class="tc-card-label">Цена за мешок</div></div>`);
		} else {
			cards.push(`<div class="tc-card ${variant}"><div class="tc-card-value">${res.tons} т</div><div class="tc-card-label">Необходимо</div></div>`);
			cards.push(`<div class="tc-card"><div class="tc-card-value">${res.tierLabel}</div><div class="tc-card-label">Ценовой диапазон</div></div>`);
			cards.push(`<div class="tc-card ${variant}" style="position:relative">${optBadge}<div class="tc-card-value">${fmt(res.pricePerTon)} ₽</div><div class="tc-card-label">Цена за тонну</div></div>`);
		}
		cards.push(`<div class="tc-card accent" style="position:relative">${optBadge}<div class="tc-card-value">${fmt(res.totalCost)} ₽</div><div class="tc-card-label">Итоговая стоимость</div></div>`);
		return cards.join('');
	};
	const renderResults = () => {
		const emptyEl = document.querySelector('#tc-empty');
		const resultsEl = document.querySelector('#tc-results');
		if (!emptyEl || !resultsEl) {
			return;
		}
		if (!state.productId || state.area <= 0) {
			emptyEl.hidden = false;
			resultsEl.hidden = true;
			return;
		}
		emptyEl.hidden = true;
		resultsEl.hidden = false;
		const product = CONFIG.products.find(p => p.id === state.productId);
		if (!product) return;
		const res = calcResult(product);
		const sRes = state.superior ? calcSuperiorResult() : null;
		const modeLabel = state.mode === 'repair' ? 'Ремонт' : 'Строительство';
		const thickLabel = state.mode === 'construction' ? ` · ${state.thickness} мм` : '';
		const titleEl = document.querySelector('#tc-results-title');
		if (titleEl) {
			titleEl.textContent = `${modeLabel}${thickLabel} · ${product.name}${product.tag ? ' ' + product.tag : ''}`;
		}
		const mainCards = document.querySelector('#tc-main-cards');
		if (mainCards) {
			mainCards.innerHTML = renderResultCards(res, product, 'primary');
		}
		const supBlock = document.querySelector('#tc-superior-block');
		const supCards = document.querySelector('#tc-superior-cards');
		const totalAmount = document.querySelector('#tc-total-amount');
		const optMsg = document.querySelector('#tc-opt-message');
		if (optMsg) {
			optMsg.hidden = res.tons < OPT_DISPLAY_THRESHOLD;
		}
		if (state.superior && sRes) {
			if (supBlock) {
				supBlock.hidden = false;
			}
			if (supCards) {
				supCards.innerHTML = renderResultCards(sRes, CONFIG.superior, 'sup');
			}
			if (totalAmount) {
				totalAmount.textContent = `${fmt(res.totalCost + sRes.totalCost)} ₽`;
			}
		} else {
			if (supBlock) {
				supBlock.hidden = true;
			}
			if (totalAmount) {
				totalAmount.textContent = `${fmt(res.totalCost)} ₽`;
			}
		}
	};
	const populateTildaPopup = e => {
		if (!state.productId) {
			e.preventDefault();
			const toast = document.createElement('div');
			toast.textContent = 'Выберите материал';
			toast.style.cssText = 'position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:#EF4444;color:#fff;padding:12px 20px;border-radius:12px;font-weight:500;z-index:10001;box-shadow:0 4px 16px rgba(0,0,0,0.15)';
			document.body.appendChild(toast);
			setTimeout(() => toast.remove(), 2500);
			return;
		}
		const product = CONFIG.products.find(p => p.id === state.productId);
		const res = calcResult(product);
		const sRes = state.superior ? calcSuperiorResult() : null;
		const modeLabel = state.mode === 'repair' ? 'Ремонт' : 'Строительство';
		const thickLabel = state.mode === 'construction' ? ` (${state.thickness} мм)` : '';
		const totalCost = res.totalCost + (sRes ? sRes.totalCost : 0);
		const formInputs = document.querySelector('.uc-calc-form .t-form__inputsbox');
		if (formInputs) {
			const setVal = (name, val) => {
				const input = formInputs.querySelector(`input[name="${name}"]`);
				if (input) {
					input.value = val || '';
				}
			};
			setVal('тип работ', modeLabel + thickLabel);
			setVal('площадь', fmt(state.area) + ' м²');
			setVal('толщина слоя', state.mode === 'construction' ? state.thickness + ' мм' : '');
			setVal('материал', product.name + (product.tag ? ' ' + product.tag : ''));
			setVal('тип отгрузки', state.packaging === 'bags' ? 'Мешки 40 кг' : 'Тонны');
			setVal('ценовой диапазон', res.tierLabel);
			setVal('итого мешков', res.bags);
			setVal('итого тонн', res.tons + ' т');
			setVal('стоимость мешками', fmt(res.isBags ? res.totalCost : Math.round(res.bags * product.bagPrice)) + ' ₽');
			setVal('стоимость тонн', fmt(!res.isBags ? res.totalCost : Math.round(res.tons * res.pricePerTon)) + ' ₽');
			setVal('финишный слой', state.superior ? 'Да' : '');
			if (state.superior && sRes) {
				setVal('финишный слой - итого мешков', sRes.bags);
				setVal('финишный слой - итого тонн', sRes.tons + ' т');
				setVal('финишный слой - стоимость', fmt(sRes.totalCost) + ' ₽');
			}
			setVal('итоговая стоимость', fmt(totalCost) + ' ₽');
		}
		const popupDescr = document.querySelector('.uc-calc-form .t702__descr');
		let summaryBlock = document.querySelector('.uc-calc-form .modal-summary');
		if (!summaryBlock && popupDescr) {
			summaryBlock = document.createElement('div');
			summaryBlock.className = 'modal-summary t-text';
			popupDescr.insertAdjacentElement('afterend', summaryBlock);
		}
		if (summaryBlock) {
			const pkgType = state.packaging === 'bags' ? 'Мешки 40 кг' : 'Тонны';
			const mainQty = state.packaging === 'bags' ? fmt(res.bags) + ' шт' : res.tons + ' т';
			let html = `<p><span>Тип работ:</span><span>${modeLabel}${thickLabel}</span></p>`;
			html += `<p><span>Материал:</span><span>${product.name}${product.tag ? ' ' + product.tag : ''}</span></p>`;
			html += `<p><span>Площадь:</span><span>${fmt(state.area)} м²</span></p>`;
			html += `<p><span>Фасовка:</span><span>${pkgType}</span></p>`;
			html += `<p><span>Объём/Кол-во:</span><span>${mainQty}</span></p>`;
			html += `<p><span>Тариф:</span><span>${res.tierLabel} · ${fmt(res.pricePerTon)} ₽/т</span></p>`;
			html += `<p><span>Стоимость основного:</span><span>${fmt(res.totalCost)} ₽</span></p>`;
			if (state.superior && sRes) {
				html += `<p><span>Финишное покрытие:</span><span>${fmt(sRes.totalCost)} ₽</span></p>`;
			}
			html += `<p><span><strong>Итоговая стоимость:</strong></span><span><strong>${fmt(totalCost)} ₽</strong></span></p>`;
			summaryBlock.innerHTML = html;
		}
	};
	let initialized = false;
	const init = () => {
		if (initialized) return;
		initialized = true;
		document.querySelectorAll('.tc-seg-btn').forEach(btn => {
			btn.onclick = () => {
				state.mode = btn.dataset.mode;
				document.querySelectorAll('.tc-seg-btn').forEach(b => {
					b.classList.toggle('active', b === btn);
				});
				const thickField = document.querySelector('#tc-thickness-field');
				if (thickField) {
					thickField.hidden = state.mode !== 'construction';
				}
				renderProducts();
				renderResults();
			};
		});
		const areaInput = document.querySelector('#tc-area');
		if (areaInput) {
			areaInput.addEventListener('input', () => {
				const value = parseFloat(areaInput.value);
				state.area = (isNaN(value) || value <= 0) ? 0 : value;
				renderProducts();
				renderResults();
			});
		}
		document.querySelector('#tc-preset')?.addEventListener('click', () => {
			state.area = CONFIG.constants.STANDARD_AREA;
			const input = document.querySelector('#tc-area');
			if (input) {
				input.value = CONFIG.constants.STANDARD_AREA;
			}
			renderProducts();
			renderResults();
		});
		const slider = document.querySelector('#tc-thickness');
		const sliderFill = document.querySelector('.tc-slider-fill');
		const sliderVal = document.querySelector('.tc-slider-val');
		const updateSlider = () => {
			if (!slider) return;
			state.thickness = parseInt(slider.value, 10);
			if (sliderVal) {
				sliderVal.textContent = state.thickness + ' мм';
			}
			const pct = ((state.thickness - slider.min) / (slider.max - slider.min)) * 100;
			if (sliderFill) {
				sliderFill.style.width = pct + '%';
			}
			const hint = document.querySelector('#tc-thickness-hint');
			if (hint) {
				hint.innerHTML = `Неуплотнённый: <strong>${Math.round(state.thickness * (4 / 3))} мм</strong> → укатка: <strong>${state.thickness} мм</strong>`;
			}
			renderProducts();
			renderResults();
		};
		if (slider) {
			slider.addEventListener('input', updateSlider);
		}
		updateSlider();
		document.querySelectorAll('.tc-toggle-btn').forEach(btn => {
			btn.onclick = () => {
				const product = CONFIG.products.find(p => p.id === state.productId);
				if (btn.dataset.packaging === 'bags' && !product?.bagPrice) {
					return;
				}
				state.packaging = btn.dataset.packaging;
				document.querySelectorAll('.tc-toggle-btn').forEach(b => {
					b.classList.toggle('active', b === btn);
				});
				renderResults();
			};
		});
		document.querySelector('#tc-superior')?.addEventListener('change', e => {
			state.superior = e.target.checked;
			renderResults();
		});
		document.querySelector('#tc-reset')?.addEventListener('click', () => {
			state.superior = false;
			const sw = document.querySelector('#tc-superior');
			if (sw) {
				sw.checked = false;
			}
			renderResults();
		});
		document.querySelector('#tc-cta')?.addEventListener('click', populateTildaPopup);
		document.querySelectorAll('.tc-toggle-btn').forEach(button => {
			button.classList.toggle('active', button.dataset.packaging === state.packaging);
		});
		renderProducts();
		renderResults();
	};
	async function waitForAppAndInit() {
		const dataReady = await waitForPriceData();
		CONFIG = buildConfig();
		state.productId = CONFIG.products[0]?.id || 'classic';
		state.area = CONFIG.constants.STANDARD_AREA;
		const areaInput = document.querySelector('#tc-area');
		if (areaInput) {
			areaInput.value = state.area;
		}
		init();
	}
	waitForAppAndInit();
	if (typeof ResizeObserver !== 'undefined' && window.parent !== window) {
		new ResizeObserver(() => {
			window.parent.postMessage({
				type: 'terracourts-resize',
				height: document.documentElement.scrollHeight + 24
			}, '*');
		}).observe(document.body);
	}
})();
</script>
Рассчитать стоимость теннисита
м²

Результаты

Итого включая все материалы
0 ₽
Оформить заказ
BASICS
Why typography matters?
Made on
Tilda