<!-- Прогресс сборов T1291 V2: суммы из цен, завершение по метке и скрытие цен в попапе. -->
<style>
.t1291 {
--fund-color: #2585d8;
--fund-track: #dfe9f2;
--fund-label-color: #ffffff;
}
.t1291 .fund-ready { position: relative; }
.t1291 .fund-ready .t-catalog__card__price-wrapper { display: none !important; }
.t1291 .t-catalog__prod-popup__price-wrapper,
.t1291 .t-catalog__prod-popup__price,
.t1291 .t-catalog__prod-popup__price_old,
.t1291 .fund-complete-tag { display: none !important; }
.t1291 .fund-progress {
box-sizing: border-box;
width: 100%;
min-width: 0;
margin-top: auto;
padding-top: 24px;
font-family: var(--t-text-font, Arial, sans-serif);
font-size: 12px;
line-height: 1.5;
text-align: left;
color: inherit;
}
.t1291 .fund-track {
height: 5px;
overflow: hidden;
border-radius: 999px;
background: var(--fund-track);
}
.t1291 .fund-fill {
display: block;
height: 100%;
width: 0;
border-radius: inherit;
background: var(--fund-color);
transition: width .45s ease;
}
.t1291 .fund-meta {
display: flex;
flex-wrap: wrap;
align-items: baseline;
justify-content: space-between;
gap: 4px 12px;
margin-top: 8px;
}
.t1291 .fund-percent {
flex: 0 0 auto;
color: var(--fund-color);
font-weight: 600;
}
.t1291 .fund-summary {
flex: 1 1 160px;
min-width: 0;
text-align: right;
overflow-wrap: anywhere;
}
.t1291 .fund-badge {
position: absolute;
top: 14px;
right: 14px;
z-index: 10;
box-sizing: border-box;
max-width: calc(100% - 28px);
padding: 7px 12px;
border-radius: 6px;
background: var(--fund-color);
color: var(--fund-label-color);
font-family: var(--t-text-font, Arial, sans-serif);
font-size: 12px;
font-weight: 500;
line-height: 1.4;
text-align: center;
pointer-events: none;
}
.t1291 .fund-badge[hidden] { display: none !important; }
@media (prefers-reduced-motion: reduce) {
.t1291 .fund-fill { transition: none; }
}
</style>
<script>
(function () {
'use strict';
if (window.TildaFundraisingST340) {
window.TildaFundraisingST340.refresh();
return;
}
var ROOT = '.t1291';
var CARD = '.t-catalog__card';
var queued = false;
var number = new Intl.NumberFormat('ru-RU', { maximumFractionDigits: 2 });
var percent = new Intl.NumberFormat('ru-RU', { maximumFractionDigits: 1 });
function amount(value) {
var text = String(value == null ? '' : value).trim();
if (!text) return NaN;
text = text.replace(/[\s\u00a0\u202f]/g, '').replace(',', '.');
return /^\d+(?:\.\d+)?$/.test(text) ? Number(text) : NaN;
}
function make(tag, className, text) {
var node = document.createElement(tag);
node.className = className;
if (text != null) node.textContent = text;
return node;
}
function setText(node, text) {
if (node.textContent !== text) node.textContent = text;
}
function reset(card) {
card.classList.remove('fund-ready');
card.querySelectorAll('.fund-progress, .fund-badge').forEach(function (node) {
node.remove();
});
}
function update(card) {
var price = card.querySelector('.t-catalog__card__price .t-catalog__card__price-value');
var old = card.querySelector('.t-catalog__card__price_old .t-catalog__card__price-value');
var host = card.querySelector('.t-catalog__card__wrap_txt-and-btns');
if (!price || !host) { reset(card); return; }
// При равенстве цен Тильда может удалить старую цену даже из ответа каталога.
// В таком случае явная метка «Сбор завершён» отличает 100% от пустого сбора.
var goal = amount(price.getAttribute('data-product-price-def'));
if (!Number.isFinite(goal)) goal = amount(price.textContent);
var collected = old && old.textContent.trim() ? amount(old.textContent) : 0;
var markedComplete = false;
card.querySelectorAll('.t-catalog__card__mark').forEach(function (mark) {
var isComplete = /^сбор\s+заверш[её]н[.!]?$/i.test(mark.textContent.trim());
mark.classList.toggle('fund-complete-tag', isComplete);
if (isComplete) markedComplete = true;
});
if (markedComplete && goal > 0) {
collected = Number.isFinite(collected) ? Math.max(goal, collected) : goal;
}
if (!(goal > 0) || !Number.isFinite(collected) || collected < 0) {
reset(card);
return;
}
var ratio = collected / goal * 100;
var fill = Math.min(100, ratio);
var complete = collected >= goal;
// Не показываем округлённые 100% до фактического достижения цели.
var shown = !complete && ratio >= 99.95 ? 99.9 : ratio;
var currencyNode = card.querySelector('.t-catalog__card__price .t-catalog__card__price-currency');
var currency = currencyNode ? currencyNode.textContent.trim() : '₽';
if (/^(?:р\.?|руб\.?)$/i.test(currency)) currency = '₽';
var unit = currency ? ' ' + currency : '';
var summary = 'Собрано ' + number.format(collected) + unit + ' из ' + number.format(goal) + unit;
var progress = card.querySelector('.fund-progress');
if (!progress) {
progress = make('div', 'fund-progress');
var track = make('div', 'fund-track');
track.setAttribute('role', 'progressbar');
track.setAttribute('aria-label', 'Прогресс сбора');
track.setAttribute('aria-valuemin', '0');
track.setAttribute('aria-valuemax', '100');
track.appendChild(make('span', 'fund-fill'));
var meta = make('div', 'fund-meta');
meta.appendChild(make('span', 'fund-percent'));
meta.appendChild(make('span', 'fund-summary'));
progress.appendChild(track);
progress.appendChild(meta);
host.appendChild(progress);
}
var trackNode = progress.querySelector('.fund-track');
trackNode.setAttribute('aria-valuenow', String(fill));
trackNode.setAttribute('aria-valuetext', summary);
progress.querySelector('.fund-fill').style.width = fill + '%';
setText(progress.querySelector('.fund-percent'), percent.format(shown) + '%');
setText(progress.querySelector('.fund-summary'), summary);
var badge = card.querySelector('.fund-badge');
if (!badge) {
badge = make('div', 'fund-badge', 'Сбор завершён');
card.appendChild(badge);
}
badge.hidden = !complete;
card.classList.add('fund-ready');
}
function refresh() {
document.querySelectorAll(ROOT + ' ' + CARD).forEach(update);
}
function schedule() {
if (queued) return;
queued = true;
requestAnimationFrame(function () { queued = false; refresh(); });
}
function start() {
refresh();
// Фильтрация, «Показать ещё» и обновление сумм без повторного запуска кода.
new MutationObserver(function (records) {
var changed = records.some(function (record) {
var target = record.target.nodeType === 1 ? record.target : record.target.parentElement;
if (!target || target.closest('.fund-progress, .fund-badge')) return false;
if (target.closest(ROOT)) return true;
return Array.from(record.addedNodes).some(function (node) {
return node.nodeType === 1 && (node.matches(ROOT) || node.querySelector(ROOT));
});
});
if (changed) schedule();
}).observe(document.body, {
childList: true,
subtree: true,
characterData: true,
attributes: true,
attributeFilter: ['data-product-price-def']
});
}
window.TildaFundraisingST340 = { version: '2', refresh: refresh };
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start, { once: true });
} else start();
})();
</script>
<!-- Мобильные карточки сборов T1291: внутренние отступы 10 px и выравнивание текстов по левому краю. -->
<style>
@media screen and (max-width: 640px) {
.t1291 .fund-ready .t-catalog__card__contentwrapper {
padding: 10px !important;
}
.t1291 .fund-ready .t-catalog__card__wrap_txt-and-btns,
.t1291 .fund-ready .t-catalog__card__textwrapper {
padding: 0 !important;
}
.t1291 .fund-ready .t-catalog__card__title,
.t1291 .fund-ready .t-catalog__card__descr {
margin-left: 0 !important;
margin-right: 0 !important;
text-align: left !important;
}
.t1291 .fund-progress {
padding-top: 10px;
text-align: left;
}
.t1291 .fund-meta {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.t1291 .fund-summary {
flex: none;
width: 100%;
text-align: left;
}
}
</style>