From c7bd6cef74509f9526d8393820de77c448cd4e09 Mon Sep 17 00:00:00 2001 From: Dekart Deploy Bot Date: Sat, 27 Jun 2026 12:31:12 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20SEO=20audit=20fixes=20for=20/otzyvy/=20?= =?UTF-8?q?=E2=80=94=20Schema.org,=20PHP,=20JS,=20CSS,=20A11Y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical: - Move GeoCoordinates from PostalAddress to Organization level - Fix AggregateRating @id to point at #organization, not page URL High: - Replace Review.itemReviewed inline LocalBusiness with @id reference - Change @type from array to just 'School' - Remove foundingDate from reviews page (add comment for CF) - Make telephone property conditional (only when non-empty) - Add postalCode from branch_postal_code option - Fix branch_city fallback from 'городе' to 'Щёлково' - Replace inline onclick yaCounter with JS global handler - Remove inline critical CSS (styles in file) - Move price text to CF field reviews_intro_price_text Medium: - Add --color-bg and --accent CSS variables - Fix .page-rewiews typo → .page-reviews - Fix .contact-map display:flex→block - Add prefers-reduced-motion support - JS: var→let/const, scroll throttle via requestAnimationFrame - JS: catch(e)→console.warn - JS: data-target→data-target-value (avoid conflict) - A11Y: FAQ aria-expanded/aria-controls, phone aria-label - A11Y: modal role=dialog aria-modal=true - A11Y: breadcrumb role=navigation aria-label - Remove desktop-only class from breadcrumbs (mobile support) Low: - Add preconnect for unpkg.com (Phosphor Icons CDN) - Add decoding=async to gallery images --- .../themes/dekart/assets/css/reviews-page.css | 1906 +++++++++++++++++ .../themes/dekart/assets/js/reviews-page.js | 222 ++ wp-content/themes/dekart/functions.php | 947 +++++++- wp-content/themes/dekart/page-reviews.php | 1380 ++++++++++-- 4 files changed, 4131 insertions(+), 324 deletions(-) create mode 100644 wp-content/themes/dekart/assets/css/reviews-page.css create mode 100644 wp-content/themes/dekart/assets/js/reviews-page.js diff --git a/wp-content/themes/dekart/assets/css/reviews-page.css b/wp-content/themes/dekart/assets/css/reviews-page.css new file mode 100644 index 0000000..74c12d3 --- /dev/null +++ b/wp-content/themes/dekart/assets/css/reviews-page.css @@ -0,0 +1,1906 @@ +/* ════════════════════════════════════════════════════ + reviews-page.css — стили для page-reviews.php + Декарт — частная школа + ════════════════════════════════════════════════════ + ⚠️ SEO: Featured image файл назван "bezymyannyj.jpg" + (ID 1162). Для улучшения SEO переименовать в + "shkola-dekart-otzyvy.jpg" при повторной загрузке + или через media-rename плагин. */ + +/* ─── CSS-переменные дизайн-системы ─── */ +:root { + --color-primary: #E8753A; + --color-primary-hover: #D6652E; + --color-secondary: #3BB2A0; + --color-accent: #FFD43E; + --color-text: #1C2B2D; + --color-text-muted: #5A6B6D; + --color-text-light: #8A9A9D; + --card-radius: 20px; + --card-padding: clamp(20px, 3vw, 32px); + --card-shadow: 0 2px 16px rgba(0,0,0,0.06); + --card-shadow-hover: 0 8px 32px rgba(0,0,0,0.1); + --transition-fast: 0.2s ease; + --transition-normal: 0.3s ease; + --color-bg: #fff; + --accent: #7C3AED; + --accent-hover: #6D28D9; + --accent-light: #F5F3FF; + --color-border: #e8e8e8; +} + +/* ─── HERO ─── */ +.reviews-hero { + position: relative; + padding: 60px 0; + overflow: hidden; + background: var(--color-text); + background-image: + radial-gradient(ellipse 80% 70% at 20% 40%, rgba(232, 117, 58, 0.08) 0%, transparent 70%), + radial-gradient(ellipse 60% 60% at 80% 60%, rgba(59, 178, 160, 0.06) 0%, transparent 70%); +} +/* Декоративный акцент — тонкая волнистая линия снизу */ +.reviews-hero::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 6px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-secondary) 50%, var(--color-primary) 100%); + opacity: 0.5; +} +/* Акцентный уголок справа */ +.reviews-hero::before { + content: ''; + position: absolute; + top: -120px; + right: -120px; + width: 360px; + height: 360px; + border-radius: 50%; + background: radial-gradient(circle, rgba(232,117,58,0.06) 0%, transparent 70%); + pointer-events: none; +} + +.reviews-hero__wrapper { + display: flex; + align-items: center; + gap: 40px; + position: relative; + z-index: 1; +} +.reviews-hero__content { + flex: 1; + max-width: 600px; + min-width: 0; +} + +/* ─── Фото ─── */ +.reviews-hero__image { + flex: 0 0 340px; + margin-left: auto; + margin-right: 20px; + border-radius: var(--card-radius); + overflow: hidden; + box-shadow: var(--card-shadow-hover); + transform: rotate(1deg); + transition: transform var(--transition-normal); + aspect-ratio: 4 / 3; +} +.reviews-hero__image:hover { + transform: rotate(0deg) scale(1.01); +} +.reviews-hero__image img { + width: 100%; + height: 100%; + display: block; + object-fit: cover; +} + +/* ─── H1 ─── */ +.reviews-hero__h1 { + font-family: 'Oswald', sans-serif; + font-size: clamp(36px, 4.2vw, 52px); + font-weight: 500; + line-height: 1.12; + margin-bottom: 14px; + color: #fff; +} +.reviews-hero__subtitle { + font-size: 18px; + line-height: 1.55; + color: rgba(255,255,255,0.72); + margin-bottom: 28px; + max-width: 500px; +} + +/* ─── Метрики ─── */ +.reviews-hero__metrics { + display: flex; + gap: 16px; + margin-bottom: 32px; + flex-wrap: nowrap; +} +.reviews-hero__metric { + background: rgba(255,255,255,0.08); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); + border: 1px solid rgba(255,255,255,0.12); + border-radius: 14px; + padding: 14px 22px; + text-align: center; + min-width: 110px; + transition: background var(--transition-fast), transform var(--transition-fast); +} +.reviews-hero__metric:hover { + background: rgba(255,255,255,0.13); + transform: translateY(-2px); +} +.reviews-hero__metric-number { + font-family: 'Oswald', sans-serif; + font-size: clamp(28px, 3vw, 34px); + font-weight: 500; + color: var(--color-primary); + display: block; + line-height: 1.1; + margin-bottom: 2px; +} +.reviews-hero__metric-label { + font-size: 13px; + color: rgba(255,255,255,0.7); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* ─── CTA ─── */ +.reviews-hero__cta-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 16px 40px; + font-size: 17px; + font-weight: 600; + color: #fff; + background: var(--color-primary); + border: none; + border-radius: 12px; + cursor: pointer; + transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast); + box-shadow: 0 4px 16px rgba(232, 117, 58, 0.35); +} +.reviews-hero__cta-btn:hover { + background: var(--color-primary-hover); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(232, 117, 58, 0.45); +} +.reviews-hero__cta-btn:active { + transform: translateY(0); +} + +/* ─── СЕТКА ОТЗЫВОВ ─── */ +.reviews-grid { + padding: 20px 0 60px; +} + +/* ─── H2 над отзывами (SEO) ─── */ +.reviews-grid__h2 { + text-align: center; + margin-bottom: 16px; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); +} + +/* ─── Пояснительный текст перед карточками ─── */ +.reviews-grid__intro { + font-size: clamp(15px, 1.2vw, 17px); + line-height: 1.65; + color: var(--color-text-muted); + text-align: center; + max-width: 700px; + margin: 0 auto 40px; +} + +/* ─── ВСТУПИТЕЛЬНЫЙ ТЕКСТ ─── */ +.reviews-intro { + padding: 48px 0; +} +.reviews-intro__content { + max-width: 820px; + margin: 0 auto; +} + +/* Лид-абзац — первый, акцентный */ +.reviews-intro__lead { + font-size: clamp(17px, 1.5vw, 20px); + line-height: 1.55; + color: var(--color-text); + text-align: center; + margin-bottom: 28px; + padding-bottom: 28px; + border-bottom: 2px solid var(--color-border, #e8e8e8); +} + +/* Сетка карточек (2-й и 3-й абзацы) */ +.reviews-intro__grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 24px; +} +.reviews-intro__card { + background: var(--accent-light, #f7f6f2); + border-radius: 12px; + padding: 20px; + display: flex; + flex-direction: column; + gap: 10px; +} +.reviews-intro__card-icon { + font-size: 22px; + line-height: 1; + flex-shrink: 0; +} +.reviews-intro__card-text { + font-size: 14.5px; + line-height: 1.55; + color: var(--color-text); + margin: 0; +} + +/* ─── Инфоблок (режим работы, цены) ─── */ +.reviews-intro__info { + display: flex; + flex-wrap: wrap; + gap: 10px 24px; + justify-content: center; + padding: 16px 24px; + background: #fff; + border: 1px solid var(--color-border, #e8e8e8); + border-radius: 10px; + font-size: 14px; + line-height: 1.5; + color: var(--color-text); +} +.reviews-intro__info p { + margin: 0; +} +.reviews-intro__info strong { + color: var(--color-text); + font-weight: 600; +} +.reviews-intro__info a { + color: var(--color-primary); + font-weight: 600; + text-decoration: underline; + text-underline-offset: 3px; + transition: color var(--transition-fast); +} +.reviews-intro__info a:hover { + color: var(--color-primary-hover); +} + +/* ─── Breadcrumbs (визуальные) ─── */ +.breadcrumbs-wrapper { + padding: 12px 0 0; +} +@media (max-width: 860px) { + .breadcrumbs-wrapper { + padding: 8px 0 0; + } +} +/* ─── LW-утилиты (как на странице лагеря) ─── */ +.lw-grid { + display: grid; +} +.lw-grid--3 { + grid-template-columns: repeat(3, 1fr); +} +.lw-gap-20 { + gap: 20px; +} +.lw-flex { + display: flex; +} +.lw-flex--row { + flex-direction: row; +} +.lw-flex--col { + flex-direction: column; +} +.lw-gap-12 { + gap: 12px; +} +.lw-gap-8 { + gap: 8px; +} +.lw-items-center { + align-items: center; +} +.lw-justify-between { + justify-content: space-between; +} + +.lw-card { + background: var(--color-bg); + border-radius: var(--card-radius); + padding: 20px; + box-shadow: var(--card-shadow); + display: flex; + flex-direction: column; + transition: box-shadow var(--transition-normal), transform var(--transition-normal); +} +.lw-card:hover { + box-shadow: var(--card-shadow-hover); + transform: translateY(-2px); +} + +.lw-avatar { + border-radius: 50%; + overflow: hidden; + flex-shrink: 0; + background: rgba(59, 178, 160, 0.1); + display: flex; + align-items: center; + justify-content: center; +} +.lw-avatar--48 { + width: 48px; + height: 48px; +} +.lw-avatar__img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} +.lw-avatar--letter { + background: rgba(232, 117, 58, 0.08); /* --color-primary 8% */ +} +.lw-avatar__letter { + display: block; + font-size: 18px; + font-weight: 700; + color: var(--color-primary); + line-height: 1; + user-select: none; +} + +.lw-text-dark { + color: #1c2b2d; +} +.lw-text-gray { + color: var(--color-text-muted); +} +.lw-text-sm { + font-size: 14px; + line-height: 1.4; +} +.lw-text-xs { + font-size: 12px; + line-height: 1.3; +} +.lw-font-medium { + font-weight: 500; +} +.lw-font-semibold { + font-weight: 600; +} +.lw-font-bold { + font-weight: 700; +} + +.lw-mt-8 { + margin-top: 8px; +} +.lw-mb-8 { + margin-bottom: 8px; +} +.lw-mb-12 { + margin-bottom: 12px; +} + +.lw-badge { + display: inline-flex; + align-items: center; + padding: 4px 10px; + border-radius: 50px; + font-size: 11px; + font-weight: 600; + line-height: 1.2; + white-space: nowrap; + margin-left: auto; + flex-shrink: 0; +} +.lw-badge--verified { + background: #059669; + color: #fff; + border-radius: 50px; + padding: 3px 12px 3px 10px; + font-size: 11px; + font-weight: 600; + line-height: 1.4; + white-space: nowrap; + align-self: flex-start; +} + +.lw-stars { + display: flex; + gap: 2px; + align-items: center; +} +.lw-star { + color: var(--color-text-light); + flex-shrink: 0; +} +.lw-star--filled { + color: #FFD43E; +} + +.lw-card__text { + font-size: 14px; + line-height: 1.55; + color: var(--color-text-muted); + word-break: break-word; +} + +/* ─── Сетка отзывов (как на странице лагеря) ─── */ +.reviews-cards .lw-scroll-x { + overflow: visible; + padding: 0; +} +.reviews-cards .lw-grid--3 { + display: flex; + flex-wrap: wrap; + gap: 24px; + justify-content: center; +} +.reviews-cards .lw-grid--3 .lw-card { + width: calc(33.33% - 16px); + min-width: 280px; + padding: 24px; + border-radius: 20px; + box-shadow: 0 2px 16px rgba(0,0,0,0.06); + border: 1.5px solid rgba(0,0,0,0.12); + transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, background 0.3s ease; +} +.reviews-cards .lw-grid--3 .lw-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 32px rgba(0,0,0,0.1); + border-color: rgba(124, 58, 237, 0.15); + background: var(--accent-light); +} + +/* ─── Clamp текста для длинных отзывов ─── */ +.review-card__text--clamped { + position: relative; + max-height: 120px; + overflow: hidden; + transition: max-height .4s ease; +} +.review-card__text--clamped.review-card__text--expanded { + max-height: 2000px; +} +.review-card__text--clamped:not(.review-card__text--expanded)::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 40px; + background: linear-gradient(transparent, var(--color-bg)); +} +.review-card__btn-more { + display: inline-block; + padding: 0; + border: none; + background: none; + color: var(--accent); + font-weight: 600; + font-size: 14px; + cursor: pointer; + align-self: flex-start; +} +.review-card__btn-more:hover { + text-decoration: underline; +} + +/* ─── ФУТЕР КАРТОЧКИ: дата + "Читать ещё" ─── */ +.review-card__footer { + display: flex; + align-items: center; + gap: 12px; + margin-top: 8px; +} +.review-card__date { + margin-left: auto; + font-size: 13px; + color: var(--color-text-muted); + white-space: nowrap; +} + +/* ─── Ссылка на преподавателя в карточке отзыва ─── */ +.review-card__teacher-link { + color: var(--accent); + text-decoration: underline; + text-underline-offset: 3px; + text-decoration-color: currentColor; + transition: color .2s, font-weight .2s; + font-weight: 500; +} +.review-card__teacher-link:hover { + color: var(--accent-hover); + font-weight: 700; +} + +/* ─── РЕЗУЛЬТАТЫ (блок с цифрами) ─── */ +.results { + padding: 40px 0; + background: var(--accent-light, #F5F3FF); +} +.results__title { + text-align: center; + margin-bottom: 40px; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); +} +.results__grid { + display: flex; + justify-content: center; + flex-wrap: wrap; +} +.results__card { + flex: 1 1 0; + min-width: 160px; + max-width: 260px; + padding: 32px 24px; + text-align: center; + position: relative; +} +.results__card + .results__card::before { + content: ''; + position: absolute; + left: 0; + top: 12%; + height: 76%; + width: 1px; + background: rgba(0,0,0,0.1); +} +.results__icon { + display: block; + font-size: 22px; + color: var(--accent); + margin-bottom: 10px; + line-height: 1; +} +.results__number { + font-family: 'Oswald', sans-serif; + font-size: clamp(48px, 6vw, 78px); + font-weight: 700; + color: var(--accent); + line-height: 1; + margin-bottom: 10px; + display: block; +} +.results__label { + font-size: 14px; + color: var(--color-text-muted); + max-width: 200px; + margin: 0 auto; + line-height: 1.4; +} + +@media (max-width: 600px) { + .results__card { + flex: 0 0 33.33%; + max-width: 33.33%; + min-width: 0; + padding: 24px 12px; + } + .results__card + .results__card::before { + top: 10%; + height: 80%; + width: 1px; + left: 0; + } + .results__number { + font-size: 38px; + margin-bottom: 4px; + } + .results__label { + font-size: 12px; + max-width: none; + } +} + +/* ─── ФОТО С ЗАНЯТИЙ ─── */ +.reviews-photos { + padding: 80px 0; + background: #fff; +} +.reviews-photos__title { + text-align: center; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); + margin-bottom: 10px; +} +.reviews-photos__desc { + text-align: center; + font-size: 15px; + color: var(--color-text-muted); + margin-bottom: 40px; +} +.reviews-photos__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 20px; +} +.reviews-photos__item { + border-radius: 16px; + overflow: hidden; + box-shadow: 0 2px 12px rgba(0,0,0,0.06); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); + /* Все фото одного размера 4:3 */ + aspect-ratio: 4 / 3; +} +.reviews-photos__item:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0,0,0,0.1); +} +.reviews-photos__img { + width: 100%; + height: 100%; + display: block; + object-fit: cover; +} +@media (max-width: 768px) { + .reviews-photos { + padding: 48px 0; + } + .reviews-photos__grid { + grid-template-columns: repeat(2, 1fr); + gap: 10px; + } + .reviews-photos__desc { + margin-bottom: 24px; + } +} + +/* ─── ВИДЕООТЗЫВЫ ─── */ +.video-reviews { + padding: 60px 0; +} +.video-reviews__title { + text-align: center; + margin-bottom: 40px; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); +} +.video-reviews__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 24px; +} +.video-reviews__card { + background: #fff; + border-radius: var(--card-radius); + overflow: hidden; + box-shadow: var(--card-shadow); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); +} +.video-reviews__card:hover { + transform: translateY(-4px); + box-shadow: var(--card-shadow-hover); +} +.video-reviews__embed { + position: relative; + width: 100%; + padding-bottom: 56.25%; /* 16:9 */ + background: #000; +} +.video-reviews__embed iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} +.video-reviews__link { + display: block; + padding: 16px 20px; + color: var(--color-primary); + font-weight: 500; + text-decoration: underline; + text-underline-offset: 3px; +} +.video-reviews__link:hover { + color: var(--color-primary-hover); +} +.video-reviews__name { + padding: 12px 20px 16px; + font-size: 15px; + color: var(--color-text-muted); + margin: 0; +} + +/* ─── FAQ (две колонки, аккордеон как на camp) ─── */ +.reviews-faq { + padding: 40px 0; + background: var(--accent-light, #F5F3FF); +} +.reviews-faq__title { + text-align: center; + margin-bottom: 40px; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); +} +.reviews-faq-wrapper { + display: flex; + gap: 30px; +} +.reviews-faq .accordion { + width: 50%; + display: flex; + flex-direction: column; + gap: 10px; + border-top: 1px solid #ccc; +} +.reviews-faq .accordion .box__accordion { + position: relative; + cursor: pointer; + border-bottom: 1px solid #ccc; + border-radius: 0; +} +.reviews-faq .box__accordion_label { + position: relative; + padding: 20px 0; + cursor: pointer; + display: flex; + align-items: center; + gap: 20px; + justify-content: space-between; +} +.reviews-faq .box__accordion_label::after { + background-image: none !important; +} +.reviews-faq .box__accordion_label span { + font-size: clamp(18px, 2.2vw, 22px); + line-height: 1.25; + font-family: var(--font-display, 'Oswald', sans-serif); + font-weight: 600; + color: var(--color-text); +} +.box__accordion_label svg { + width: 36px; + height: 36px; + padding: 8px; + border-radius: 50%; + background: var(--color-primary); + stroke: #fff; + transition: background var(--transition-fast); + flex-shrink: 0; +} +.box__accordion_label svg:hover { + background: var(--color-primary-hover); +} +.active .box__accordion_label svg { + rotate: 45deg; + background: var(--color-primary-hover); +} +.box__accordion_label svg g { + stroke: #fff; +} +.box__accordion_label svg:hover g { + stroke: #fff; +} +.reviews-faq .box__accordion_content { + display: flex; + position: relative; + overflow: hidden; + max-height: 0; + transition: max-height .3s ease; + gap: 20px; + align-items: center; +} +.box__accordion_content-text { + display: flex; + flex-direction: column; + gap: 10px; + font-size: 16px; + line-height: 1.6; + color: var(--color-text-muted); + padding-bottom: 20px; + font-family: var(--font-body, sans-serif); +} +.box__accordion_content-text p { + margin: 0; +} + +/* ─── ЗАКЛЮЧИТЕЛЬНЫЙ ТЕКСТ ─── */ +.reviews-cta-text { + padding: 20px 0 60px; +} +.reviews-cta-text__inner { + max-width: 780px; + margin: 0 auto; +} +.reviews-cta-text__lead { + font-size: clamp(17px, 1.3vw, 19px); + line-height: 1.7; + color: var(--color-text); + text-align: center; +} + +/* ─── ФИНАЛЬНЫЙ CTA ─── */ + .final-cta { + padding: 80px 0; + background: linear-gradient(135deg, #1a2f31 0%, #0f2022 100%); + color: #fff; + text-align: center; + position: relative; + overflow: hidden; +} +/* Тонкий акцентный бордер сверху */ +.final-cta::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 4px; + background: linear-gradient(90deg, var(--color-primary), var(--color-secondary)); +} +.final-cta__inner { + position: relative; + z-index: 1; +} +.final-cta__title { + font-family: 'Oswald', sans-serif; + font-size: clamp(26px, 3.2vw, 38px); + font-weight: 500; + margin-bottom: 12px; + color: #fff; + letter-spacing: -0.3px; +} +.final-cta__subtitle { + font-size: 17px; + line-height: 1.55; + margin-bottom: 32px; + max-width: 560px; + margin-left: auto; + margin-right: auto; + color: rgba(255,255,255,0.7); +} +.final-cta__actions { + display: flex; + gap: 16px; + justify-content: center; + flex-wrap: wrap; +} +.final-cta__buttons { + display: flex; + gap: 16px; + justify-content: center; + flex-wrap: wrap; +} +.final-cta .btn-primary { + box-shadow: 0 4px 20px rgba(232,117,58,0.35); +} +.final-cta .btn-secondary { + border-color: rgba(255,255,255,0.3); + color: #fff; + background: rgba(255,255,255,0.06); +} +.final-cta .btn-secondary:hover { + border-color: rgba(255,255,255,0.6); + background: rgba(255,255,255,0.1); +} + +/* ─── ПЕРЕЛИНКОВКА ─── */ +.cross-links { + padding: 60px 0; +} +.cross-links__title { + text-align: center; + margin-bottom: 40px; + font-family: 'Oswald', sans-serif; + font-size: clamp(24px, 2.8vw, 32px); + font-weight: 500; + color: var(--color-text); +} +.cross-links__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 20px; +} +.cross-links__card { + display: block; + padding: 24px; + background: #fff; + border-radius: 12px; + text-decoration: none; + box-shadow: var(--card-shadow); + border: 1px solid rgba(0,0,0,0.06); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); + color: var(--color-text); + font-weight: 500; +} +.cross-links__card:hover { + transform: translateY(-3px); + box-shadow: var(--card-shadow-hover); + color: var(--color-primary); +} + +/* ─── ОСТАВИТЬ ОТЗЫВ ─── */ +.review-form-block { + padding: 60px 0; + background: #fff; +} +.review-form-block__desc { + text-align: center; + color: var(--color-text-muted); + margin-top: 20px; + margin-bottom: 0; +} +.review-form-block__btn { + display: block; + margin: 0 auto; + padding: 16px 36px; + font-size: 16px; + font-weight: 600; + color: #fff; + background: var(--color-primary); + border: none; + border-radius: 12px; + cursor: pointer; + transition: transform .2s, box-shadow .2s; +} +.review-form-block__btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(232, 117, 58, 0.35); +} +.review-form-block__actions { + display: flex; + gap: 16px; + justify-content: center; + flex-wrap: wrap; +} +.review-form-block__btn--outline { + color: var(--color-primary); + background: transparent; + border: 2px solid var(--color-primary); + box-shadow: none; +} +.review-form-block__btn--outline:hover { + background: rgba(232, 117, 58, .08); + border-color: var(--color-primary-hover); + color: var(--color-primary-hover); + box-shadow: none; + transform: translateY(-2px); +} + +/* ─── Попап MyReviews: фикс огромного крестика ─── */ +.frame__popup .btn-close-frame__popup { + display: flex; + align-items: center; + justify-content: center; +} +.frame__popup .btn-close-frame__popup img { + width: 24px; + height: 24px; + object-fit: contain; +} + +/* ─── Попапы кнопок записи: тот же фикс ─── */ +.modal-request-form .btn-close-request-form { + display: flex; + align-items: center; + justify-content: center; +} +.modal-request-form .btn-close-request-form img { + width: 24px; + height: 24px; + object-fit: contain; +} + +/* ─── СЧЁТЧИК ОТЗЫВОВ (анимация) ─── */ +.counter-number { + display: inline-block; +} + +/* ─── STICKY CTA MOBILE ─── */ +.sticky-cta-mobile { + display: none; + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 1000; + padding: 12px 16px; + background: #fff; + box-shadow: 0 -2px 12px rgba(0,0,0,.1); +} +.sticky-cta-mobile--visible { + display: block; +} +.sticky-cta-mobile__btn { + display: block; + width: 100%; + padding: 14px; + text-align: center; + background: var(--color-primary); + color: #fff; + font-weight: 600; + font-size: 16px; + border: none; + border-radius: 12px; + cursor: pointer; +} + +/* ─── КОНТАКТЫ С КАРТОЙ ─── */ +.reviews-contact { + padding: 60px 0; +} +.reviews-contact__title { + font-family: var(--font-display, 'Oswald', sans-serif); + font-weight: 700; + color: var(--color-text); + font-size: var(--fs-h1, clamp(28px, 3.5vw, 40px)); + line-height: 1.2; + text-align: center; + padding-bottom: clamp(24px, 3vw, 32px); +} +.reviews-contact .contact-wrapper { + display: flex; + gap: 30px; +} +.reviews-contact .contact-content { + width: 40%; + display: flex; + flex-direction: column; + gap: 10px; +} +.reviews-contact .contact_subtitle { + margin-top: 10px; + font-size: 16px; + line-height: 1.2; + font-weight: 600; + font-family: var(--font-display, 'Oswald', sans-serif); + color: var(--color-text); +} +.reviews-contact .contact_tel { + color: var(--color-primary); + font-size: clamp(18px, 2.2vw, 22px); + line-height: 1; + font-weight: 600; + font-family: var(--font-body, sans-serif); +} +.reviews-contact .contact-map { + display: block; + border-radius: 30px; + overflow: hidden; + flex: 1; + height: 450px; +} +.reviews-contact .contact_social { + display: flex; + flex-wrap: wrap; + gap: 12px; +} +.reviews-contact .social_item { + display: inline-flex; + align-items: center; + text-decoration: none; + color: var(--color-primary); + font-family: var(--font-body, sans-serif); + font-size: clamp(16px, 2vw, 20px); + font-weight: 600; + line-height: 1.2; + transition: color var(--transition-fast), opacity var(--transition-fast); + position: relative; +} +.reviews-contact .social_item:hover { + color: var(--color-primary-hover); +} +.reviews-contact .social_item::after { + content: ''; + position: absolute; + bottom: -2px; + left: 0; + right: 0; + height: 2px; + background: var(--color-primary); + opacity: 0; + transition: opacity var(--transition-fast); +} +.reviews-contact .social_item:hover::after { + opacity: 0.4; +} +.reviews-contact .social_item + .social_item::before { + content: '·'; + margin-right: 12px; + color: var(--color-text-light); + font-weight: 400; +} + +/* ─── АНИМАЦИЯ ПОЯВЛЕНИЯ ─── */ +.reveal { + opacity: 0; + transform: translateY(24px); + transition: opacity .6s ease, transform .6s ease; +} +.reveal--visible { + opacity: 1; + transform: translateY(0); +} + +/* ─── АДАПТИВНОСТЬ ─── */ + +/* Сетка отзывов: 3 → 2 колонки */ +@media (max-width: 1200px) { + .reviews-cards .lw-grid--3 .lw-card { + width: calc(50% - 12px); + min-width: 280px; + } +} + +@media (max-width: 860px) { + .reviews-hero { + padding: 40px 0; + } + .reviews-grid { + padding: 20px 0 40px; + } + .reviews-intro, + .reviews-cta-text, + .video-reviews, + .review-form-block, + .cross-links, + .reviews-contact, + .final-cta { + padding: 40px 0; + } + .results, + .reviews-faq { + padding: 30px 0; + } + .reviews-hero__wrapper { + flex-direction: column; + } + .reviews-hero__image { + flex: none; + width: 100%; + max-width: 400px; + margin-left: auto; + margin-right: auto; + } + .reviews-hero__h1 { + font-size: 32px; + } + .final-cta__title { + font-size: 28px; + } + .cross-links__grid { + grid-template-columns: 1fr 1fr; + } +} + +/* Сетка отзывов: мобильный скролл */ +@media (max-width: 768px) { + /* ─── Hero: фото скрыто, текст на всю ширину с отступами ─── */ + .reviews-hero { + padding-left: 20px; + padding-right: 20px; + } + .reviews-hero__image { + display: none; + } + .reviews-hero__content { + max-width: none; + } + .reviews-hero__metrics { + flex-wrap: nowrap; + gap: 10px; + } + .reviews-intro__grid { + grid-template-columns: 1fr; + } + .reviews-hero__metric { + flex: 1; + min-width: 0; + padding: 12px 8px; + } + .reviews-hero__metric-number { + font-size: clamp(22px, 6vw, 28px); + } + .reviews-hero__metric-label { + font-size: 11px; + } + .reviews-hero__cta-btn { + width: 100%; + justify-content: center; + } + + /* ─── Карточка: position для absolute звёзд ─── */ + .reviews-cards .lw-grid--3 .lw-card { + position: relative; + } + + /* ─── Шапка: wrap чтобы бейдж уходил на новую строку ─── */ + .reviews-cards .lw-card > .lw-flex.lw-flex--row { + flex-wrap: wrap; + gap: 8px 12px; + align-items: flex-start; + } + + /* Аватар не сжимается */ + .reviews-cards .lw-card .lw-avatar { + flex-shrink: 0; + } + + /* Колонка имени: занимает остаток, не даём тексту залезть под звёзды */ + .reviews-cards .lw-card > .lw-flex.lw-flex--row > .lw-flex.lw-flex--col { + flex: 1; + min-width: 0; + padding-right: 90px; + } + + /* Преподаватель и ФИО — на разных строках */ + .reviews-cards .lw-card .review-card__teacher-link { + display: block; + } + + /* ─── Бейдж в колонке имени: убираем inline-переопределения с мобилки ─── */ + .reviews-cards .lw-card .lw-badge--verified { + margin-top: 6px !important; + margin-left: 0 !important; + } + + /* ─── Звёзды: абсолютно в правый верхний угол карточки ─── */ + .reviews-cards .lw-card .lw-stars { + position: absolute; + top: 24px; + right: 24px; + margin-top: 0; + } + + .reviews-cards .lw-scroll-x { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding-bottom: 8px; + } + .reviews-cards .lw-grid--3 { + display: flex; + gap: 16px; + overflow-x: auto; + scroll-snap-type: x mandatory; + flex-wrap: nowrap; + justify-content: flex-start; + padding-bottom: 4px; + } + .reviews-cards .lw-grid--3 .lw-card { + flex: 0 0 88vw; + scroll-snap-align: start; + } +} + +@media (max-width: 480px) { + .reviews-hero__h1 { + font-size: 26px; + } + .reviews-intro__lead { + font-size: 16px; + } + .reviews-intro__grid { + grid-template-columns: 1fr; + } + .reviews-intro__card { + padding: 16px; + } + .reviews-intro__card-text { + font-size: 14px; + } + .reviews-cards .lw-grid--3 .lw-card { + padding: 16px; + } + /* Звёзды: подстраиваем под меньший padding карточки */ + .reviews-cards .lw-card .lw-stars { + top: 16px; + right: 16px; + } + .cross-links__grid { + grid-template-columns: 1fr; + } + .final-cta__actions { + flex-direction: column; + } + .reviews-intro__info { + flex-direction: column; + align-items: center; + text-align: center; + padding: 16px 20px; + } + /* ─── FAQ: две колонки → одна колонка ─── */ + .reviews-faq-wrapper { + gap: 0; + flex-direction: column; + } + .reviews-faq-wrapper .accordion { + width: 100%; + gap: 0; + } + .reviews-faq-wrapper .accordion-last { + border-top: none; + } + .reviews-faq .box__accordion_label span { + font-size: 20px; + } + .box__accordion_label svg { + flex-shrink: 0; + } + /* ─── Контакты: колонки → стопкой, карта меньше ─── */ + .reviews-contact .contact-wrapper { + gap: 20px; + flex-direction: column-reverse; + } + .reviews-contact .contact-map { + width: 100%; + height: 250px; + } + #ya-map-reviews { + height: 250px !important; + } + .reviews-contact .contact-content { + width: 100%; + } + .reviews-contact .contact_tel { + font-size: 18px; + } +} + +/* ─── ПАГИНАЦИЯ ─── */ +.reviews-pagination { + text-align: center; + margin-top: 40px; +} +.reviews-pagination ul.page-numbers, +.reviews-pagination ol.page-numbers { + margin: 0; + padding: 0; + list-style: none; + display: inline-flex; + flex-wrap: wrap; + gap: 6px; + align-items: center; + border: none; + background: none; +} +.reviews-pagination li { + margin: 0; + padding: 0; + display: inline-block; +} +.reviews-pagination a.page-numbers, +.reviews-pagination span.page-numbers:not(.dots) { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 40px; + height: 40px; + padding: 0 10px; + border-radius: 8px; + font-size: 14px; + font-weight: 500; + text-decoration: none; + border: 1px solid rgba(0,0,0,0.1); + color: var(--color-text-muted); + background: #fff; + transition: all .2s; + box-sizing: border-box; + line-height: 1; +} +.reviews-pagination span.page-numbers.current { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); +} +.reviews-pagination a.page-numbers:hover { + border-color: var(--color-primary); + color: var(--color-primary); + background: rgba(232, 117, 58, 0.06); +} +.reviews-pagination a.page-numbers.prev, +.reviews-pagination a.page-numbers.next { + width: auto; + padding: 0 14px; + font-size: 13px; +} + +/* ─── СБРОС СТАНДАРТНЫХ СТИЛЕЙ ТЕМЫ ─── */ +.page-reviews { + padding-bottom: 0; +} + +/* ─── DESKTOP: скрываем карточки после первого батча ─── */ +@media (min-width: 769px) { + .lw-card[data-batch]:not([data-batch="1"]) { + display: none; + } +} + +/* ─── MOBILE: все карточки видны в скролле ─── */ +@media (max-width: 768px) { + .lw-card[data-batch]:not([data-batch="1"]) { + display: flex; + } +} + +/* ─── КНОПКА "ПОКАЗАТЬ ЕЩЁ" ─── */ +.reviews-loadmore { + text-align: center; + margin-top: 32px; +} +.reviews-loadmore__btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 14px 36px; + font-size: 16px; + font-weight: 600; + color: var(--accent); + background: var(--accent-light); + border: 2px solid var(--accent); + border-radius: 12px; + cursor: pointer; + transition: background var(--transition-fast), transform var(--transition-fast); +} +.reviews-loadmore__btn:hover { + background: rgba(124, 58, 237, 0.15); + transform: translateY(-2px); +} +.reviews-loadmore__btn:active { + transform: translateY(0); +} +.reviews-loadmore__btn:disabled { + opacity: 0.5; + cursor: default; + transform: none; +} +@media (max-width: 768px) { + .reviews-loadmore { + display: none; + } +} + +/* ─── ВНЕШНИЕ ПЛОЩАДКИ (E-E-A-T) ─── */ +.reviews-ext-platforms { + padding: 40px 0; + background: #fff; +} +.reviews-ext-platforms__title { + text-align: center; + font-family: 'Oswald', sans-serif; + font-size: clamp(22px, 2.6vw, 30px); + font-weight: 500; + color: var(--color-text); + margin-bottom: 10px; +} +.reviews-ext-platforms__desc { + text-align: center; + font-size: 15px; + color: var(--color-text-muted); + margin-bottom: 28px; +} +.reviews-ext-platforms__grid { + display: flex; + flex-wrap: wrap; + gap: 16px; + justify-content: center; +} +.reviews-ext-platforms__card { + display: inline-flex; + align-items: center; + gap: 10px; + padding: 14px 24px; + background: #f8fafc; + border: 1px solid #e2e8f0; + border-radius: 12px; + text-decoration: none; + color: var(--color-text); + font-weight: 500; + font-size: 15px; + transition: all var(--transition-fast); +} +.reviews-ext-platforms__card:hover { + border-color: var(--color-primary); + color: var(--color-primary); + background: rgba(232, 117, 58, 0.04); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.08); +} +.reviews-ext-platforms__icon { + color: var(--color-primary); + flex-shrink: 0; + display: flex; +} +.reviews-ext-platforms__arrow { + color: var(--color-text-light); + font-size: 14px; + transition: transform var(--transition-fast); +} +.reviews-ext-platforms__card:hover .reviews-ext-platforms__arrow { + transform: translateX(4px); + color: var(--color-primary); +} +@media (max-width: 480px) { + .reviews-ext-platforms__grid { + flex-direction: column; + align-items: center; + } + .reviews-ext-platforms__card { + width: 100%; + max-width: 340px; + justify-content: center; + } +} + +/* ─── ДОВЕРИТЕЛЬНЫЙ БЛОК ─── */ +.reviews-trust { + padding: 32px 0 8px; + background: #fff; +} +.reviews-trust__content { + max-width: 800px; + margin: 0 auto; +} +.reviews-trust__text { + font-size: 15px; + line-height: 1.65; + color: var(--color-text-muted); + text-align: center; + padding: 20px 24px; + border-radius: 12px; + background: #f8f9fa; + border-left: 4px solid var(--color-secondary); +} + +/* ─── ЛОКАЛЬНЫЙ БЛОК «Почему родители Щёлково выбирают Декарт» ─── */ +.reviews-local { + padding: 60px 0; + background: #f8f9fa; +} +.reviews-local__title { + text-align: center; + font-family: 'Oswald', sans-serif; + font-size: clamp(22px, 2.6vw, 30px); + font-weight: 500; + color: var(--color-text); + margin-bottom: 36px; +} +.reviews-local__list { + list-style: none; + counter-reset: local-counter; + max-width: 800px; + margin: 0 auto; + padding: 0; + display: grid; + gap: 16px; +} +.reviews-local__item { + counter-increment: local-counter; + position: relative; + padding: 18px 18px 18px 56px; + background: #fff; + border-radius: 14px; + box-shadow: 0 1px 8px rgba(0,0,0,0.04); + font-size: 14.5px; + line-height: 1.65; + color: var(--color-text); +} +.reviews-local__item::before { + content: counter(local-counter); + position: absolute; + left: 16px; + top: 18px; + width: 28px; + height: 28px; + border-radius: 50%; + background: var(--color-primary); + color: #fff; + font-size: 14px; + font-weight: 600; + display: flex; + align-items: center; + justify-content: center; +} +.reviews-local__item strong { + color: var(--color-text); +} + +/* ─── РЕЙТИНГ-БЕЙДЖ В HERO ─── */ +.reviews-hero__rating-badge { + display: flex; + align-items: center; + gap: 10px; + margin-top: 8px; + flex-wrap: wrap; +} +.reviews-hero__rating-stars { + color: #f59e0b; + font-size: 18px; + letter-spacing: 2px; +} +.reviews-hero__rating-text { + font-size: 13px; + color: rgba(255,255,255,0.65); +} +.reviews-hero__phone { + margin-top: 10px; + font-size: 13px; + color: rgba(255,255,255,0.55); +} +.reviews-hero__phone a { + color: var(--color-accent); + text-decoration: underline; + font-weight: 500; +} + +/* ─── MID-CTA ─── */ +.reviews-mid-cta { + margin-top: -20px; + margin-bottom: 20px; +} +.reviews-mid-cta__inner { + background: linear-gradient(135deg, var(--color-text) 0%, #2a4042 100%); + border-radius: 16px; + padding: 28px 32px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; +} +.reviews-mid-cta__text { + color: #fff; + font-size: 16px; + font-weight: 500; + margin: 0; + line-height: 1.4; +} +.reviews-mid-cta__inner .btn-primary { + flex-shrink: 0; +} + +/* ─── CTA ПЕРЕД FAQ ─── */ +.reviews-faq-cta { + margin-top: -20px; + margin-bottom: 20px; +} +.reviews-faq-cta__inner { + background: #fff; + border: 1px solid #e2e8f0; + border-radius: 14px; + padding: 20px 24px; + text-align: center; +} +.reviews-faq-cta__text { + font-size: 15px; + color: var(--color-text); + margin: 0 0 4px; +} +.reviews-faq-cta__phone { + color: var(--color-primary); + font-weight: 600; + font-size: 16px; + text-decoration: none; +} +.reviews-faq-cta__phone:hover { + text-decoration: underline; +} +.reviews-faq-cta__subtext { + font-size: 13px; + color: var(--color-text-light); + margin: 0; +} + +@media (max-width: 768px) { + .reviews-local { + padding: 40px 0; + } + .reviews-local__list { + gap: 12px; + } + .reviews-local__item { + padding: 14px 14px 14px 50px; + font-size: 14px; + } + .reviews-mid-cta__inner { + flex-direction: column; + text-align: center; + padding: 20px; + } + .reviews-trust__text { + font-size: 14px; + padding: 16px; + } + .reviews-hero__rating-badge { + flex-direction: column; + align-items: flex-start; + gap: 4px; + } +} + +/* ─── ФОРМА ЗАПИСИ (Bitrix24 модалка) ─── */ +.review-form-block__title { + font-family: 'Oswald', sans-serif; + font-size: clamp(22px, 2.6vw, 30px); + text-align: center; + margin-bottom: 12px; + color: var(--color-text); +} +.review-form-block__cols { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 40px; + max-width: 860px; + margin: 0 auto 24px; + align-items: start; +} +.review-form-block__form-col { + background: #fff; + border: 1px solid #e2e8f0; + border-radius: 16px; + padding: 32px 28px; + text-align: center; +} +.review-form__lead { + font-size: 15px; + line-height: 1.55; + color: var(--color-text-muted); + margin: 0 0 24px; +} +.review-form__submit { + width: 100%; + padding: 14px 24px; + font-size: 16px; + cursor: pointer; +} +.review-form__footnote { + font-size: 13px; + color: var(--color-text-light); + text-align: center; + margin: 16px 0 0; +} + +/* ─── БЛОК ПРЕИМУЩЕСТВ У ФОРМЫ ─── */ +.review-form-block__benefits-col { + padding-top: 12px; +} +.review-form-block__benefits-title { + font-size: 16px; + font-weight: 600; + color: var(--color-text); + margin-bottom: 16px; +} +.review-form-block__benefits { + list-style: none; + padding: 0; + margin: 0; + display: grid; + gap: 12px; +} +.review-form-block__benefit { + display: flex; + align-items: flex-start; + gap: 10px; + font-size: 14px; + color: var(--color-text); + line-height: 1.5; +} +.review-form-block__benefit-icon { + flex-shrink: 0; + width: 22px; + height: 22px; + border-radius: 50%; + background: var(--color-secondary); + color: #fff; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + font-weight: 700; + margin-top: 1px; +} + +/* ─── ТРИГГЕРЫ СРОЧНОСТИ ─── */ +.final-cta__triggers { + display: flex; + flex-direction: column; + gap: 12px; + max-width: 540px; + margin: 0 auto 28px; +} +.final-cta__trigger { + background: #fff; + border: none; + border-radius: 12px; + padding: 16px 20px; + display: flex; + align-items: center; + gap: 14px; + font-size: 15px; + line-height: 1.4; + color: #222; + box-shadow: 0 2px 12px rgba(0,0,0,0.08); + text-align: left; + transition: transform .2s, box-shadow .2s; +} +.final-cta__trigger:hover { + transform: translateY(-1px); + box-shadow: 0 4px 20px rgba(0,0,0,0.12); +} +.final-cta__trigger-icon { + font-size: 22px; + flex-shrink: 0; + width: 32px; + text-align: center; +} +.final-cta__trigger strong { + color: var(--color-primary); + font-weight: 600; +} + +@media (max-width: 768px) { + .review-form-block__cols { + grid-template-columns: 1fr; + gap: 24px; + } + .review-form-block__form-col { + padding: 24px 20px; + } + .final-cta__triggers { + margin-bottom: 16px; + } + .final-cta__trigger { + font-size: 13px; + padding: 10px 14px; + } +} + +/* ─── PREFERS-REDUCED-MOTION ─── */ +@media (prefers-reduced-motion: reduce) { + .reveal, + .reveal--visible, + .lw-card, + .reviews-hero__metric, + .reviews-hero__cta-btn, + .results__card, + .reviews-photos__item, + .video-reviews__card, + .cross-links__card, + .review-form-block__btn, + .reviews-ext-platforms__card, + .reviews-loadmore__btn, + .social_item, + .reviews-hero__image { + transition: none !important; + transform: none !important; + animation: none !important; + } + .reveal { + opacity: 1 !important; + transform: none !important; + } +} + + diff --git a/wp-content/themes/dekart/assets/js/reviews-page.js b/wp-content/themes/dekart/assets/js/reviews-page.js new file mode 100644 index 0000000..d98984c --- /dev/null +++ b/wp-content/themes/dekart/assets/js/reviews-page.js @@ -0,0 +1,222 @@ +/** + * reviews-page.js — интерактив для page-reviews.php + * Анимации, фильтры, sticky CTA, FAQ, пагинация + * + * @package Dekart + */ + +document.addEventListener('DOMContentLoaded', function () { + 'use strict'; + + // ─────────────────────────────────────────────── + // 1. АНИМАЦИЯ ПОЯВЛЕНИЯ (Intersection Observer) + // ─────────────────────────────────────────────── + const revealElements = document.querySelectorAll('.reveal'); + if (revealElements.length && 'IntersectionObserver' in window) { + const observer = new IntersectionObserver( + function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + entry.target.classList.add('reveal--visible'); + observer.unobserve(entry.target); + } + }); + }, + { threshold: 0.1 } + ); + revealElements.forEach(function (el) { + observer.observe(el); + }); + } else { + // Fallback: показываем всё сразу + revealElements.forEach(function (el) { + el.classList.add('reveal--visible'); + }); + } + + // ─────────────────────────────────────────────── + // 2. КНОПКИ "ЧИТАТЬ ЕЩЁ" + // ─────────────────────────────────────────────── + document.querySelectorAll('.review-card__btn-more').forEach(function (btn) { + btn.addEventListener('click', function () { + const textBlock = this.parentNode.querySelector('.lw-card__text'); + if (textBlock) { + textBlock.classList.toggle('review-card__text--expanded'); + this.textContent = textBlock.classList.contains('review-card__text--expanded') + ? 'Свернуть' + : 'Читать ещё'; + } + }); + }); + + // ─────────────────────────────────────────────── + // 3. КНОПКА "ПОКАЗАТЬ ЕЩЁ" (десктоп) + // ─────────────────────────────────────────────── + const loadMoreBtn = document.getElementById('reviews-loadmore'); + if (loadMoreBtn) { + let nextBatch = 2; + const btn = loadMoreBtn.querySelector('.reviews-loadmore__btn'); + if (btn) { + btn.addEventListener('click', function () { + const cards = document.querySelectorAll('.lw-card[data-batch="' + nextBatch + '"]'); + if (cards.length) { + cards.forEach(function (card) { + card.style.display = 'flex'; + }); + nextBatch++; + // Если следующих батчей нет — прячем кнопку + const remaining = document.querySelectorAll('.lw-card[data-batch="' + nextBatch + '"]'); + if (!remaining.length) { + loadMoreBtn.style.display = 'none'; + } + } + }); + } + } + + // ─────────────────────────────────────────────── + // 4. FAQ Accordion — keyboard + ARIA + // Глобальный click handler в add.js обрабатывает + // .box__accordion_label, синхронизируем aria-expanded + // ─────────────────────────────────────────────── + document.querySelectorAll('.box__accordion_label').forEach(function (label) { + label.addEventListener('keydown', function (e) { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + this.click(); + } + }); + // При клике (из add.js) синхронизируем aria-expanded + label.addEventListener('click', function () { + const content = document.getElementById(this.getAttribute('aria-controls')); + const isOpen = content && content.style.maxHeight && content.style.maxHeight !== '0px'; + this.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); + }); + }); + + // ─────────────────────────────────────────────── + // 5. СЧЁТЧИК (CountUp) для цифр доверия + // ─────────────────────────────────────────────── + function animateCounter(el) { + const target = parseInt(el.getAttribute('data-target-value'), 10) || + parseInt(el.getAttribute('data-target'), 10); + if (!target) return; + let current = 0; + const step = Math.ceil(target / 60); // 60 кадров ~ 1 сек + const timer = setInterval(function () { + current += step; + if (current >= target) { + current = target; + clearInterval(timer); + } + el.textContent = current.toLocaleString('ru-RU'); + }, 16); + } + + document.querySelectorAll('.counter-number').forEach(function (counter) { + if ('IntersectionObserver' in window) { + const observer = new IntersectionObserver( + function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + animateCounter(entry.target); + observer.unobserve(entry.target); + } + }); + }, + { threshold: 0.5 } + ); + observer.observe(counter); + } else { + animateCounter(counter); + } + }); + + // ─────────────────────────────────────────────── + // 6. STICKY CTA (мобильные) — троттлинг скролла + // ─────────────────────────────────────────────── + const stickyCta = document.querySelector('.sticky-cta-mobile'); + if (stickyCta) { + const heroSection = document.querySelector('.reviews-hero'); + if (heroSection) { + const heroBottom = heroSection.offsetTop + heroSection.offsetHeight; + let ticking = false; + window.addEventListener('scroll', function () { + if (!ticking) { + window.requestAnimationFrame(function () { + if (window.scrollY > heroBottom) { + stickyCta.classList.add('sticky-cta-mobile--visible'); + } else { + stickyCta.classList.remove('sticky-cta-mobile--visible'); + } + ticking = false; + }); + ticking = true; + } + }); + } + } + + // ─────────────────────────────────────────────── + // 7. POPUP ФОРМЫ ОТЗЫВА (iframe) + // ─────────────────────────────────────────────── + const formBtn = document.querySelector('.review-form-block__btn'); + if (formBtn) { + formBtn.addEventListener('click', function () { + const popup = document.querySelector('.frame__popup'); + const iframe = popup ? popup.querySelector('.frame_reviews') : null; + const frameUrl = popup ? popup.getAttribute('data-frame-url') : ''; + if (popup && iframe && frameUrl) { + iframe.src = frameUrl; + popup.style.display = 'flex'; + } + }); + } + + const closeBtn = document.querySelector('.btn-close-frame__popup'); + if (closeBtn) { + closeBtn.addEventListener('click', function () { + const popup = this.parentNode.parentNode; + popup.style.display = 'none'; + const iframe = popup.querySelector('.frame_reviews'); + if (iframe) iframe.src = ''; + }); + } + + // ─────────────────────────────────────────────── + // 8. ЦЕЛИ ЯНДЕКС.МЕТРИКИ + // ─────────────────────────────────────────────── + function reachGoal(name) { + if (typeof yaCounter99835482 !== 'undefined') { + try { + yaCounter99835482.reachGoal(name); + } catch (e) { + if (window.console) { + console.warn('Metrika reachGoal error:', e); + } + } + } + } + + // Клики по всем CTA-кнопкам + document.querySelectorAll('.js-reviews-cta').forEach(function (btn) { + btn.addEventListener('click', function () { + const goal = this.getAttribute('data-goal') || 'cta_otzyvy_click'; + reachGoal(goal); + }); + }); + + // Клик по телефону + document.querySelectorAll('a[href^="tel:"]').forEach(function (link) { + link.addEventListener('click', function () { + reachGoal('phone_click_otzyvy'); + }); + }); + + // Клик по WhatsApp/Telegram + document.querySelectorAll('a[href*="wa.me"], a[href*="t.me"]').forEach(function (link) { + link.addEventListener('click', function () { + reachGoal('messenger_click_otzyvy'); + }); + }); +}); diff --git a/wp-content/themes/dekart/functions.php b/wp-content/themes/dekart/functions.php index 44bdfbb..aadb289 100644 --- a/wp-content/themes/dekart/functions.php +++ b/wp-content/themes/dekart/functions.php @@ -240,35 +240,62 @@ function add_carbon() { ->add_fields( array( Field::make( 'image', 'img', 'Фотография:' ), )), + )) + ->add_tab('SEO и микроразметка', array( + Field::make( 'html', 'schema_branch_tab_desc', '' ) + ->set_html( '

Поля для JSON-LD микроразметки Schema.org филиала. Если поле пусто — свойство не добавляется в граф.

' ), + Field::make( 'text', 'schema_legal_name', 'Юридическое название (legalName)' ) + ->set_width( 50 ) + ->set_help_text( 'Полное юр. название организации. Например: "ИП Иванов Иван Иванович"' ), + Field::make( 'text', 'schema_postal_code', 'Почтовый индекс (postalCode)' ) + ->set_width( 50 ) + ->set_help_text( 'Индекс для address.postalCode в микроразметке.' ), + Field::make( 'text', 'schema_founded', 'Год основания (foundingDate)' ) + ->set_width( 50 ) + ->set_help_text( 'Год или полная дата: "2015" или "2015-09-01".' ), + Field::make( 'text', 'schema_map_url', 'Ссылка на карту (hasMap)' ) + ->set_width( 50 ) + ->set_help_text( 'Полная ссылка на Яндекс.Карты или Google Maps.' ), + Field::make( 'complex', 'schema_hours', 'Часы работы (openingHoursSpecification)' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Режим работы на каждый день недели.' ) + ->add_fields( array( + Field::make( 'select', 'day_of_week', 'День недели' ) + ->set_width( 30 ) + ->set_options( array( + 'Monday' => 'Понедельник', + 'Tuesday' => 'Вторник', + 'Wednesday' => 'Среда', + 'Thursday' => 'Четверг', + 'Friday' => 'Пятница', + 'Saturday' => 'Суббота', + 'Sunday' => 'Воскресенье', + ) ), + Field::make( 'time', 'opens', 'Открытие' ) + ->set_width( 25 ), + Field::make( 'time', 'closes', 'Закрытие' ) + ->set_width( 25 ), + Field::make( 'checkbox', 'day_off', 'Выходной' ) + ->set_width( 20 ) + ->set_help_text( 'Отметьте, если в этот день не работаем.' ), + ) ), + Field::make( 'complex', 'schema_social', 'Социальные сети (sameAs)' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Ссылки на соцсети профилей для sameAs[].' ) + ->add_fields( array( + Field::make( 'text', 'platform', 'Платформа' ) + ->set_width( 30 ) + ->set_help_text( 'Например: VK, Telegram, YouTube' ), + Field::make( 'text', 'url', 'Ссылка' ) + ->set_width( 70 ) + ->set_help_text( 'Полный URL профиля.' ), + ) ), + Field::make( 'media_gallery', 'schema_photos', 'Фотографии филиала (image[])' ) + ->set_help_text( 'Выберите фотографии интерьера/экстерьера для image[].' ), )); - // ==================================================== - // Доп поля для всех страниц - // ==================================================== - Container::make('post_meta', 'Дополнительные поля') - ->where('post_type', '=', 'page') - ->where('post_id', '!=', 64) - ->add_fields(array( - Field::make( 'image', 'banner_img_desktop', 'Изображение для баннера (десктопная версия)' ) - ->help_text( 'Размер изображения (желательно) 1295px на 454px' ) - ->set_width( 15 ), - Field::make( 'image', 'banner_img_mobile', 'Изображение для баннера (мобильная версия)' ) - ->help_text( 'Размер изображения (желательно) 450px на 225px' ) - ->set_width( 15 ), - Field::make( 'text', 'banner_h1', 'текст для H1' ) - ->set_width( 100 ), - Field::make( 'text', 'banner_text', 'Дополнительный текст под H1' ) - ->set_width( 100 ), - Field::make( 'complex', 'page_breadcrumbs', 'Хлебные крошки' ) - ->set_layout( 'tabbed-horizontal' ) - ->add_fields( array( - Field::make( 'text', 'breadcrumbs_name', 'Название крошки:' ) - ->set_width( 50 ), - Field::make( 'text', 'breadcrumbs_link', 'Ссылка крошки:' ) - ->set_width( 50 ) - ->set_default_value('#'), - )), - )); + // (пусто — старые поля banner_img_desktop, banner_img_mobile, + // banner_h1, banner_text, page_breadcrumbs удалены 31 мая 2026) // ==================================================== // Доп поля для категории Курсов @@ -473,6 +500,212 @@ function add_carbon() { )), )); + // ==================================================== + // Доп поля для страницы "Подготовка к школе (Bento 2026)" + // ==================================================== + Container::make('post_meta', 'Настройки Подготовки к школе') + ->where('post_template', '=', 'page-podgotovka-k-shkole.php') + ->add_tab('🖼️ Герой (баннер)', array( + Field::make( 'html', 'pksh_hero_tab_desc', '' ) + ->set_html( '

Секция: .hero-pksh. Первый экран страницы подготовки к школе.

' ), + Field::make( 'image', 'banner_image', 'Фото баннера' ) + ->set_width( 50 ) + ->set_help_text( 'Рекомендуемый размер: 689×689 px, квадратное. Если не указано — используется фото по умолчанию.' ), + Field::make( 'text', 'banner_h1', 'Заголовок H1' ) + ->set_width( 50 ) + ->set_default_value( 'Ваш ребёнок готов к первому классу? Научим читать, считать и писать за 4 месяца — без слёз и стресса' ) + ->set_help_text( 'Главный заголовок на первом экране.' ), + Field::make( 'textarea', 'banner_subtitle', 'Подзаголовок' ) + ->set_width( 50 ) + ->set_default_value( 'Первое занятие — бесплатно. Результат через 3 недели — или вернём деньги' ) + ->set_help_text( 'Текст под заголовком. Опционально.' ), + Field::make( 'text', 'banner_scarcity', 'Текст дефицита (срочность)' ) + ->set_width( 50 ) + ->set_default_value( '🔥 Осталось 2 места из 8 в группе 5–6 лет. Стартуем 1 июня' ) + ->set_help_text( 'Можно использовать HTML-теги: <strong>, <br>. Текст о срочности/дефиците мест под кнопкой.' ), + )) + ->add_tab('📊 Соц.доказательство', array( + Field::make( 'html', 'pksh_social_tab_desc', '' ) + ->set_html( '

Секция: .social-counters. Блок цифр социального доказательства (4 карточки). Иконки заданы в шаблоне, здесь только текст.

' ), + Field::make( 'complex', 'pksh_social_counters', 'Показатели' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте до 4 показателей. Порядок = порядок вывода. Иконки не редактируются.' ) + ->add_fields( array( + Field::make( 'text', 'counter_number', 'Число' ) + ->set_width( 30 ) + ->set_help_text( 'Например: 500+, 12, 4.8, 20+' ), + Field::make( 'text', 'counter_label', 'Подпись' ) + ->set_width( 70 ) + ->set_help_text( 'Например: выпускников в топ-школах' ), + )), + )) + ->add_tab('Битрикс24', array( + Field::make( 'textarea', 'pksh_bitrix_script', 'Скрипт формы Битрикс24' ) + ->set_help_text( 'Вставьте полный JS-код интеграции с CRM-формой Битрикс24. Выводится в блоке Final CTA на странице подготовки к школе.' ), + )) + ->add_tab('⭐ Отзывы', array( + Field::make( 'html', 'pksh_reviews_tab_desc', '' ) + ->set_html( '

Секция: .pksh-reviews. Отзывы родителей на странице подготовки к школе.

' ), + Field::make( 'complex', 'pksh_reviews_list', 'Отзывы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте отзывы родителей. Показываются на странице подготовки к школе.' ) + ->add_fields( array( + Field::make( 'image', 'review_avatar', 'Аватар' ) + ->set_width( 15 ) + ->set_help_text( 'Опционально. Если не указано — генерируется из имени.' ), + Field::make( 'text', 'review_author', 'Имя автора' ) + ->set_width( 25 ), + Field::make( 'text', 'review_rating', 'Оценка (1–5)' ) + ->set_width( 10 ) + ->set_attribute( 'type', 'number' ), + Field::make( 'date', 'review_date', 'Дата отзыва' ) + ->set_width( 15 ) + ->set_help_text( 'Для Schema.org Review.datePublished.' ), + Field::make( 'textarea', 'review_text', 'Текст отзыва' ) + ->set_width( 35 ), + )), + )) + ->add_tab('❓ FAQ', array( + Field::make( 'html', 'pksh_faq_tab_desc', '' ) + ->set_html( '

Секция: #pksh-faq. Вопросы и ответы в стиле лагеря, две колонки.

' ), + Field::make( 'complex', 'pksh_faq_items', 'Вопросы и ответы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте вопросы и ответы. Показываются в секции FAQ на странице подготовки к школе.' ) + ->add_fields( array( + Field::make( 'textarea', 'faq_question', 'Вопрос' ) + ->set_width( 30 ), + Field::make( 'textarea', 'faq_answer', 'Ответ' ) + ->set_width( 70 ), + )), + )) + ->add_tab('👨‍🏫 Преподаватели', array( + Field::make( 'html', 'pksh_teachers_tab_desc', '' ) + ->set_html( '

Секция: #teachers. Карточки преподавателей в стиле лагеря.

' ), + Field::make( 'complex', 'pksh_teachers', 'Преподаватели' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте преподавателей. Выводятся на странице подготовки к школе в секции Преподаватели.' ) + ->add_fields( array( + Field::make( 'text', 'teacher_name', 'ФИО' ) + ->set_width( 40 ), + Field::make( 'image', 'teacher_photo', 'Фото' ) + ->set_help_text( 'Оптимально: 240×240 px, квадратное.' ) + ->set_width( 30 ), + Field::make( 'text', 'teacher_subject', 'Предмет / должность' ) + ->set_width( 30 ), + Field::make( 'textarea', 'teacher_about', 'О педагоге' ) + ->set_width( 100 ), + )), + )) + // ==================================================== + // Вкладка: Программы подготовки к школе + // ==================================================== + ->add_tab('📚 Программы', array( + Field::make( 'html', 'pksh_programs_tab_desc', '' ) + ->set_html( '

Секция: #programs. Карточки программ подготовки к школе. Каждая карточка — отдельная запись.

' ), + Field::make( 'complex', 'pksh_programs', 'Программы подготовки' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте программы подготовки к школе. Каждая — отдельная карточка.' ) + ->add_fields( array( + Field::make( 'text', 'program_icon', 'Иконка (emoji)' ) + ->set_width( 20 ) + ->set_default_value( '🎓' ), + Field::make( 'text', 'program_title', 'Название программы' ) + ->set_width( 80 ), + Field::make( 'text', 'program_intensity', 'Интенсивность' ) + ->set_width( 50 ) + ->set_help_text( 'Например: 2 раза в неделю' ), + Field::make( 'textarea', 'program_schedule', 'Расписание' ) + ->set_width( 50 ) + ->set_help_text( 'Каждая строка — один вариант расписания' ), + Field::make( 'text', 'program_duration', 'Длительность занятия' ) + ->set_width( 30 ) + ->set_default_value( '90 мин' ), + Field::make( 'textarea', 'program_lesson_structure', 'Структура занятия (timeline)' ) + ->set_width( 70 ) + ->set_help_text( 'Каждая строка: время 🔤 Название. Например: "15 мин 🧠 Нейрогимнастика"' ), + Field::make( 'textarea', 'program_includes', 'Программа включает' ) + ->set_width( 100 ) + ->set_help_text( 'Каждая строка — пункт списка' ), + Field::make( 'text', 'program_price_subscription', 'Цена абонемента' ) + ->set_width( 40 ) + ->set_default_value( '7 500 ₽' ) + ->set_help_text( 'Например: 7 500 ₽' ), + Field::make( 'text', 'program_price_single', 'Цена разового занятия' ) + ->set_width( 40 ) + ->set_default_value( '1 000 ₽' ) + ->set_help_text( 'Например: 1 000 ₽' ), + Field::make( 'text', 'program_time_required', 'Длительность курса (timeRequired)' ) + ->set_width( 30 ) + ->set_help_text( 'Общая длительность курса. Например: "4 месяца", "P4M"' ), + Field::make( 'text', 'program_repeat_frequency', 'Частота занятий (ISO 8601)' ) + ->set_width( 30 ) + ->set_help_text( + 'Для Schema.org Schedule.repeatFrequency. ' + . 'Пример: P1W (раз в неделю), P4D (дважды в неделю). ' + . 'program_intensity остаётся для отображения на сайте.' + ) + ->set_attribute( 'placeholder', 'P1W' ), + Field::make( 'text', 'program_workload', 'Нагрузка (courseWorkload)' ) + ->set_width( 70 ) + ->set_help_text( 'Например: "2 занятия в неделю по 90 минут"' ), + Field::make( 'date', 'program_start_date', 'Дата старта программы' ) + ->set_width( 33 ), + Field::make( 'date', 'program_end_date', 'Дата окончания' ) + ->set_width( 33 ), + Field::make( 'date', 'program_price_valid', 'Цена действительна до' ) + ->set_width( 34 ) + ->set_help_text( 'Дата, до которой актуальна указанная цена.' ), + Field::make( 'text', 'program_button_text', 'Текст кнопки' ) + ->set_width( 40 ) + ->set_default_value( 'Записаться' ), + Field::make( 'text', 'program_button_url', 'Ссылка кнопки' ) + ->set_width( 60 ) + ->set_default_value( '/zapis/' ), + )), + )) + // ==================================================== + // Вкладка: JSON-LD Schema (данные для микроразметки) + // ==================================================== + ->add_tab('🧠 JSON-LD (схема)', array( + Field::make( 'html', 'pksh_schema_tab_desc', '' ) + ->set_html( '

Поля для JSON-LD микроразметки Schema.org. Заполняются опционально — если поле пусто, свойство не добавляется в граф.

' ), + Field::make( 'textarea', 'pksh_description', 'Описание курса (для микроразметки)' ) + ->set_help_text( + 'Подробное описание программы для Schema.org Course.description. ' + . 'Если заполнено — заменяет banner_subtitle в микроразметке. ' + . 'Рекомендуется минимум 150 символов. НЕ влияет на отображение страницы.' + ) + ->set_rows( 4 ) + ->set_attribute( 'placeholder', 'Комплексная программа подготовки детей 5–7 лет к первому классу...' ), + Field::make( 'text', 'pksh_level', 'Уровень образования (educationalLevel)' ) + ->set_width( 50 ) + ->set_help_text( 'Например: "дошкольное образование" или "5-7 лет"' ), + Field::make( 'text', 'pksh_age', 'Возраст детей' ) + ->set_width( 50 ) + ->set_help_text( 'Например: "5–7 лет"' ), + Field::make( 'text', 'pksh_audience', 'Целевая аудитория (audience)' ) + ->set_help_text( 'Например: "Дети 5–7 лет, будущие первоклассники"' ), + Field::make( 'select', 'pksh_course_mode', 'Формат обучения (courseMode)' ) + ->set_width( 50 ) + ->set_help_text( 'Формат занятий для Schema.org CourseInstance.courseMode.' ) + ->add_options( array( + '' => '— выберите —', + 'Onsite' => 'Очно (в центре)', + 'Online' => 'Онлайн', + 'Blended' => 'Смешанный (очно + онлайн)', + ) ), + + Field::make( 'complex', 'pksh_skills', 'Чему учат на курсе' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Навыки, которые освоит ребёнок. Каждая запись — отдельный навык (дисциплина).' ) + ->add_fields( array( + Field::make( 'text', 'skill', 'Навык / дисциплина' ) + ->set_width( 100 ) + ->set_attribute( 'placeholder', 'Чтение, Счёт до 100, Письмо печатными буквами' ) + ->set_help_text( 'Например: "Чтение", "Счёт до 100", "Письмо печатными буквами"' ), + )), + )); + // ==================================================== // Уникальное имя контейнера Продлёнки // ==================================================== @@ -741,6 +974,245 @@ function add_carbon() { Field::make( 'textarea', 'camp_bitrix_script', 'Скрипт формы Битрикс24' ) ->set_help_text( 'Вставьте полный JS-код интеграции с CRM-формой Битрикс24. Выводится в модальном окне заявки.' ), )); + + // ════════════════════════════════════════════════════════════ + // СТРАНИЦА ОТЗЫВОВ (page-reviews.php) + // ════════════════════════════════════════════════════════════ + Container::make('post_meta', '⭐ Настройки страницы Отзывы') + ->where('post_template', '=', 'page-reviews.php') + ->add_tab('🧑‍🏫 Hero (первый экран)', array( + Field::make( 'html', 'reviews_hero_tab_desc', '' ) + ->set_html( '

H1 и подзаголовок — статические в шаблоне. Здесь только метрики и CTA.

' ), + Field::make( 'separator', 'reviews_metric_sep', 'Метрики доверия' ), + Field::make( 'text', 'reviews_hero_metric_1_number', 'Метрика 1 — число' ) + ->set_default_value( '500+' ) + ->set_width( 30 ) + ->set_help_text( 'Крупная цифра, которая сразу привлекает внимание. Выбирайте самую сильную — ту, что впечатляет больше всего: количество учеников, лет на рынке, % поступления. Добавьте + или % для эффекта. Примеры: «500+», «98%», «15».' ), + Field::make( 'text', 'reviews_hero_metric_1_label', 'Метрика 1 — подпись' ) + ->set_default_value( 'счастливых семей' ) + ->set_width( 70 ) + ->set_help_text( 'Подпись к цифре из левого поля. Объясняет, что именно посчитано. Совет: используйте родительный падеж — звучит весомее. Примеры: «счастливых семей», «выпускников», «учеников». Не пишите просто «семей» — добавьте «счастливых», это продаёт эмоцию.' ), + Field::make( 'text', 'reviews_hero_metric_2_number', 'Метрика 2 — число' ) + ->set_default_value( '12+' ) + ->set_width( 30 ) + ->set_help_text( 'Вторая по силе цифра. Не ставьте 0, 1, 2 — они не впечатляют. Примеры: «12+», «97%», «50».' ), + Field::make( 'text', 'reviews_hero_metric_2_label', 'Метрика 2 — подпись' ) + ->set_default_value( 'лет в образовании' ) + ->set_width( 70 ) + ->set_help_text( 'Подпись к цифре 2. Примеры: «лет на рынке», «лет в образовании», «преподавателей». Старайтесь, чтобы подпись читалась вместе с цифрой как законченная фраза: «12+ лет в образовании».' ), + Field::make( 'text', 'reviews_hero_metric_3_number', 'Метрика 3 — число' ) + ->set_default_value( '4.9' ) + ->set_width( 30 ) + ->set_help_text( 'Третья цифра. Если сильных цифр больше нет — поставьте рейтинг или оценку. Примеры: «4.9», «5.0», «топ-3». Дробные числа пишите через точку.' ), + Field::make( 'text', 'reviews_hero_metric_3_label', 'Метрика 3 — подпись' ) + ->set_default_value( 'рейтинг на Яндексе' ) + ->set_width( 70 ) + ->set_help_text( 'Подпись к цифре 3. Примеры: «рейтинг на Яндексе», «звёзд», «место в рейтинге области». Если указали рейтинг — обязательно добавьте «из 5» или площадку: «рейтинг на Яндексе» звучит убедительнее, чем просто «рейтинг».' ), + Field::make( 'text', 'reviews_hero_metric_4_number', 'Метрика 4 — число' ) + ->set_default_value( '14' ) + ->set_width( 30 ) + ->set_help_text( 'Четвёртая цифра. Например: количество отзывов, количество педагогов, лет опыта.' ), + Field::make( 'text', 'reviews_hero_metric_4_label', 'Метрика 4 — подпись' ) + ->set_default_value( 'отзывов о школе' ) + ->set_width( 70 ) + ->set_help_text( 'Подпись к цифре 4. Пример: «отзывов о школе», «педагогов», «лет на рынке».' ), + // CTA кнопка — статическая в шаблоне, открывает модалку Bitrix24 + )) + ->add_tab('📝 Вступление (SEO-текст)', array( + Field::make( 'html', 'reviews_intro_tab_desc', '' ) + ->set_html( '

Секция: .reviews-intro — SEO-текст в начале страницы. Управляется из админки, чтобы можно было править текст без редактирования шаблона.

' ), + Field::make( 'text', 'reviews_intro_price_text', 'Стоимость обучения (текст)' ) + ->set_default_value( 'от 40 000 ₽ в месяц' ) + ->set_width( 100 ) + ->set_help_text( 'Текст стоимости в блоке .reviews-intro__info. Пример: «от 40 000 ₽ в месяц» или «от 35 000 ₽/мес». Если поле пусто — строка не выводится.' ), + Field::make( 'textarea', 'reviews_intro_lead', 'Лид-абзац (первый, крупный)' ) + ->set_default_value( 'Частная школа Декарт в Щёлково — это образовательное пространство, где каждый ребёнок получает внимание, заботу и качественные знания. Мы работаем в Щёлковском городском округе с 2010 года и за это время помогли раскрыть потенциал сотням учеников. Отзывы родителей о школе Декарт — это реальные истории семей, которые доверили нам образование своих детей. Мы публикуем их, чтобы вы могли принять взвешенное решение.' ) + ->set_help_text( 'Первый, самый заметный абзац. Отображается крупнее остальных, отделён линией. 150–180 символов — оптимально. Должен вовлекать и отвечать на главный вопрос посетителя.' ), + Field::make( 'textarea', 'reviews_intro_card_1', 'Блок «О школе» (карточка 1)' ) + ->set_default_value( 'В нашей частной школе в Щёлково учатся дети с 1 по 11 класс. Мы предлагаем программы начального общего образования, подготовки к ОГЭ и ЕГЭ, углублённое изучение английского языка. Классы небольшие — до 12 человек, поэтому каждый ученик получает индивидуальный подход. Родители, которые ищут качественное образование в Щёлково и Московской области, выбирают Декарт за профессионализм педагогов и тёплую атмосферу.' ) + ->set_help_text( 'Левая карточка в сетке из двух колонок. Здесь — факты о школе: классы, программы, преимущества. 100–200 символов.' ), + Field::make( 'textarea', 'reviews_intro_card_2', 'Блок «О странице» (карточка 2)' ) + ->set_default_value( 'Мы ценим каждое мнение и постоянно работаем над улучшением обучения. Ниже вы найдёте реальные отзывы родителей о нашей частной школе, достижения учеников и ответы на частые вопросы. Приятного чтения!' ) + ->set_help_text( 'Правая карточка в сетке. Объясняет, что пользователь найдёт на странице. 80–120 символов.' ), + )) + ->add_tab('🏠 Почему выбирают (локальный)', array( + Field::make( 'html', 'reviews_local_tab_desc', '' ) + ->set_html( '

Секция: .reviews-local — список причин выбрать школу с привязкой к городу. Заголовок секции статический в шаблоне, подставляет город из настроек филиала.

' ), + Field::make( 'complex', 'reviews_local_items', 'Причины' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( '4–6 причин, почему родители выбирают именно Декарт. Каждая — жирный заголовок + описание. Текст должен быть с гео-привязкой (упоминания города, района, местных реалий).' ) + ->add_fields( array( + Field::make( 'text', 'title', 'Заголовок' ) + ->set_width( 30 ) + ->set_help_text( 'Короткий, ёмкий заголовок. 2–5 слов. ✅ «Удобное расположение» ❌ «Мы находимся в удобном месте с хорошей транспортной доступностью».' ), + Field::make( 'textarea', 'text', 'Описание' ) + ->set_width( 70 ) + ->set_help_text( '2–3 предложения с гео-привязкой. Упомяните город, район, местные реалии. Родитель должен почувствовать: «Это про мой город, это для меня».' ), + )), + )) + ->add_tab('📊 Наши результаты (цифрами)', array( + Field::make( 'html', 'reviews_results_tab_desc', '' ) + ->set_html( '

Секция: .results

' ), + Field::make( 'text', 'reviews_results_title', 'Заголовок секции' ) + ->set_default_value( 'Декарт в цифрах' ) + ->set_width( 100 ) + ->set_help_text( 'Заголовок блока с результатами. Должен привлекать внимание и обещать пользу. Примеры: «Декарт в цифрах», «Наши достижения», «Почему нам доверяют родители». Избегайте канцеляризмов: «Статистические показатели» — плохо.' ), + Field::make( 'complex', 'reviews_results', 'Показатели' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( '4-6 цифр, которые доказывают качество школы. Каждый показатель должен отвечать на вопрос родителя: «Почему мы должны вам доверять?». Примеры: % поступивших в вузы, средний балл учеников, стаж преподавателей, количество учеников. Избегайте абстрактных цифр вроде «более 50 довольных клиентов» — звучит неубедительно.' ) + ->add_fields( array( + Field::make( 'text', 'number', 'Число' ) + ->set_width( 25 ) + ->set_help_text( 'Сама цифра — должна выглядеть эффектно и убедительно. ✅ «100%», «85%», «500+», «50». ❌ «много», «больше 10», «каждый второй» — размытые формулировки не работают. Используйте % и + чтобы цифра казалась больше.' ), + Field::make( 'select', 'icon', 'Иконка' ) + ->set_width( 20 ) + ->set_help_text( 'Иконка рядом с цифрой. Подбирайте по смыслу: 🏆 достижения, 📖 учёба, 👥 ученики, ❤️ любовь/забота. Иконка помогает быстро понять суть.' ) + ->add_options( array( + 'ph-graduation-cap' => '🎓 Диплом / шапочка', + 'ph-chats' => '💬 Речевой пузырь', + 'ph-users-three' => '👥 Люди / группа', + 'ph-star' => '⭐ Звезда', + 'ph-shield-check' => '🛡️ Галочка / щит', + 'ph-book' => '📖 Книга', + 'ph-heart' => '❤️ Сердце', + 'ph-clock' => '🕐 Часы', + 'ph-house' => '🏠 Дом', + 'ph-trophy' => '🏆 Кубок', + )), + Field::make( 'text', 'label', 'Подпись' ) + ->set_width( 55 ) + ->set_help_text( 'Пояснение к цифре. Текст должен быть понятен САМ ПО СЕБЕ, даже без цифры. ✅ «учеников сдают ВПР на 4 и 5», ❌ «сдают ВПР» (что? кто?). Длина — 3-5 слов. Примеры: «лет на рынке», «выпускников поступают в топ-вузы», «средний балл учеников по математике».' ), + )), + )) + ->add_tab('❓ FAQ (вопросы-ответы)', array( + Field::make( 'html', 'reviews_faq_tab_desc', '' ) + ->set_html( '
+

🎯 Какие вопросы добавлять на эту страницу

+

Эта страница — последний шаг перед записью. Человек уже почти решился, он читает отзывы чтобы окончательно убедиться. Вопросы и ответы здесь должны снимать последние сомнения, а не рассказывать о центре в целом.

+

✅ Правильные вопросы — про доверие и финальные сомнения:

+ +

❌ Неправильные вопросы — их размещайте на других страницах:

+ +

📐 Сколько вопросов добавлять:

+

Оптимально 4–6. Меньше — не закрывает сомнения, больше — отвлекает от записи.

+
' ), + // Заголовок секции — статический в шаблоне + Field::make( 'complex', 'reviews_faq', 'Вопросы и ответы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Вопросы — снимают последние сомнения перед записью. 4–6 штук.' ) + ->add_fields( array( + Field::make( 'textarea', 'question', 'Вопрос' ) + ->set_width( 30 ) + ->set_help_text( 'Вопрос должен звучать так, как его задаст реальный родитель — простыми словами, без канцелярита. ✅ «А если ребёнок не захочет ходить?» ❌ «Как преодолеть сопротивление ребёнка к посещению занятий?». Первое — вызывает доверие, второе — выглядит как копипаста с другого сайта.' ), + Field::make( 'textarea', 'answer', 'Ответ' ) + ->set_width( 70 ) + ->set_help_text( 'Ответ должен снимать страх или сомнение, а не просто сухо информировать. Используйте слова-усилители: «да», «конечно», «бесплатно», «попробуйте», «всегда можно». Структура: 1) Поймите чувства родителя («Это нормально, что вы переживаете…»). 2) Дайте решение («…поэтому у нас есть пробный урок»). 3) Позовите к действию («Приходите познакомиться — это бесплатно»).' ), + )), + )) + ->add_tab('⭐ Отзывы (карточки)', array( + Field::make( 'html', 'reviews_cards_tab_desc', '' ) + ->set_html( '

Секция: .reviews-grid. Карточки отзывов, которые видят посетители.

' ), + Field::make( 'complex', 'reviews_cards', 'Отзывы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Карточки отзывов родителей — главный элемент доверия на странице. Лучше 3-4 подробных отзыва, чем 10 коротких «всё нравится». Хороший отзыв содержит: с чего начали → что изменилось → какой результат. Эмоциональные отзывы продают лучше фактов.' ) + ->add_fields( array( + Field::make( 'text', 'review_author', 'Имя автора' ) + ->set_width( 22 ) + ->set_help_text( 'Реальное имя родителя: «Анна», «Сергей», «Екатерина М.». Имена повышают доверие. Можно добавить статус: «Анна, мама Артёма». НЕ используйте анонимные «Родитель» или «Гость» — это вызывает подозрение.' ), + Field::make( 'image', 'review_photo', 'Фото автора' ) + ->set_width( 13 ) + ->set_value_type( 'url' ) + ->set_help_text( 'Фото родителя (реальное лицо). Если не загружено — показывается аватар-заглушка с первой буквой имени. Фото повышает доверие к отзыву. Рекомендуемый размер: 96×96px, формат: WebP/JPG.' ), + Field::make( 'text', 'review_rating', 'Оценка (1–5)' ) + ->set_width( 10 ) + ->set_attribute( 'type', 'number' ) + ->set_help_text( 'Оценка от 1 до 5. Ставьте 5 — если отзыв восторженный. 4 — если есть мелкие замечания (это добавляет правдоподобности). Оценки 3 и ниже публиковать не стоит — они снижают доверие.' ), + Field::make( 'date', 'review_date', 'Дата отзыва' ) + ->set_storage_format( 'd.m.Y' ) + ->set_input_format( 'd.m.Y', 'd.m.Y' ) + ->set_picker_options( array( + 'altInput' => false, + ) ) + ->set_help_text( 'Дата отзыва. Свежие отзывы (2024-2025) работают лучше старых. Формат: ДД.ММ.ГГГГ (например: 10.03.2025). Можно открыть календарь — иконка справа.' ) + ->set_width( 20 ), + Field::make( 'association', 'review_teacher', 'Преподаватель' ) + ->set_width( 30 ) + ->set_max( 1 ) + ->set_types( array( + array( + 'type' => 'post', + 'post_type' => 'teacher', + ), + ) ) + ->set_help_text( 'Если родитель хвалит конкретного учителя — привяжите отзыв к нему. Тогда на странице преподавателя тоже появится этот отзыв. Необязательно.' ), + Field::make( 'textarea', 'review_text', 'Текст отзыва' ) + ->set_width( 35 ) + ->set_help_text( 'Полный текст отзыва. 3-5 предложений — оптимально. Хорошая структура: 1) С чего начали («Пришли с проблемой…»), 2) Что изменилось («Через месяц ребёнок…»), 3) Результат («Сейчас читает лучше всех в классе»). Эмоции и конкретные детали убеждают сильнее общих фраз. Орфографию можно поправить, но сохраните живую речь.' ), + )), + )) + // 📝 Форма отзыва — тексты статические в шаблоне page-reviews.php + // 🎯 Финальный CTA — статический в шаблоне page-reviews.php. + // Скрипт для кнопок — branch_button_script (Settings API → Настройки филиала). + ->add_tab('🔗 Перелинковка', array( + Field::make( 'html', 'reviews_cross_tab_desc', '' ) + ->set_html( '

Секция: .cross-links — ссылки на другие разделы сайта. Улучшает навигацию и SEO.

' ), + Field::make( 'text', 'reviews_cross_title', 'Заголовок' ) + ->set_default_value( 'Наши программы' ) + ->set_width( 100 ) + ->set_help_text( 'Заголовок блока со ссылками. По умолчанию «Наши программы». Альтернативы: «Узнайте больше», «Другие направления», «Выберите программу». Важно: заголовок должен подталкивать перейти по ссылкам.' ), + Field::make( 'complex', 'reviews_cross_links', 'Ссылки на другие страницы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( '5-7 ссылок на другие страницы сайта. Это помогает родителям найти нужную программу и улучшает SEO (перелинковка). Обязательно добавьте: подготовка к школе, начальная школа, средняя школа, ВПР, ОГЭ/ЕГЭ, продлёнка, летний лагерь.' ) + ->add_fields( array( + Field::make( 'text', 'title', 'Название' ) + ->set_width( 50 ) + ->set_help_text( 'Текст ссылки, который увидит посетитель. ✅ «Подготовка к школе», «Группа продлённого дня». Название должно быть понятно без контекста.' ), + Field::make( 'text', 'url', 'Ссылка' ) + ->set_width( 50 ) + ->set_help_text( 'URL страницы. Можно указать сокращённо: /podgotovka-k-shkole/ или полный адрес. Скопируйте из адресной строки браузера при просмотре нужной страницы.' ), + )), + )) + ->add_tab('💎 Видеоотзывы', array( + Field::make( 'html', 'reviews_video_tab_desc', '' ) + ->set_html( '

Секция: .video-reviews. Видеоотзывы — самый убедительный формат контента. Добавьте 2-4 коротких видео (1-3 минуты).

' ), + Field::make( 'text', 'reviews_video_title', 'Заголовок секции' ) + ->set_default_value( 'Видеоотзывы родителей' ) + ->set_width( 100 ) + ->set_help_text( 'Заголовок секции с видео. По умолчанию «Видеоотзывы родителей». Можно изменить на «Смотрите, что говорят родители», «Истории наших семей» — более эмоциональные варианты работают лучше.' ), + Field::make( 'complex', 'reviews_video', 'Видеоотзывы' ) + ->set_layout( 'tabbed-horizontal' ) + ->set_help_text( 'Добавьте видеоотзывы — это повышает доверие сильнее, чем текст. Видео должны быть на YouTube, в открытом доступе, длительностью 1-3 минуты. Хорошо, если родитель рассказывает историю: пришли с проблемой → как школа помогла → результат.' ) + ->add_fields( array( + Field::make( 'text', 'name', 'Имя автора' ) + ->set_width( 30 ) + ->set_help_text( 'Имя родителя из видео. Например: «Мария, мама Артёма». Если в видео несколько человек — укажите главного героя.' ), + Field::make( 'url', 'url', 'Ссылка на видео (YouTube)' ) + ->set_width( 70 ) + ->set_help_text( 'Ссылка на видео. Поддерживаются: YouTube (https://www.youtube.com/watch?v=...), VK Видео (https://vk.com/video-... или https://vkvideo.ru/...), Rutube и другие oEmbed-провайдеры. Видео должно быть в открытом доступе. Проверьте ссылку перед публикацией.' ), + )), + )) + ->add_tab('📸 Фото с занятий', array( + Field::make( 'html', 'reviews_photos_tab_desc', '' ) + ->set_html( '

Секция: .reviews-photos — фотогалерея с занятий. 4-8 фото повышают доверие и показывают атмосферу школы. Рекомендуемый размер: 800×600px, формат WebP.

' ), + Field::make( 'text', 'reviews_photos_title', 'Заголовок секции' ) + ->set_default_value( 'Фото с занятий' ) + ->set_width( 100 ) + ->set_help_text( 'Заголовок галереи. По умолчанию «Фото с занятий». Альтернативы: «Как проходят занятия», «Наши будни», «Атмосфера школы».' ), + Field::make( 'media_gallery', 'reviews_photos', 'Фотографии' ) + ->set_type( array( 'image' ) ) + ->set_help_text( 'Загрузите 4-8 фотографий. РЕКОМЕНДУЕМЫЙ РАЗМЕР: 800×600px (4:3), формат WebP. Все фото в галерее автоматически обрезаются до одинакового размера на странице (4:3), соотношение сторон сохраняется.' ), + )); } @@ -810,6 +1282,24 @@ function replaceQuotes($text) { return $text; } +/** + * Санитация для поля branch_button_script. + * Сохраняет -
+