Global-2026-07-13
This commit is contained in:
parent
ca70d76648
commit
b484d7ca19
1
.gitignore
vendored
1
.gitignore
vendored
@ -128,3 +128,4 @@ wp-content/upgrade-temp-backup/
|
||||
data/
|
||||
llms.txt
|
||||
test.php
|
||||
.agents/
|
||||
|
||||
275
AGENTS.md
275
AGENTS.md
@ -1,24 +1,251 @@
|
||||
# Site1 — WordPress project
|
||||
|
||||
## Primary agent
|
||||
- @site1 — dedicated WordPress agent (auto-activated, see `.opencode/AGENTS.md`)
|
||||
|
||||
## Quick rules
|
||||
- PHP: PSR-12, type declarations, Composer
|
||||
- JS: TypeScript strict, ESM, async/await
|
||||
- Commits: conventional commits (`feat:`, `fix:`, `chore:`, etc.)
|
||||
|
||||
## Security
|
||||
- NEVER modify wp-config.php without explicit confirmation
|
||||
- NEVER delete files in uploads/ or wp-content/ without confirmation
|
||||
- ALWAYS ask before destructive actions (rm, overwrite, DB write, git push)
|
||||
|
||||
## Commands
|
||||
- PHP test: `vendor/bin/phpunit`
|
||||
- PHP lint: `vendor/bin/phpstan analyse`
|
||||
- JS build: `npm run build`
|
||||
- JS test: `npm test`
|
||||
- JS lint: `npm run lint`
|
||||
|
||||
## All details
|
||||
See `.opencode/AGENTS.md` for full architecture, skills, agents list, and directory structure.
|
||||
# Site1 — WordPress Project
|
||||
## Agent
|
||||
Primary agent:
|
||||
- @site1
|
||||
This agent manages the WordPress project architecture, development workflow, frontend changes, SEO safety, and deployment preparation.
|
||||
---
|
||||
# Project Context
|
||||
Project type:
|
||||
- Custom WordPress website.
|
||||
Architecture:
|
||||
- WordPress core.
|
||||
- Custom theme:
|
||||
`wp-content/themes/dekart/`
|
||||
Theme contains:
|
||||
- Templates
|
||||
- Custom frontend styles
|
||||
- Carbon Fields integration
|
||||
- Schema.org JSON-LD logic
|
||||
- Custom business data logic
|
||||
Repository:
|
||||
- Git is the source of truth.
|
||||
- Theme changes are deployed through Git.
|
||||
- Production and development environments are separated.
|
||||
Important:
|
||||
Before any changes, inspect existing architecture.
|
||||
Do not assume standard WordPress structure.
|
||||
---
|
||||
# Critical Rules
|
||||
## Forbidden without explicit confirmation
|
||||
NEVER modify:
|
||||
- wp-config.php
|
||||
- database structure
|
||||
- production environment files
|
||||
- uploads directory
|
||||
- user data
|
||||
- existing production configuration
|
||||
Before executing:
|
||||
- rm
|
||||
- delete
|
||||
- overwrite
|
||||
- database write
|
||||
- git push
|
||||
Ask for confirmation.
|
||||
---
|
||||
# WordPress Architecture Rules
|
||||
## Theme
|
||||
Location:
|
||||
wp-content/themes/dekart/
|
||||
Rules:
|
||||
Preserve:
|
||||
- existing PHP templates
|
||||
- template hierarchy
|
||||
- hooks
|
||||
- filters
|
||||
- Carbon Fields compatibility
|
||||
- schema.org output
|
||||
- SEO logic
|
||||
Do not:
|
||||
- rebuild templates
|
||||
- replace theme architecture
|
||||
- move functionality into plugins without approval
|
||||
- introduce page builders
|
||||
---
|
||||
# Carbon Fields
|
||||
Carbon Fields is intentionally located inside the theme.
|
||||
Rules:
|
||||
Do not:
|
||||
- move Carbon Fields into a plugin
|
||||
- rename fields
|
||||
- change option keys
|
||||
- modify stored data structure
|
||||
Any changes must preserve backward compatibility.
|
||||
---
|
||||
# Frontend / Redesign Rules
|
||||
Goal:
|
||||
Improve visual design without changing markup.
|
||||
Allowed:
|
||||
- CSS
|
||||
- SCSS
|
||||
- CSS variables
|
||||
- typography
|
||||
- colors
|
||||
- spacing
|
||||
- borders
|
||||
- shadows
|
||||
- animations
|
||||
- responsive improvements
|
||||
Forbidden:
|
||||
- changing HTML structure
|
||||
- changing block layout
|
||||
- changing forms
|
||||
- replacing components
|
||||
- adding Elementor
|
||||
- adding visual builders
|
||||
Priority:
|
||||
1. Preserve functionality
|
||||
2. Preserve SEO
|
||||
3. Preserve accessibility
|
||||
4. Improve UI consistency
|
||||
---
|
||||
# Modern Web Development
|
||||
Use Google Chrome Modern Web Guidance principles.
|
||||
Priorities:
|
||||
- Accessibility
|
||||
- Performance
|
||||
- Responsive design
|
||||
- Maintainable CSS
|
||||
- Browser compatibility
|
||||
Prefer:
|
||||
- CSS variables
|
||||
- reusable design tokens
|
||||
- semantic CSS naming
|
||||
- modern CSS compatible with Baseline
|
||||
Avoid:
|
||||
- unnecessary JavaScript
|
||||
- duplicated CSS
|
||||
- layout shifts
|
||||
- heavy dependencies
|
||||
Consider:
|
||||
- Core Web Vitals
|
||||
- CLS
|
||||
- LCP
|
||||
- accessibility contrast
|
||||
- responsive behavior
|
||||
---
|
||||
# Frontend Workflow
|
||||
Before changing styles:
|
||||
1. Audit existing CSS.
|
||||
2. Identify:
|
||||
- colors
|
||||
- typography
|
||||
- spacing
|
||||
- components
|
||||
- duplicated rules
|
||||
- inconsistent UI patterns
|
||||
Create design tokens when possible:
|
||||
Example:
|
||||
```css
|
||||
:root {
|
||||
--color-primary:
|
||||
--color-secondary:
|
||||
--color-text:
|
||||
--color-background:
|
||||
--border-radius:
|
||||
--shadow:
|
||||
}
|
||||
Do not make blind global replacements.
|
||||
SEO Safety
|
||||
Never break:
|
||||
title/meta logic
|
||||
schema.org JSON-LD
|
||||
breadcrumbs
|
||||
canonical URLs
|
||||
indexing behavior
|
||||
structured data
|
||||
Frontend changes must not affect SEO output.
|
||||
Performance
|
||||
Keep:
|
||||
Core Web Vitals
|
||||
minimal CSS overhead
|
||||
optimized assets
|
||||
no unnecessary scripts
|
||||
Avoid:
|
||||
additional libraries without approval
|
||||
duplicate dependencies
|
||||
blocking resources
|
||||
Redis Object Cache
|
||||
Current architecture:
|
||||
Redis Object Cache plugin
|
||||
mu-plugin bootstrap
|
||||
WordPress object cache API
|
||||
Rules:
|
||||
Do not create another caching layer.
|
||||
Do not create custom Redis clients.
|
||||
Do not create custom object-cache.php.
|
||||
Use:
|
||||
wp_cache_get()
|
||||
wp_cache_set()
|
||||
Runtime files:
|
||||
Never commit:
|
||||
wp-content/object-cache.php
|
||||
Development Standards
|
||||
PHP
|
||||
Use:
|
||||
PSR-12
|
||||
type declarations where appropriate
|
||||
WordPress coding standards
|
||||
JavaScript
|
||||
Use:
|
||||
TypeScript strict
|
||||
ESM
|
||||
async/await
|
||||
Avoid unnecessary frameworks.
|
||||
Git Rules
|
||||
Commit format:
|
||||
feat:
|
||||
fix:
|
||||
refactor:
|
||||
style:
|
||||
chore:
|
||||
docs:
|
||||
Before commit:
|
||||
Run:
|
||||
git status
|
||||
git diff
|
||||
Never commit:
|
||||
.env
|
||||
uploads/
|
||||
logs/
|
||||
wp-content/object-cache.php
|
||||
cache files
|
||||
temporary files
|
||||
Testing
|
||||
PHP:
|
||||
vendor/bin/phpunit
|
||||
vendor/bin/phpstan analyse
|
||||
JavaScript:
|
||||
npm run build
|
||||
npm test
|
||||
npm run lint
|
||||
Run only relevant checks for changed area.
|
||||
Deployment Rules
|
||||
Before deployment verify:
|
||||
changed files
|
||||
dependencies
|
||||
environment requirements
|
||||
database impact
|
||||
cache impact
|
||||
Never assume production environment matches development.
|
||||
Required Work Process
|
||||
For complex tasks:
|
||||
Analyze current implementation.
|
||||
Explain planned changes.
|
||||
Wait for confirmation if architecture changes are required.
|
||||
Implement minimal changes.
|
||||
Verify result.
|
||||
Provide report.
|
||||
Final Response Format
|
||||
After completing tasks always provide:
|
||||
Summary
|
||||
What was changed.
|
||||
Files Changed
|
||||
List files.
|
||||
Technical Details
|
||||
Explain implementation.
|
||||
Validation
|
||||
Tests and checks performed.
|
||||
Risks
|
||||
Possible issues.
|
||||
Deployment Notes
|
||||
Required production actions.
|
||||
@ -1,14 +1,21 @@
|
||||
<?php
|
||||
// Auto-enable Redis object cache if available
|
||||
if ( extension_loaded("redis") ) {
|
||||
$host = getenv("WP_REDIS_HOST") ?: "127.0.0.1";
|
||||
$port = (int)(getenv("WP_REDIS_PORT") ?: 6379);
|
||||
$db = (int)(getenv("WP_REDIS_DATABASE") ?: 0);
|
||||
|
||||
if ( @fsockopen($host, $port, $errno, $errstr, 0.5) ) {
|
||||
define("WP_REDIS_HOST", $host);
|
||||
define("WP_REDIS_PORT", $port);
|
||||
define("WP_REDIS_DATABASE", $db);
|
||||
define("WP_CACHE", true);
|
||||
}
|
||||
if ( ! defined( 'WP_REDIS_HOST' ) ) {
|
||||
define(
|
||||
'WP_REDIS_HOST',
|
||||
getenv( 'WP_REDIS_HOST' ) ?: '127.0.0.1'
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! defined( 'WP_REDIS_PORT' ) ) {
|
||||
define(
|
||||
'WP_REDIS_PORT',
|
||||
( int ) ( getenv( 'WP_REDIS_PORT' ) ?: 6379 )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! defined( 'WP_REDIS_DATABASE' ) ) {
|
||||
define(
|
||||
'WP_REDIS_DATABASE',
|
||||
( int ) ( getenv( 'WP_REDIS_DATABASE' ) ?: 0 )
|
||||
);
|
||||
}
|
||||
|
||||
@ -324,7 +324,7 @@ background: rgba(124, 58, 237, 0.2);
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
margin: 28px 0 0;
|
||||
align-items: stretch;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* ── Карточка ── */
|
||||
@ -428,7 +428,6 @@ background: rgba(124, 58, 237, 0.2);
|
||||
|
||||
/* ── Тело карточки ── */
|
||||
.prog-card__body {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@ -1881,16 +1881,19 @@ function dekart_branch_add_menu() {
|
||||
add_action( 'admin_init', 'dekart_branch_register_settings' );
|
||||
function dekart_branch_register_settings() {
|
||||
$text_fields = array(
|
||||
'branch_city_prep' => 'text',
|
||||
'branch_city' => 'text',
|
||||
'branch_region' => 'text',
|
||||
'branch_address' => 'text',
|
||||
'branch_coords' => 'text',
|
||||
'branch_postal_code' => 'text',
|
||||
'branch_phone' => 'text',
|
||||
'branch_email' => 'email',
|
||||
'branch_name' => 'text',
|
||||
'branch_price_range' => 'text',
|
||||
'branch_city_prep' => 'text',
|
||||
'branch_city' => 'text',
|
||||
'branch_region' => 'text',
|
||||
'branch_address' => 'text',
|
||||
'branch_coords' => 'text',
|
||||
'branch_postal_code' => 'text',
|
||||
'branch_phone' => 'text',
|
||||
'branch_email' => 'email',
|
||||
'branch_name' => 'text',
|
||||
'branch_price_range' => 'text',
|
||||
'branch_logistics_walk' => 'text',
|
||||
'branch_logistics_parking' => 'text',
|
||||
'branch_logistics_schools' => 'text',
|
||||
);
|
||||
foreach ( $text_fields as $slug => $type ) {
|
||||
register_setting( 'dekart_branch_group', $slug, array( 'sanitize_callback' => $type === 'email' ? 'sanitize_email' : ( $type === 'url' ? 'esc_url_raw' : 'sanitize_text_field' ) ) );
|
||||
@ -1912,6 +1915,9 @@ function dekart_branch_register_settings() {
|
||||
register_setting( 'dekart_branch_group', 'branch_remaining_seats', array( 'sanitize_callback' => 'absint' ) );
|
||||
register_setting( 'dekart_branch_group', 'branch_schema_description', array( 'sanitize_callback' => 'sanitize_textarea_field' ) );
|
||||
register_setting( 'dekart_branch_group', 'branch_area_served', array( 'sanitize_callback' => 'sanitize_text_field' ) );
|
||||
register_setting( 'dekart_branch_group', 'branch_logistics_walk', array( 'sanitize_callback' => 'sanitize_textarea_field' ) );
|
||||
register_setting( 'dekart_branch_group', 'branch_logistics_parking', array( 'sanitize_callback' => 'sanitize_textarea_field' ) );
|
||||
register_setting( 'dekart_branch_group', 'branch_logistics_nearby', array( 'sanitize_callback' => 'sanitize_textarea_field' ) );
|
||||
// Поля branch_map_url, branch_founded, branch_photos — удалены.
|
||||
// Они дублировали CF таб «SEO и микроразметка» (schema_*).
|
||||
// Чтение: inc/schema.php → dekart_schema_option() → CF → Settings API (backward compat).
|
||||
@ -1970,6 +1976,21 @@ function dekart_branch_settings_page() {
|
||||
<label>Почтовый индекс</label>
|
||||
<input type="text" name="branch_postal_code" value="<?php echo esc_attr( get_option( 'branch_postal_code', '' ) ); ?>">
|
||||
</div>
|
||||
<div class="branch-field">
|
||||
<label>Пешком от ориентира</label>
|
||||
<input type="text" name="branch_logistics_walk" value="<?php echo esc_attr( get_option( 'branch_logistics_walk', '5 минут пешком от ТЦ «Глобус»' ) ); ?>">
|
||||
<p class="desc">Например: «5 минут пешком от ТЦ «Глобус»</p>
|
||||
</div>
|
||||
<div class="branch-field">
|
||||
<label>Парковка</label>
|
||||
<input type="text" name="branch_logistics_parking" value="<?php echo esc_attr( get_option( 'branch_logistics_parking', 'Есть бесплатная парковка у входа' ) ); ?>">
|
||||
<p class="desc">Например: «Есть бесплатная парковка у входа»</p>
|
||||
</div>
|
||||
<div class="branch-field">
|
||||
<label>Рядом с школами/садами</label>
|
||||
<input type="text" name="branch_logistics_schools" value="<?php echo esc_attr( get_option( 'branch_logistics_schools', 'Рядом со школами №9 и №12, детским садом №15' ) ); ?>">
|
||||
<p class="desc">Например: «Рядом со школами №9 и №12, детским садом №15»</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -211,8 +211,38 @@ class Pksh_Data {
|
||||
[];
|
||||
$this->branch['social'] = is_array( $raw ) ? $raw : [];
|
||||
}
|
||||
wp_cache_set( $cache_key, $this->branch['social'], 'dekart_branch', DAY_IN_SECONDS );
|
||||
return $this->branch['social'];
|
||||
wp_cache_set( $cache_key, $this->branch['social'], 'dekart_branch', DAY_IN_SECONDS );
|
||||
return $this->branch['social'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Логистика — пешком от ТЦ (branch_logistics_walk)
|
||||
*/
|
||||
public function get_logistics_walk(): string {
|
||||
if ( ! array_key_exists( 'logistics_walk', $this->branch ) ) {
|
||||
$this->branch['logistics_walk'] = get_option( 'branch_logistics_walk', '5 минут пешком от ТЦ «Глобус»' );
|
||||
}
|
||||
return $this->branch['logistics_walk'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Логистика — парковка (branch_logistics_parking)
|
||||
*/
|
||||
public function get_logistics_parking(): string {
|
||||
if ( ! array_key_exists( 'logistics_parking', $this->branch ) ) {
|
||||
$this->branch['logistics_parking'] = get_option( 'branch_logistics_parking', 'Есть бесплатная парковка у входа' );
|
||||
}
|
||||
return $this->branch['logistics_parking'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Логистика — соседние школы/сад (branch_logistics_schools)
|
||||
*/
|
||||
public function get_logistics_nearby(): string {
|
||||
if ( ! array_key_exists( 'logistics_nearby', $this->branch ) ) {
|
||||
$this->branch['logistics_nearby'] = get_option( 'branch_logistics_schools', 'Рядом со школами №9 и №12, детским садом №15' );
|
||||
}
|
||||
return $this->branch['logistics_nearby'];
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
||||
@ -22,6 +22,8 @@ $data = Pksh_Data::instance();
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<?php get_template_part( 'template-parts/svg-sprite' ); ?>
|
||||
|
||||
<main class="page page-pksh">
|
||||
|
||||
<?php
|
||||
|
||||
@ -10,13 +10,16 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = Pksh_Data::instance();
|
||||
$opt_phone = $data->get_phone();
|
||||
$opt_email = $data->get_email();
|
||||
$opt_address = $data->get_address();
|
||||
$opt_social = $data->get_social_links();
|
||||
$opt_coords = $data->get_coords();
|
||||
$opt_name = $data->get_name();
|
||||
$data = Pksh_Data::instance();
|
||||
$opt_phone = $data->get_phone();
|
||||
$opt_email = $data->get_email();
|
||||
$opt_address = $data->get_address();
|
||||
$opt_social = $data->get_social_links();
|
||||
$opt_coords = $data->get_coords();
|
||||
$opt_name = $data->get_name();
|
||||
$opt_logistics_walk = $data->get_logistics_walk();
|
||||
$opt_logistics_parking = $data->get_logistics_parking();
|
||||
$opt_logistics_nearby = $data->get_logistics_nearby();
|
||||
?>
|
||||
<section class="bento pksh-section" id="pksh-contact" aria-label="Контакты">
|
||||
<div class="bento__full section-header--centered">
|
||||
@ -43,18 +46,24 @@ $opt_name = $data->get_name();
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="pksh-contact__logistics">
|
||||
<?php if ( ! empty( $opt_logistics_walk ) ) : ?>
|
||||
<span class="pksh-contact__logistics-item">
|
||||
<span class="pksh-contact__logistics-icon">📍</span>
|
||||
<span class="pksh-contact__logistics-text">5 минут пешком от ТЦ «Глобус»</span>
|
||||
<span class="pksh-contact__logistics-text"><?php echo esc_html( $opt_logistics_walk ); ?></span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $opt_logistics_parking ) ) : ?>
|
||||
<span class="pksh-contact__logistics-item">
|
||||
<span class="pksh-contact__logistics-icon">🅿️</span>
|
||||
<span class="pksh-contact__logistics-text">Есть бесплатная парковка у входа</span>
|
||||
<span class="pksh-contact__logistics-text"><?php echo esc_html( $opt_logistics_parking ); ?></span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! empty( $opt_logistics_nearby ) ) : ?>
|
||||
<span class="pksh-contact__logistics-item">
|
||||
<span class="pksh-contact__logistics-icon">🚸</span>
|
||||
<span class="pksh-contact__logistics-text">Рядом со школами №9 и №12, детским садом №15</span>
|
||||
<span class="pksh-contact__logistics-text"><?php echo esc_html( $opt_logistics_nearby ); ?></span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ( ! empty( $opt_social ) && is_array( $opt_social ) ) : ?>
|
||||
|
||||
@ -30,10 +30,7 @@ $hero_metrics = $data->get_social_counters();
|
||||
<div class="ds-hero__content">
|
||||
|
||||
<div class="ds-hero__address">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/>
|
||||
<circle cx="12" cy="10" r="3"/>
|
||||
</svg>
|
||||
<svg aria-hidden="true" width="16" height="16"><use href="#icon-location-pin"/></svg>
|
||||
<span><?php echo esc_html( $opt_address ?: 'ул. Талсинская, 24' ); ?> — центр <?php echo esc_html( $branch_city_clean ?: 'Щёлково' ); ?></span>
|
||||
</div>
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="steps-3">
|
||||
<div class="step">
|
||||
<div class="step__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg class="step-icon" aria-hidden="true"><use href="#icon-check"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Вход в тему</strong>
|
||||
@ -33,7 +33,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6-1.6 1.6a1 1 0 0 0 1.4 1.4l2.3-2.3a1 1 0 0 0 0-1.4L16.1 6.3a1 1 0 0 0-1.4 0z" fill="currentColor"/><path d="M4 6h13M4 12h9M4 18h13" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg class="step-icon" aria-hidden="true"><use href="#icon-document"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Игровое задание</strong>
|
||||
@ -42,7 +42,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="step__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg class="step-icon" aria-hidden="true"><use href="#icon-clock"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Рефлексия</strong>
|
||||
@ -59,7 +59,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="objection-list">
|
||||
<div class="objection-item">
|
||||
<div class="objection-item__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" stroke="#059669" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg aria-hidden="true" width="24" height="24"><use href="#icon-check-circle"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Не перегрузят ли ребёнка?</strong>
|
||||
@ -68,22 +68,23 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
</div>
|
||||
<div class="objection-item">
|
||||
<div class="objection-item__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" stroke="#059669" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg aria-hidden="true" width="24" height="24"><use href="#icon-calendar"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Успеем ли до сентября?</strong>
|
||||
<p>Да. Наша программа рассчитана на 4–6 месяцев. Первые результаты — через 3 недели.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="objection-item">
|
||||
<div class="objection-item">
|
||||
<div class="objection-item__icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" stroke="#059669" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
<svg aria-hidden="true" width="24" height="24"><use href="#icon-coin"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Дорого?</strong>
|
||||
<p>От 600 ₽ за занятие. Первое — бесплатно. А если не понравится — вернём деньги.</p>
|
||||
<p>От 600 ₽ за занятие. Первое — бесплатно.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -71,9 +71,7 @@ $total_count = count( $review_items );
|
||||
</div>
|
||||
<div class="lw-stars lw-mt-8">
|
||||
<?php for ( $i = 1; $i <= 5; $i++ ) : ?>
|
||||
<svg class="lw-star <?php echo $i <= $stars ? 'lw-star--filled' : ''; ?>" width="16" height="16" viewBox="0 0 21 19" fill="none">
|
||||
<path d="M9.58463 1.50884C9.89101 0.602477 11.1729 0.602476 11.4793 1.50884L13.1158 6.35007C13.2531 6.75637 13.6343 7.02985 14.0631 7.02985H19.2721C20.2504 7.02985 20.6467 8.28958 19.8447 8.84971L15.6995 11.7446C15.335 11.9991 15.1822 12.4636 15.3247 12.8847L16.9239 17.6158C17.233 18.5302 16.1954 19.3085 15.404 18.7559L11.1045 15.7533C10.7606 15.5131 10.3033 15.5131 9.95941 15.7533L5.65991 18.7559C4.86857 19.3085 3.83092 18.5302 4.14001 17.6158L5.73926 12.8847C5.8816 12.4636 5.72891 11.9991 5.36448 11.7446L1.21924 8.84971C0.417196 8.28958 0.813532 7.02985 1.79181 7.02985H7.00081C7.42969 7.02985 7.81081 6.75637 7.94815 6.35007L9.58463 1.50884Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<svg class="lw-star <?php echo $i <= $stars ? 'lw-star--filled' : ''; ?>" aria-hidden="true" width="16" height="16"><use href="#<?php echo $i <= $stars ? 'icon-star-filled' : 'icon-star'; ?>"/></svg>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
<div class="lw-card__text lw-mt-8<?php echo $is_long ? ' review-card__text--clamped' : ''; ?>">
|
||||
|
||||
77
wp-content/themes/dekart/template-parts/svg-sprite.php
Normal file
77
wp-content/themes/dekart/template-parts/svg-sprite.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* SVG Sprite — общие иконки для page-podgotovka-k-shkole.php
|
||||
* Подключается в футере через get_template_part('template-parts/svg-sprite')
|
||||
*
|
||||
* @package Dekart
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none;" aria-hidden="true">
|
||||
<symbol id="icon-check-circle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-calendar" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
||||
<line x1="16" y1="2" x2="16" y2="6"/>
|
||||
<line x1="8" y1="2" x2="8" y2="6"/>
|
||||
<line x1="3" y1="10" x2="21" y2="10"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-coin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<path d="M12 6v12M6 12h12"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6-1.6 1.6a1 1 0 0 0 1.4 1.4l2.3-2.3a1 1 0 0 0 0-1.4L16.1 6.3a1 1 0 0 0-1.4 0z" fill="currentColor"/>
|
||||
<path d="M4 6h13M4 12h9M4 18h13" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-document" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-coin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<path d="M12 6v12M6 12h12"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-calendar" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
||||
<line x1="16" y1="2" x2="16" y2="6"/>
|
||||
<line x1="8" y1="2" x2="8" y2="6"/>
|
||||
<line x1="3" y1="10" x2="21" y2="10"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-location-pin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/>
|
||||
<circle cx="12" cy="10" r="3"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-star" viewBox="0 0 21 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="10.5 0 12.5 7.5 20 7.5 14 12.5 16 19.5 10.5 16 5 19.5 7 12.5 1 7.5 6 12.5"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-star-filled" viewBox="0 0 21 19" fill="currentColor">
|
||||
<polygon points="10.5 0 12.5 7.5 20 7.5 14 12.5 16 19.5 10.5 16 5 19.5 7 12.5 1 7.5 6 12.5"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<path d="M12 6v6l4 2"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12h18M3 6h18M3 18h18"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="icon-arrow-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</symbol>
|
||||
</symbol>
|
||||
</svg>
|
||||
Loading…
Reference in New Issue
Block a user