diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..068cf37 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "11ty dev server (live reload)", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "port": 8080 + }, + { + "name": "Python HTTP Server (_site)", + "runtimeExecutable": "python3", + "runtimeArgs": ["-m", "http.server", "8081", "--directory", "/Users/lexx/Projects/2026/dp-trade-UI-kit/_site"], + "port": 8081 + } + ] +} diff --git a/.eleventy.js b/.eleventy.js new file mode 100644 index 0000000..820157b --- /dev/null +++ b/.eleventy.js @@ -0,0 +1,15 @@ +export default function (eleventyConfig) { + eleventyConfig.addPassthroughCopy("src/css"); + eleventyConfig.addPassthroughCopy("src/assets"); + eleventyConfig.addPassthroughCopy("src/js"); + + return { + dir: { + input: "src", + output: "_site", + includes: "_includes", + }, + templateFormats: ["njk", "html"], + htmlTemplateEngine: "njk", + }; +} diff --git a/.gitignore b/.gitignore index 6a73c02..5281e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store node_modules/ dist/ +_site/ .env diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..818ebbc --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,100 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +Перед началом работы над любой задачей сложнее одного шага +составь todo-список и показывай его прогресс по ходу выполнения. +Для задач с неочевидным подходом сначала предложи план и дождись подтверждения. + +## Project + +Static HTML/CSS UI-kit and page prototypes for **DP Trade** — a B2B wine wholesale catalog (wine-dp-trade.ru). The output of this project is handed off to **WordPress/Elementor** for production deployment. See `docs/elementor-token-handoff.md` for the full Elementor migration guide. + +## Commands + +```bash +# Dev server (11ty with live reload) +npm run dev # http://localhost:8080 + +# Production build → _site/ +npm run build +``` + +Dev server config is also saved in `.claude/launch.json` for use with `preview_start`. + +## Architecture + +### CSS layer (single dependency direction) + +``` +css/tokens.css ← design tokens only (colors, fonts, spacing, radius, shadows) + ↓ +css/site.css ← all page styles, imports tokens.css +css/ui-kit.css ← design system showcase styles, standalone +``` + +Never put visual styles in `tokens.css`. Never import `site.css` into `ui-kit.css`. + +### 11ty template structure (`src/`) + +``` +src/ + _includes/ + layouts/ + base.njk ← HTML shell: , fonts, CSS link, + default.njk ← base + header partial + footer partial (used by all site pages) + ui-kit.njk ← base only, no header/footer (used by ui-kit page) + partials/ + header.njk ← full site header with mega-menu nav + footer.njk ← full site footer + css/ ← passthrough copy → _site/css/ + assets/ ← passthrough copy → _site/assets/ + *.njk ← one file per page +``` + +### Page front matter + +Every page declares layout, title, optional bodyClass, and permalink: + +```yaml +--- +title: "DP Trade — Catalog" +layout: default # or "ui-kit" for the design system page +bodyClass: compact-type # omit if not needed +permalink: /catalog.html # keeps flat output, preserves relative CSS paths +--- +``` + +Pages with `bodyClass: compact-type`: catalog, about, contacts, article-guidelines. +The `ui-kit` page uses `layout: ui-kit` and `css: ui-kit` (links `ui-kit.css` instead of `site.css`). + +### CSS paths + +All CSS paths in `base.njk` are **absolute** (`/css/site.css`), which requires the 11ty dev server — they will not work when opening `_site/` files directly in a browser via `file://`. + +### Design tokens + +Key CSS custom properties defined in `css/tokens.css`: + +- Colors: `--color-primary-wine-100` (#4b0f24), `--color-accent-gold` (#b9965b), `--color-accent-blue` (#1f3476) +- Fonts: `--font-heading` (Montserrat 800), `--font-body` (Inter), `--font-heading-classic` (Playfair Display) +- Container: `--container: 1240px` + +When adding new tokens, add to `tokens.css` and mirror to the Elementor CSS layer in `docs/elementor-token-handoff.md` (Section 6). + +### Responsive breakpoints + +Defined at the bottom of `css/site.css`: + +- `@media (max-width: 1080px)` — tablet +- `@media (max-width: 720px)` — mobile + +## Key files + +| File | Purpose | +| ----------------------------------- | ------------------------------------------------------------ | +| `css/tokens.css` | Single source of truth for all design values | +| `docs/elementor-token-handoff.md` | Guide for migrating tokens/components to WordPress Elementor | +| `.claude/launch.json` | Dev server configurations | +| `src/_includes/partials/header.njk` | Mega-menu navigation — edit here, propagates to all pages | +| `src/_includes/partials/footer.njk` | Footer — edit here, propagates to all pages | diff --git a/docs/elementor-token-handoff.md b/docs/elementor-token-handoff.md new file mode 100644 index 0000000..dc8d7ed --- /dev/null +++ b/docs/elementor-token-handoff.md @@ -0,0 +1,666 @@ +# Перенос UI-kit токенов и элементов в Elementor + +Документ описывает безопасный перенос дизайн-токенов и базовых элементов DP Trade UI-kit в Elementor WordPress. Главная цель: внедрить новую дизайн-систему постепенно, не ломая текущие страницы и глобальные настройки сайта. + +## 1. Базовый принцип переноса + +Не заменяйте существующие настройки Elementor сразу. Сначала добавьте новые токены рядом со старыми, соберите тестовую страницу, проверьте визуально, затем постепенно переводите реальные шаблоны и страницы на новые значения. + +Рекомендуемый порядок: + +1. Сделать backup сайта и базы данных. +2. Работать на staging-копии или тестовой странице. +3. Добавить новые Global Colors. +4. Добавить новые Global Fonts. +5. Настроить базовые элементы: кнопки, поля, карточки, теги. +6. Создать страницу `UI Kit Preview` в WordPress. +7. Проверить desktop, tablet, mobile. +8. Только после проверки применять к Header, Footer, каталогу и страницам. + +## 2. Источники токенов в проекте + +Основные файлы: + +- `css/tokens.css` — базовые дизайн-токены сайта. +- `css/site.css` — стили реальных страниц, header, footer, карточек, каталога, форм. +- `css/ui-kit.css` — витрина UI-kit, состояния и примеры компонентов. +- `ui-kit.html` — живая HTML-витрина дизайн-системы. + +В Elementor переносите не весь CSS целиком, а роли и значения: цвета, шрифты, отступы, радиусы, тени и повторяемые компоненты. + +## 3. Карта цветов для Elementor Global Colors + +Перейдите в: + +`Elementor -> Site Settings -> Global Colors` + +Добавьте новые цвета. Старые цвета пока не удаляйте. + +| Elementor name | CSS token | Value | Role | +|---|---:|---:|---| +| DP Wine 100 | `--color-primary-wine-100` | `#4b0f24` | Основной брендовый цвет, primary buttons, hover menu, акценты | +| DP Wine 80 | `--color-primary-wine-80` | `#6d1c36` | Hover для primary, вторичный винный оттенок | +| DP Black | `--color-neutral-black` | `#161616` | Основной текст | +| DP Gray 700 | `--color-neutral-gray-700` | `#30343a` | Навигация, плотный вторичный текст | +| DP Gray 600 | `--color-neutral-gray-600` | `#66605f` | Описания, muted text, подписи | +| DP Gray 300 | `--color-neutral-gray-300` | `#d9dee6` | Бордеры, разделители | +| DP Background | `--color-background-base` | `#f4f6f9` | Основной фон страниц | +| DP Surface | `--color-surface` | `#ffffff` | Карточки, поля, панели | +| DP Gold | `--color-accent-gold` | `#b9965b` | Eyebrow, статусы, премиальные акценты | +| DP Blue | `--color-accent-blue` | `#1f3476` | Логотип, телефон, информационные акценты | +| DP Error | `--color-error` | `#a33a2f` | Ошибки форм | + +Важно: если в текущем Elementor уже есть цвета `Primary`, `Secondary`, `Text`, `Accent`, не заменяйте их сразу. Добавьте цвета с префиксом `DP`, затем перепривязывайте элементы вручную. + +## 4. Карта шрифтов для Elementor Global Fonts + +Перейдите в: + +`Elementor -> Site Settings -> Global Fonts` + +Подключение шрифтов: + +- Headings: `Montserrat` +- Body: `Inter` +- Classic heading, если понадобится для редакционных блоков: `Playfair Display` + +| Elementor style | Font family | Weight | Size desktop | Line height | Transform | +|---|---|---:|---:|---:|---| +| DP H1 | `Montserrat` | `800` | `48-72px` | `1.1` | Uppercase | +| DP H2 | `Montserrat` | `800` | `36-40px` | `1.1-1.22` | Uppercase | +| DP H3 | `Montserrat` | `800` | `24-28px` | `1.15-1.25` | Uppercase | +| DP Body | `Inter` | `400` | `16px` | `1.5` | None | +| DP Body Large | `Inter` | `400` | `18px` | `28px` | None | +| DP Caption | `Inter` | `600-700` | `12-13px` | `16px` | Optional uppercase | +| DP Button | `Inter` | `700` | `14-16px` | `1.2` | None | +| DP Nav | `Inter` | `800` | `12px` | `1.2` | Uppercase | + +Рекомендация по responsive: + +| Style | Tablet | Mobile | +|---|---:|---:| +| DP H1 | `40-48px` | `34-40px` | +| DP H2 | `32-36px` | `28-32px` | +| DP H3 | `22-24px` | `20-22px` | +| DP Body | `16px` | `16px` | +| DP Button | `14-16px` | `14px` | + +Не используйте viewport-based font size в Elementor. Лучше задавать отдельные значения для desktop, tablet и mobile. + +## 5. Spacing, radius, shadows + +В Elementor нет полноценной системы design tokens для spacing, поэтому переносите значения как правила для секций, контейнеров и классов. + +### Spacing scale + +| Token | Value | Где использовать | +|---|---:|---| +| `--spacing-4` | `4px` | Мелкие зазоры, иконки | +| `--spacing-8` | `8px` | Gap внутри кнопок, compact controls | +| `--spacing-16` | `16px` | Карточки, поля, grid gap | +| `--spacing-24` | `24px` | Padding карточек, блоки форм | +| `--spacing-32` | `32px` | Gap между колонками | +| `--spacing-48` | `48px` | Крупные отступы секций | +| `--spacing-64` | `64px` | Hero, большие секции | + +### Layout + +| Token | Value | Elementor setting | +|---|---:|---| +| `--container` | `1240px` | Site Settings -> Layout -> Content Width | +| Section desktop padding | `72px 24-72px` | Section/container padding | +| Section mobile padding | `48px 20px` | Responsive padding | +| Container side gap | `20px` each side | Container width: `min(100% - 40px, 1240px)` в CSS | + +### Radius + +| Token | Value | Где использовать | +|---|---:|---| +| `--radius-sm` | `8px` | Кнопки, поля, карточки, теги | +| `--radius-md` | `12px` | Крупные панели, preview blocks | +| `--radius-lg` | `24px` | Редкие крупные акцентные блоки | + +### Shadows + +Elementor поддерживает box-shadow в Advanced/Style, но удобнее завести CSS-классы. + +| Token | Value | Где использовать | +|---|---|---| +| `--shadow-soft` | `0 12px 32px rgba(22, 22, 22, 0.08)` | Обычные карточки, формы, footer panel | +| `--shadow-lift` | `0 20px 52px rgba(75, 15, 36, 0.14)` | Hover карточек, mega menu, primary hover | +| Header shadow | `0 10px 28px rgba(22, 22, 22, 0.05)` | Sticky header | +| Focus shadow | `0 0 0 4px rgba(75, 15, 36, 0.08)` | Search/input focus | + +## 6. Безопасный CSS-слой для Elementor + +Добавляйте CSS не через глобальные теги `body`, `h1`, `button`, `input`, а через классы с префиксом `dp-`. + +Где добавлять: + +1. Сначала на тестовой странице: `Page Settings -> Advanced -> Custom CSS`. +2. После проверки: `Elementor -> Site Settings -> Custom CSS`. +3. Если есть child theme, финальную версию можно перенести в `style.css`. + +Базовый слой: + +```css +:root { + --dp-wine-100: #4b0f24; + --dp-wine-80: #6d1c36; + --dp-black: #161616; + --dp-gray-700: #30343a; + --dp-gray-600: #66605f; + --dp-gray-300: #d9dee6; + --dp-bg: #f4f6f9; + --dp-surface: #ffffff; + --dp-gold: #b9965b; + --dp-blue: #1f3476; + --dp-error: #a33a2f; + --dp-radius-sm: 8px; + --dp-shadow-soft: 0 12px 32px rgba(22, 22, 22, 0.08); + --dp-shadow-lift: 0 20px 52px rgba(75, 15, 36, 0.14); +} + +.dp-section { + padding-top: 72px; + padding-bottom: 72px; +} + +.dp-surface { + background: var(--dp-surface); + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--dp-radius-sm); + box-shadow: var(--dp-shadow-soft); +} + +.dp-eyebrow { + color: var(--dp-gold); + font-family: Inter, Arial, sans-serif; + font-size: 12px; + line-height: 16px; + font-weight: 700; + letter-spacing: 0; + text-transform: uppercase; +} +``` + +Mobile override: + +```css +@media (max-width: 767px) { + .dp-section { + padding-top: 48px; + padding-bottom: 48px; + } +} +``` + +## 7. Перенос кнопок + +В Elementor настройте: + +`Site Settings -> Buttons` + +Базовая кнопка: + +| Property | Value | +|---|---:| +| Min height | `48px` | +| Padding | `12px 22px` | +| Border radius | `8px` | +| Font | `Inter`, `700` | +| Transition | `0.2s` | + +Primary: + +| State | Text | Background | Border | Shadow | +|---|---:|---:|---:|---| +| Default | `#ffffff` | `#4b0f24` | transparent | `0 10px 22px rgba(75, 15, 36, 0.16)` | +| Hover | `#ffffff` | `#6d1c36` | transparent | `0 20px 52px rgba(75, 15, 36, 0.14)` | + +Secondary: + +| State | Text | Background | Border | +|---|---:|---:|---:| +| Default | `#4b0f24` | `rgba(255,255,255,0.55)` | `rgba(75,15,36,0.24)` | +| Hover | `#4b0f24` | `rgba(75,15,36,0.06)` | `rgba(75,15,36,0.36)` | + +CSS-классы: + +```css +.dp-btn-primary .elementor-button { + min-height: 48px; + padding: 12px 22px; + border-radius: 8px; + background: var(--dp-wine-100); + color: #ffffff; + font-weight: 700; + box-shadow: 0 10px 22px rgba(75, 15, 36, 0.16); + transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; +} + +.dp-btn-primary .elementor-button:hover { + background: var(--dp-wine-80); + box-shadow: var(--dp-shadow-lift); + transform: translateY(-1px); +} + +.dp-btn-secondary .elementor-button { + min-height: 48px; + padding: 12px 22px; + border: 1px solid rgba(75, 15, 36, 0.24); + border-radius: 8px; + background: rgba(255, 255, 255, 0.55); + color: var(--dp-wine-100); + font-weight: 700; +} + +.dp-btn-sm .elementor-button { + min-height: 38px; + padding: 8px 14px; + font-size: 14px; +} +``` + +В Elementor у виджета Button добавляйте классы: + +- `dp-btn-primary` +- `dp-btn-secondary` +- `dp-btn-sm` + +## 8. Перенос форм и input fields + +Для Elementor Forms: + +`Site Settings -> Form Fields` + +| Property | Value | +|---|---:| +| Background | `#ffffff` | +| Text | `#161616` | +| Placeholder | `#66605f` | +| Border | `1px solid rgba(102, 96, 95, 0.24)` | +| Border radius | `8px` | +| Padding | `12-14px` | +| Focus border | `#4b0f24` | +| Focus shadow | `0 0 0 3-4px rgba(75, 15, 36, 0.08-0.10)` | +| Error color | `#a33a2f` | + +CSS-класс для формы: + +```css +.dp-form .elementor-field { + border: 1px solid rgba(102, 96, 95, 0.24); + border-radius: 8px; + background: #ffffff; + color: var(--dp-black); + font-family: Inter, Arial, sans-serif; + font-size: 14px; +} + +.dp-form .elementor-field:focus { + border-color: var(--dp-wine-100); + box-shadow: 0 0 0 4px rgba(75, 15, 36, 0.08); +} + +.dp-form .elementor-field-label { + color: var(--dp-gray-700); + font-size: 13px; + font-weight: 700; +} + +.dp-form .elementor-message-danger { + color: var(--dp-error); +} +``` + +Проверить после переноса: + +- default state; +- focus state; +- required fields; +- error message; +- textarea; +- disabled field; +- submit button; +- mobile keyboard behavior. + +## 9. Карточки товаров и контентные карточки + +Карточки UI-kit используют: + +- белую поверхность; +- radius `8px`; +- border `rgba(102, 96, 95, 0.16)`; +- shadow soft; +- hover lift; +- внутренний padding `16-24px`; +- muted text `#66605f`; +- uppercase heading на `Montserrat 800`. + +CSS-класс: + +```css +.dp-card { + min-width: 0; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: 8px; + background: #ffffff; + box-shadow: var(--dp-shadow-soft); + overflow: hidden; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.dp-card:hover { + transform: translateY(-3px); + box-shadow: var(--dp-shadow-lift); +} + +.dp-card-title { + color: var(--dp-black); + font-family: Montserrat, Inter, Arial, sans-serif; + font-size: 24px; + line-height: 1.15; + font-weight: 800; + text-transform: uppercase; +} + +.dp-card-text { + color: var(--dp-gray-600); + font-size: 14px; + line-height: 1.45; +} +``` + +Для Elementor: + +1. Создайте контейнер карточки. +2. В Advanced -> CSS Classes добавьте `dp-card`. +3. Заголовку добавьте `dp-card-title`. +4. Описанию добавьте `dp-card-text`. +5. Кнопке добавьте `dp-btn-primary` или `dp-btn-secondary`. + +## 10. Теги, chips, статусы + +Используются для стран, категорий, фильтров, статусов. + +```css +.dp-tag, +.dp-chip { + display: inline-flex; + align-items: center; + min-height: 30px; + padding: 6px 10px; + border-radius: 8px; + font-size: 12px; + font-weight: 800; + line-height: 1; + text-transform: uppercase; +} + +.dp-tag-filled, +.dp-chip-active { + background: var(--dp-wine-100); + color: #ffffff; +} + +.dp-tag-outline { + border: 1px solid rgba(75, 15, 36, 0.24); + color: var(--dp-wine-100); + background: transparent; +} + +.dp-tag-gold { + background: rgba(185, 150, 91, 0.18); + color: #7c5f26; +} +``` + +В Elementor это можно делать через: + +- Heading widget с HTML tag `span`; +- Text Editor; +- Button widget без ссылки; +- Loop item meta fields, если это каталог. + +## 11. Header и навигация + +Header в UI-kit использует: + +- sticky position; +- background `rgba(248, 250, 252, 0.94)`; +- border-bottom `rgba(102, 96, 95, 0.18)`; +- shadow `0 10px 28px rgba(22, 22, 22, 0.05)`; +- blur `backdrop-filter: blur(18px)`; +- nav font `Inter 800 12px uppercase`; +- active/hover color `#4b0f24`. + +Рекомендация: + +1. Не меняйте текущий Header template сразу. +2. Дублируйте шаблон Header в Elementor. +3. Назовите копию `Header DP UI Kit Draft`. +4. Примените новые стили на копии. +5. Проверьте меню, dropdown, search, phone, cart/favorites icons. +6. Только после проверки назначайте новый шаблон на сайт. + +CSS-класс для контейнера: + +```css +.dp-header { + background: rgba(248, 250, 252, 0.94); + border-bottom: 1px solid rgba(102, 96, 95, 0.18); + box-shadow: 0 10px 28px rgba(22, 22, 22, 0.05); + backdrop-filter: blur(18px); +} + +.dp-nav a, +.dp-nav .elementor-item { + color: var(--dp-gray-700); + font-family: Inter, Arial, sans-serif; + font-size: 12px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; +} + +.dp-nav a:hover, +.dp-nav .elementor-item:hover, +.dp-nav .elementor-item-active { + color: var(--dp-wine-100); +} +``` + +## 12. Footer + +Footer использует карточную панель: + +- surface `#ffffff`; +- radius `8px`; +- shadow soft; +- структурированную сетку ссылок; +- muted legal text; +- акцентные ссылки на hover. + +Безопасный перенос: + +1. Дублируйте текущий Footer template. +2. Добавьте классы `dp-footer`, `dp-surface`, `dp-nav`. +3. Проверьте desktop/mobile сетку. +4. Не удаляйте старый footer до полной проверки. + +## 13. Каталог и product cards + +Для каталога важны следующие элементы: + +- toolbar; +- sort select; +- filters; +- grid/list cards; +- compact cards; +- price block; +- tags; +- CTA button; +- hover state. + +Порядок переноса: + +1. Сначала перенесите визуальный стиль карточки товара. +2. Потом фильтры и chips. +3. Потом toolbar/sort. +4. Потом list/compact variants. +5. Последним этапом подключайте hover и lift effects. + +Минимальный набор CSS-классов: + +```txt +dp-card +dp-product-card +dp-card-title +dp-card-text +dp-tag +dp-tag-filled +dp-btn-primary +dp-btn-sm +``` + +## 14. Страница UI Kit Preview в WordPress + +Создайте отдельную страницу: + +`UI Kit Preview` + +Разместите на ней: + +1. Цветовые swatches. +2. H1, H2, H3, body, caption. +3. Primary, secondary, small buttons. +4. Form fields: default, focus, error. +5. Product card. +6. Tags/chips. +7. Header preview. +8. Footer preview. +9. Catalog toolbar preview. +10. Mobile preview section. + +Страница нужна как контрольная витрина. Любое изменение токенов сначала проверяйте на ней. + +## 15. Что нельзя делать при переносе + +Не добавляйте глобально такие правила без полной проверки: + +```css +* { + margin: 0; + padding: 0; +} + +button { + all: unset; +} + +a { + color: inherit; + text-decoration: none; +} + +h1, +h2, +h3 { + margin: 0; +} +``` + +Они могут сломать тему, плагины, WooCommerce, формы, меню и старые страницы. + +Также не рекомендуется: + +- удалять старые Elementor Global Colors; +- массово заменять цвета по всему сайту; +- менять breakpoints без полного responsive QA; +- вставлять весь `site.css` в Elementor; +- переносить demo-стили UI-kit sidebar; +- менять Header/Footer на production без дубликата и предпросмотра. + +## 16. QA checklist перед публикацией + +Проверьте: + +- Главная страница. +- Каталог. +- Карточка товара. +- Страница контактов. +- Страница статьи/новости. +- Header desktop. +- Header mobile. +- Mega menu/dropdown. +- Footer desktop. +- Footer mobile. +- Все формы. +- Search. +- Cart/favorites/account icons, если есть. +- 404 page. +- WooCommerce cart/checkout/account, если сайт использует WooCommerce. + +Для каждого экрана: + +- нет горизонтального скролла; +- текст не обрезается; +- кнопки не ломаются; +- hover/focus состояния видны; +- карточки не прыгают по высоте; +- изображения не растягиваются; +- меню открывается и закрывается корректно; +- формы отправляются; +- ошибки форм читаемы; +- контраст текста достаточный. + +## 17. Публикация на production + +Финальный порядок: + +1. Сделать свежий backup production. +2. Экспортировать Elementor templates. +3. Перенести Global Colors. +4. Перенести Global Fonts. +5. Добавить проверенный CSS-слой. +6. Импортировать или обновить шаблоны. +7. Назначить Header/Footer только после проверки preview. +8. Elementor -> Tools -> Regenerate CSS & Data. +9. Очистить кэш плагина оптимизации. +10. Очистить server/CDN cache, если есть. +11. Проверить сайт в incognito. + +## 18. План отката + +Перед публикацией должны быть готовы: + +- backup production; +- экспорт старых Elementor templates; +- список измененных Global Colors/Fonts; +- копия добавленного Custom CSS; +- скриншоты ключевых страниц до переноса. + +Если что-то сломалось: + +1. Отключите новый Custom CSS. +2. Верните старый Header/Footer template. +3. Regenerate CSS & Data. +4. Очистите кэш. +5. Проверьте сайт. +6. Если проблема осталась, восстановите backup. + +## 19. Минимальный набор для первого этапа + +Для первого безопасного внедрения достаточно перенести: + +1. Global Colors с префиксом `DP`. +2. Global Fonts `DP H1`, `DP H2`, `DP H3`, `DP Body`, `DP Button`. +3. CSS-переменные `--dp-*`. +4. Классы кнопок `dp-btn-primary`, `dp-btn-secondary`, `dp-btn-sm`. +5. Класс карточки `dp-card`. +6. Класс формы `dp-form`. +7. Классы тегов `dp-tag`, `dp-tag-filled`, `dp-tag-outline`. +8. Тестовую страницу `UI Kit Preview`. + +После этого можно спокойно двигаться к Header, Footer, каталогу и product templates. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1715177 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1652 @@ +{ + "name": "dp-trade-ui-kit", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dp-trade-ui-kit", + "version": "1.0.0", + "devDependencies": { + "@11ty/eleventy": "^3.0.0" + } + }, + "node_modules/@11ty/dependency-tree": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree/-/dependency-tree-4.0.2.tgz", + "integrity": "sha512-RTF6VTZHatYf7fSZBUN3RKwiUeJh5dhWV61gDPrHhQF2/gzruAkYz8yXuvGLx3w3ZBKreGrR+MfYpSVkdbdbLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1" + } + }, + "node_modules/@11ty/dependency-tree-esm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree-esm/-/dependency-tree-esm-2.0.4.tgz", + "integrity": "sha512-MYKC0Ac77ILr1HnRJalzKDlb9Z8To3kXQCltx299pUXXUFtJ1RIONtULlknknqW8cLe19DLVgmxVCtjEFm7h0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.7", + "acorn": "^8.15.0", + "dependency-graph": "^1.0.0", + "normalize-path": "^3.0.0" + } + }, + "node_modules/@11ty/eleventy": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@11ty/eleventy/-/eleventy-3.1.5.tgz", + "integrity": "sha512-hZ0g6MwZyRxCqXsPm82gIM304LraKbUz3ZmezOSjsqxttZG6cHTib3Qq8QkESJoKwnr+yX1eyfOkPC5/mEgZnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/dependency-tree": "^4.0.2", + "@11ty/dependency-tree-esm": "^2.0.4", + "@11ty/eleventy-dev-server": "^2.0.8", + "@11ty/eleventy-plugin-bundle": "^3.0.7", + "@11ty/eleventy-utils": "^2.0.7", + "@11ty/lodash-custom": "^4.17.21", + "@11ty/posthtml-urls": "^1.0.2", + "@11ty/recursive-copy": "^4.0.4", + "@sindresorhus/slugify": "^2.2.1", + "bcp-47-normalize": "^2.3.0", + "chokidar": "^3.6.0", + "debug": "^4.4.3", + "dependency-graph": "^1.0.0", + "entities": "^6.0.1", + "filesize": "^10.1.6", + "gray-matter": "^4.0.3", + "iso-639-1": "^3.1.5", + "js-yaml": "^4.1.1", + "kleur": "^4.1.5", + "liquidjs": "^10.25.0", + "luxon": "^3.7.2", + "markdown-it": "^14.1.1", + "minimist": "^1.2.8", + "moo": "0.5.2", + "node-retrieve-globals": "^6.0.1", + "nunjucks": "^3.2.4", + "picomatch": "^4.0.3", + "please-upgrade-node": "^3.2.0", + "posthtml": "^0.16.7", + "posthtml-match-helper": "^2.0.3", + "semver": "^7.7.4", + "slugify": "^1.6.8", + "tinyglobby": "^0.2.15" + }, + "bin": { + "eleventy": "cmd.cjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-dev-server": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-dev-server/-/eleventy-dev-server-2.0.8.tgz", + "integrity": "sha512-15oC5M1DQlCaOMUq4limKRYmWiGecDaGwryr7fTE/oM9Ix8siqMvWi+I8VjsfrGr+iViDvWcH/TVI6D12d93mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1", + "chokidar": "^3.6.0", + "debug": "^4.4.0", + "finalhandler": "^1.3.1", + "mime": "^3.0.0", + "minimist": "^1.2.8", + "morphdom": "^2.7.4", + "please-upgrade-node": "^3.2.0", + "send": "^1.1.0", + "ssri": "^11.0.0", + "urlpattern-polyfill": "^10.0.0", + "ws": "^8.18.1" + }, + "bin": { + "eleventy-dev-server": "cmd.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-plugin-bundle": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-bundle/-/eleventy-plugin-bundle-3.0.7.tgz", + "integrity": "sha512-QK1tRFBhQdZASnYU8GMzpTdsMMFLVAkuU0gVVILqNyp09xJJZb81kAS3AFrNrwBCsgLxTdWHJ8N64+OTTsoKkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.2", + "debug": "^4.4.0", + "posthtml-match-helper": "^2.0.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-utils": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-utils/-/eleventy-utils-2.0.7.tgz", + "integrity": "sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/lodash-custom": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@11ty/lodash-custom/-/lodash-custom-4.17.21.tgz", + "integrity": "sha512-Mqt6im1xpb1Ykn3nbcCovWXK3ggywRJa+IXIdoz4wIIK+cvozADH63lexcuPpGS/gJ6/m2JxyyXDyupkMr5DHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/posthtml-urls": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@11ty/posthtml-urls/-/posthtml-urls-1.0.3.tgz", + "integrity": "sha512-1YvhnkaNlFnnJic1rBMWmTC2adbuy+JQiBfl1Hecr1Wjjik1pQZmGyk/eC9zKX/FQv52s2Nht1Gi/UwhYqrBeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "evaluate-value": "^2.0.0", + "http-equiv-refresh": "^2.0.1", + "list-to-array": "^1.1.0", + "parse-srcset": "^1.0.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@11ty/recursive-copy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@11ty/recursive-copy/-/recursive-copy-4.0.4.tgz", + "integrity": "sha512-oI7m8pa7/IAU/3lqRU9vjBbs20iKFo7x+1K9kT3aVira6scc1X9MjBdgLCHzLJeJ7iB6wydioA+kr9/qPnvmlQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "errno": "^1.0.0", + "junk": "^3.1.0", + "minimatch": "^3.1.5", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sindresorhus/slugify": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", + "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^1.0.0", + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/transliterate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-normalize": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", + "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bcp-47": "^2.0.0", + "bcp-47-match": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz", + "integrity": "sha512-3zV5mFS1E8/1bPxt/B0xxzI1snsg3uSCIh6Zo1qKg6iMw93hzPANk9oBFzSFBFrwuVoQuE3rLoouAUfwOAj1wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm-import-transformer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/esm-import-transformer/-/esm-import-transformer-3.0.5.tgz", + "integrity": "sha512-1GKLvfuMnnpI75l8c6sHoz0L3Z872xL5akGuBudgqTDPv4Vy6f2Ec7jEMKTxlqWl/3kSvNbHELeimJtnqgYniw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/evaluate-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/evaluate-value/-/evaluate-value-2.0.0.tgz", + "integrity": "sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-equiv-refresh": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz", + "integrity": "sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/iso-639-1": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-3.1.5.tgz", + "integrity": "sha512-gXkz5+KN7HrG0Q5UGqSMO2qB9AsbEeyLP54kF1YrMsIxmu+g4BdB7rflReZTSTZGpfj8wywu6pfPBCylPIzGQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/liquidjs": { + "version": "10.25.6", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.25.6.tgz", + "integrity": "sha512-h5ki5HS1PiL9/NmLw3iUcTF1jQswKJd8KLEXNrtSf8XHF0v3c5+d+8llz3N9I5IUdc5rsOuVLb9AVnqvqqscPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^10.0.0" + }, + "bin": { + "liquid": "bin/liquid.js", + "liquidjs": "bin/liquid.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/liquidjs" + } + }, + "node_modules/list-to-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", + "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/morphdom": { + "version": "2.7.8", + "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.8.tgz", + "integrity": "sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-retrieve-globals": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/node-retrieve-globals/-/node-retrieve-globals-6.0.1.tgz", + "integrity": "sha512-j0DeFuZ/Wg3VlklfbxUgZF/mdHMTEiEipBb3q0SpMMbHaV3AVfoUQF8UGxh1s/yjqO0TgRZd4Pi/x2yRqoQ4Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "acorn-walk": "^8.3.4", + "esm-import-transformer": "^3.0.3" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/posthtml": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.7.tgz", + "integrity": "sha512-7Hc+IvlQ7hlaIfQFZnxlRl0jnpWq2qwibORBhQYIb0QbNtuicc5ZxvKkVT71HJ4Py1wSZ/3VR1r8LfkCtoCzhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-match-helper": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.3.tgz", + "integrity": "sha512-p9oJgTdMF2dyd7WE54QI1LvpBIkNkbSiiECKezNnDVYhGhD1AaOnAkw0Uh0y5TW+OHO8iBdSqnd8Wkpb6iUqmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" + } + }, + "node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slugify": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ssri": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-11.0.0.tgz", + "integrity": "sha512-aZpUoMN/Jj2MqA4vMCeiKGnc/8SuSyHbGSBdgFbZxP8OJGF/lFkIuElzPxsN0q8TQQ+prw3P4EDfB3TBHHgfXw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..de1f2e5 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "dp-trade-ui-kit", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "eleventy --serve", + "build": "eleventy" + }, + "devDependencies": { + "@11ty/eleventy": "^3.0.0" + }, + "type": "module" +} diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk new file mode 100644 index 0000000..5c07625 --- /dev/null +++ b/src/_includes/layouts/base.njk @@ -0,0 +1,16 @@ + + + + + + {{ title }} + + + + + + + {{ content | safe }} + + + diff --git a/src/_includes/layouts/default.njk b/src/_includes/layouts/default.njk new file mode 100644 index 0000000..a7267ee --- /dev/null +++ b/src/_includes/layouts/default.njk @@ -0,0 +1,8 @@ +--- +layout: layouts/base +--- +
+ {% include "partials/header.njk" %} + {{ content | safe }} + {% include "partials/footer.njk" %} +
diff --git a/src/_includes/layouts/ui-kit.njk b/src/_includes/layouts/ui-kit.njk new file mode 100644 index 0000000..60a8207 --- /dev/null +++ b/src/_includes/layouts/ui-kit.njk @@ -0,0 +1,5 @@ +--- +layout: layouts/base +css: ui-kit +--- +{{ content | safe }} diff --git a/src/_includes/partials/footer.njk b/src/_includes/partials/footer.njk new file mode 100644 index 0000000..f993954 --- /dev/null +++ b/src/_includes/partials/footer.njk @@ -0,0 +1,73 @@ + diff --git a/src/_includes/partials/header.njk b/src/_includes/partials/header.njk new file mode 100644 index 0000000..c72a9cc --- /dev/null +++ b/src/_includes/partials/header.njk @@ -0,0 +1,253 @@ + diff --git a/src/about.njk b/src/about.njk new file mode 100644 index 0000000..953242b --- /dev/null +++ b/src/about.njk @@ -0,0 +1,46 @@ +--- +title: "DP Trade — О компании" +layout: layouts/default +permalink: /about.html +bodyClass: compact-type +--- +
+
+
+
+

О компании

+

DP Trade — территория качественного вина

+

Импорт, каталог, персональная работа с клиентами, собственные склады в регионах и доставка собственным транспортом.

+
+ +
+
+ +
+
+
+

DP Trade развивает профессиональный винный каталог, где регионы, производители, партии и коммерческие условия собраны в едином интерфейсе для быстрых закупочных решений.

+

Главная ценность сервиса — соединить сильный ассортимент с понятной навигацией: от страны и апелласьона до конкретного производителя, винтажа и карточки товара.

+

Как устроен подход

+

Компания делает акцент на удобном каталоге, персональном отношении, собственных складских возможностях и доставке собственным транспортом. Для B2B-клиентов это значит меньше ручных уточнений и быстрее путь от выбора до заказа.

+
+
+
01

Удобный каталог

Фильтры по типу, региону, производителю, сорту, году, объему и стилю.

+
02

Персональный подход

Быстрая коммуникация с менеджером и подборки под формат клиента.

+
03

Склады в регионах

Инфраструктура для регулярных поставок и управления доступностью.

+
04

Собственная доставка

Контроль логистики и аккуратная работа с профессиональными заказами.

+
+
+
+ +
+
+

Portfolio

Винные дома и регионы

+

Страница показывает, как может выглядеть корпоративный раздел: спокойная подача, крупные тезисы и блок преимуществ без перегруза.

+
+
+
diff --git a/src/article-guidelines.njk b/src/article-guidelines.njk new file mode 100644 index 0000000..fc3b260 --- /dev/null +++ b/src/article-guidelines.njk @@ -0,0 +1,112 @@ +--- +title: "DP Trade — Article Guidelines" +layout: layouts/default +permalink: /article-guidelines.html +bodyClass: compact-type +--- +
+
+
+
+

Editorial guidelines

+

Рекомендации по статьям DP Trade

+

Требования к структуре материала, заголовкам, тексту и фотографиям для новостей, историй производителей и экспертных заметок.

+
+ +
+
+ +
+
+
+ 01 +

Структура статьи

+

Каждый материал должен быстро отвечать на три вопроса: о ком/о чём статья, почему это важно для аудитории DP Trade и какое действие читатель может сделать дальше.

+
    +
  • Заголовок: конкретный, с именем производителя, региона или события.
  • +
  • Лид: 1-2 предложения, раскрывает главный повод.
  • +
  • Основной текст: 3-5 смысловых блоков с подзаголовками или визуальными паузами.
  • +
  • Финал: вывод, рекомендация, ссылка в каталог или повод обратиться к менеджеру.
  • +
+
+
+ 02 +

Заголовки

+

Заголовок должен быть редакционным, но полезным: не только красивым, а ещё и объясняющим тему.

+
    +
  • Оптимально: 55-90 символов.
  • +
  • Использовать имена: Villa Raiano, Gaja, Bordeaux, Fiano.
  • +
  • Избегать пустых формул: «уникальная история», «легендарное событие» без факта.
  • +
  • Подзаголовки должны вести читателя по смыслу, а не повторять заголовок.
  • +
+
+
+ 03 +

Текст

+

Стиль: профессиональный, спокойный, без рекламного нажима. Пишем для закупщиков, сомелье, ресторанов и розницы.

+
    +
  • Абзац: 350-650 знаков.
  • +
  • Лид: до 280 знаков.
  • +
  • Новость: 3 000-5 500 знаков.
  • +
  • История производителя: 5 000-8 000 знаков.
  • +
  • Цифры, годы, награды и сорта проверять отдельно.
  • +
+
+
+ 04 +

Фотографии

+

Фотографии должны показывать реальный продукт, место, людей или процесс. Лучше меньше декоративности и больше конкретики.

+
    +
  • Hero: горизонтальное фото от 1600px по ширине.
  • +
  • Внутренние фото: от 1200px, без сильной компрессии.
  • +
  • Для карточек: предмет или бутылка должны быть читаемы на мобильном.
  • +
  • Не использовать тёмные, размытые, случайно обрезанные изображения.
  • +
  • Обязательно писать alt: кто/что изображено и где.
  • +
+
+
+ 05 +

Композиция

+

Для длинной статьи нужны визуальные паузы: крупное фото после лида, цитата или факт-блок в середине и финальный акцент.

+
    +
  • Не ставить подряд больше 4 текстовых абзацев без паузы.
  • +
  • Цитаты использовать только если они усиливают материал.
  • +
  • Сайдбар может содержать факты: страна, регион, сорт, год, награда.
  • +
  • Финальный CTA должен быть связан с каталогом или менеджером.
  • +
+
+
+ 06 +

SEO и handoff

+

Материал должен быть понятен поиску и разработке: один H1, последовательные H2, корректные alt и прозрачная структура блоков.

+
    +
  • Title: до 60 символов, включает бренд или тему.
  • +
  • Description: 140-160 символов.
  • +
  • URL: латиница, короткий slug.
  • +
  • Изображения называть по смыслу, а не `photo-final-2`.
  • +
  • В CMS хранить дату, автора/раздел, теги и связанные товары.
  • +
+
+
+
+ +
+
+
+

Pre-publish checklist

+

Проверка перед публикацией

+
+
    +
  • Заголовок отражает конкретный повод и не звучит как реклама.
  • +
  • В лиде понятна ценность материала для профессиональной аудитории.
  • +
  • Все годы, имена, апелласьоны и награды проверены.
  • +
  • Есть минимум 2-4 качественные фотографии с alt-текстами.
  • +
  • Финал ведёт к каталогу, производителю, товару или контакту с менеджером.
  • +
+
+
+
diff --git a/src/assets/images/00073820_1.png b/src/assets/images/00073820_1.png new file mode 100644 index 0000000..9f82d3b Binary files /dev/null and b/src/assets/images/00073820_1.png differ diff --git a/src/assets/images/00080768_1.png b/src/assets/images/00080768_1.png new file mode 100644 index 0000000..0bc9d72 Binary files /dev/null and b/src/assets/images/00080768_1.png differ diff --git a/src/assets/images/00081538_1.png b/src/assets/images/00081538_1.png new file mode 100644 index 0000000..24e149f Binary files /dev/null and b/src/assets/images/00081538_1.png differ diff --git a/src/assets/images/00081726_1.png b/src/assets/images/00081726_1.png new file mode 100644 index 0000000..2c866d3 Binary files /dev/null and b/src/assets/images/00081726_1.png differ diff --git a/src/assets/images/photo_2026-04-06_16-53-23-2.jpg b/src/assets/images/photo_2026-04-06_16-53-23-2.jpg new file mode 100644 index 0000000..d540b6f Binary files /dev/null and b/src/assets/images/photo_2026-04-06_16-53-23-2.jpg differ diff --git a/src/assets/images/photo_2026-04-06_16-53-23.jpg b/src/assets/images/photo_2026-04-06_16-53-23.jpg new file mode 100644 index 0000000..a474acc Binary files /dev/null and b/src/assets/images/photo_2026-04-06_16-53-23.jpg differ diff --git a/src/assets/images/photo_2026-04-06_16-53-24.jpg b/src/assets/images/photo_2026-04-06_16-53-24.jpg new file mode 100644 index 0000000..c327af5 Binary files /dev/null and b/src/assets/images/photo_2026-04-06_16-53-24.jpg differ diff --git a/src/assets/images/photo_2026-04-06_16-53-26.jpg b/src/assets/images/photo_2026-04-06_16-53-26.jpg new file mode 100644 index 0000000..ab03f6b Binary files /dev/null and b/src/assets/images/photo_2026-04-06_16-53-26.jpg differ diff --git a/src/bottle-cards.njk b/src/bottle-cards.njk new file mode 100644 index 0000000..c135734 --- /dev/null +++ b/src/bottle-cards.njk @@ -0,0 +1,232 @@ +--- +title: "DP Trade — Bottle Card Variants" +layout: layouts/default +permalink: /bottle-cards.html +bodyClass: compact-type +--- +
+
+
+
+

UI-kit / Product cards

+

Варианты карточек бутылок

+
+

Отдельная витрина для выбора направления карточки: крупные плитки, компактные версии и горизонтальный формат для B2B-каталога.

+
+ +
+
+

Variant 01

+

Акцентные карточки каталога

+
+
+
+
+ Chateau Laroque Grand Cru +
+
+

Bordeaux

+

Chateau Laroque Grand Cru

+

France · Red dry · 2019 · 0.75 L

+
+ +
+ +
+
+ Brunello di Montalcino +
+
+

Tuscany

+

Brunello di Montalcino

+

Italy · Red dry · 2018 · 0.75 L

+
+ +
+ +
+
+ Riesling Kabinett +
+
+

Mosel

+

Riesling Kabinett

+

Germany · White · 2021 · 0.75 L

+
+ +
+
+
+ +
+
+

Variant 02-04

+

Альтернативные форматы

+
+
+
+
+ Oremus Case of Aszu +
+
+

Clean retail

+

Oremus Case of Aszu 5 Puttonyos

+

Hungary · White sweet · 2000 · 0.5 L

+
+ +
+ +
+
+ Oremus Tokaji Aszu +
+
+

Compact

+

Tokaji Aszu 5 Puttonyos

+

Hungary · 12% · Furmint, Harslevelu

+
+ +
+ +
+
+ Oremus Tokaji Late Harvest +
+
+
+

B2B row card

+

Oremus Tokaji Late Harvest

+

Вино белое полусладкое · Венгрия · 11.5%

+

Сорт: Фурминт, Зета, Харшлевелю

+
+ +
+
+
+
+ +
+
+

Catalog current

+

Варианты текущей карточки каталога

+
+
+
+

Default / как в каталоге

+
+ + Вино белое Oremus, Case of Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Case of Aszu 5 Puttonyos, 0.5 л. 2000

+

Вино белое, Oremus, Венгрия

+

Вино Белое Сладкое
12 %

+

Сорт: Фурминт (70%), Харшлевелю (28%), Мускат (2%)

+
+
+ 19 240 ₽ + В избранное +
+
+
+ +
+

Compact / меньше высота

+
+ + Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000

+

Вино белое, Oremus, Венгрия

+

Сладкое · 12% · Фурминт, Харшлевелю, Мускат

+
+
+ 19 240 ₽ + В избранное +
+
+
+ +
+

Hover / активная строка

+
+ + Вино белое Oremus, Tokaji Late Harvest, 0.5 л. 2021 + +
+

Вино белое Oremus, Tokaji Late Harvest, 0.5 л. 2021

+

Вино белое, Oremus, Венгрия

+

Вино Белое Полусладкое
11.5 %

+

Сорт: Фурминт, Зета, Харшлевелю

+
+
+ 4 980 ₽ + Подробнее +
+
+
+ +
+

Color image / цветной фон фото

+
+ + Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000

+

Вино белое, Oremus, Венгрия

+

Вино Белое Сладкое
12 %

+

Сорт: Фурминт (70%), Харшлевелю (28%), Мускат (2%)

+
+
+ 19 240 ₽ + В избранное +
+
+
+ +
+

B2B dense / больше данных

+
+ + Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000

+

Венгрия · Tokaj · Oremus · 0.5 л · 12%

+
+ Тип: белое сладкое + Сорт: Фурминт 70% + Упаковка: 6 шт. + Артикул: 00073820 +
+
+
+ 19 240 ₽ + В избранное +
+
+
+
+
+
+
diff --git a/src/catalog.njk b/src/catalog.njk new file mode 100644 index 0000000..a442a09 --- /dev/null +++ b/src/catalog.njk @@ -0,0 +1,80 @@ +--- +title: "DP Trade — Catalog" +layout: layouts/default +permalink: /catalog.html +bodyClass: compact-type +--- +
+
+
+
+

Catalog / Country

+

Венгрия

+
+ +
+ +
+ Всего найдено: 22 + +
+ +
+
+ + Вино белое Oremus, Case of Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Case of Aszu 5 Puttonyos, 0.5 л. 2000

+

Вино белое, Oremus, Венгрия

+

Вино Белое Сладкое
12 %

+

Сорт: Фурминт (70%), Харшлевелю (28%), Мускат (2%)

+
+
+ 19 240 ₽ + В избранное +
+
+ +
+ + Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000 + +
+

Вино белое Oremus, Tokaji Aszu 5 Puttonyos, 0.5 л. 2000

+

Вино белое, Oremus, Венгрия

+

Вино Белое Сладкое
12 %

+

Сорт: Фурминт (70%), Харшлевелю (28%), Мускат (2%)

+
+
+ 19 240 ₽ + В избранное +
+
+ +
+ + Вино белое Oremus, Tokaji Late Harvest, 0.5 л. 2021 + +
+

Вино белое Oremus, Tokaji Late Harvest, 0.5 л. 2021

+

Вино белое, Oremus, Венгрия

+

Вино Белое Полусладкое
11.5 %

+

Сорт: Фурминт, Зета, Харшлевелю

+
+
+ 4 980 ₽ + В избранное +
+
+
+
+
diff --git a/src/contacts-auth.njk b/src/contacts-auth.njk new file mode 100644 index 0000000..d0c3933 --- /dev/null +++ b/src/contacts-auth.njk @@ -0,0 +1,61 @@ +--- +title: "DP Trade — Контакты / Auth Gate" +layout: layouts/default +permalink: /contacts-auth.html +bodyClass: compact-type +--- +
+
+
+
+

Контакты

+

Связаться с DP Trade

+

Контакты открыты для всех, но заявка менеджеру доступна только зарегистрированным или залогиненным пользователям.

+
+ +
+
+ +
+
+
+
+ Телефон + +7 (495) 937-94-60 +

Для консультаций по ассортименту, поставкам и условиям сотрудничества.

+
+
+ Email + dptr@dp-trade.ru +

Удобно для запросов прайса, карточек производителей и B2B-документов.

+
+
+ Юридическая информация +

Интернет-витрина размещает информацию об алкогольной продукции исключительно в ознакомительных целях. Дистанционная продажа алкогольной продукции не осуществляется.

+
+
+
+
Требуется аккаунт
+

Заявка доступна после входа

+

Мы показываем телефон и email открыто, но форму заявки менеджеру оставляем внутри личного кабинета: так менеджер сразу видит компанию, историю запросов и коммерческий статус клиента.

+ +
+ После входа откроется: + форма заявки, автозаполнение контактов, привязка к компании и история обращений. +
+
+ + + +
+
+
+
+
diff --git a/src/contacts.njk b/src/contacts.njk new file mode 100644 index 0000000..92f523e --- /dev/null +++ b/src/contacts.njk @@ -0,0 +1,50 @@ +--- +title: "DP Trade — Контакты" +layout: layouts/default +permalink: /contacts.html +bodyClass: compact-type +--- +
+
+
+
+

Контакты

+

Связаться с DP Trade

+

Для вопросов по каталогу, ассортименту, поставкам и работе с менеджером используйте телефон, почту или форму заявки.

+
+ +
+
+ +
+
+
+
+ Телефон + +7 (495) 937-94-60 +

Для консультаций по ассортименту, поставкам и условиям сотрудничества.

+
+
+ Email + dptr@dp-trade.ru +

Удобно для запросов прайса, карточек производителей и B2B-документов.

+
+
+ Юридическая информация +

Интернет-витрина размещает информацию об алкогольной продукции исключительно в ознакомительных целях. Дистанционная продажа алкогольной продукции не осуществляется.

+
+
+
+

Заявка менеджеру

+ + + + +
+
+
+
diff --git a/src/css/site.css b/src/css/site.css new file mode 100644 index 0000000..9e441e7 --- /dev/null +++ b/src/css/site.css @@ -0,0 +1,2541 @@ +@import url("tokens.css"); + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + background: var(--color-background-base); + color: var(--color-neutral-black); + font-family: var(--font-body); + font-size: 16px; + line-height: 1.5; +} + +img { + display: block; + max-width: 100%; +} + +a { + color: inherit; + text-decoration: none; +} + +button, +input, +select { + font: inherit; +} + +.site-shell { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.container { + width: min(100% - 40px, var(--container)); + margin: 0 auto; +} + +.site-header { + position: sticky; + top: 0; + z-index: 20; + background: rgba(248, 250, 252, 0.94); + border-bottom: 1px solid rgba(102, 96, 95, 0.18); + box-shadow: 0 10px 28px rgba(22, 22, 22, 0.05); + backdrop-filter: blur(18px); +} + +.header-top { + display: grid; + grid-template-columns: 170px minmax(260px, 1fr) auto; + align-items: center; + gap: 20px; + min-height: 72px; +} + +.brand-logo { + position: relative; + display: inline-block; + width: fit-content; + color: var(--color-accent-blue); + font-family: var(--font-heading-retail); + font-size: 26px; + font-weight: 800; + letter-spacing: 0; + line-height: 0.9; + text-transform: uppercase; +} + +.brand-logo span:first-child { + color: var(--color-primary-wine-80); +} + +.brand-logo small { + position: absolute; + left: 54px; + top: 24px; + color: var(--color-primary-wine-80); + font-size: 8px; + font-weight: 700; + white-space: nowrap; +} + +.search-bar { + display: grid; + grid-template-columns: 44px minmax(0, 1fr); + align-items: center; + min-height: 44px; + border: 1px solid rgba(102, 96, 95, 0.24); + border-radius: var(--radius-sm); + background: var(--color-surface); +} + +.search-bar:focus-within { + border-color: var(--color-primary-wine-100); + box-shadow: 0 0 0 4px rgba(75, 15, 36, 0.08); +} + +.search-bar button { + width: 44px; + height: 42px; + border: 0; + background: transparent; + color: var(--color-primary-wine-100); + font-size: 18px; + cursor: pointer; +} + +.search-bar input { + min-width: 0; + border: 0; + outline: 0; + color: var(--color-neutral-black); + font-size: 14px; +} + +.header-actions { + display: flex; + align-items: center; + gap: 10px; +} + +.phone-link { + color: var(--color-accent-blue); + font-size: 15px; + font-weight: 800; + white-space: nowrap; +} + +.header-icon { + width: 38px; + height: 38px; + border: 1px solid rgba(75, 15, 36, 0.14); + border-radius: var(--radius-sm); + background: transparent; + color: var(--color-primary-wine-100); + display: inline-grid; + place-items: center; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease; +} + +.header-icon:hover { + border-color: rgba(75, 15, 36, 0.36); + background: rgba(75, 15, 36, 0.06); + transform: translateY(-1px); +} + +.header-icon svg { + width: 20px; + height: 20px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.45; +} + +.header-icon--air { + border-color: rgba(75, 15, 36, 0.13); + background: transparent; +} + +.main-nav { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 8px; + min-height: 52px; + overflow-x: auto; + border-top: 1px solid rgba(102, 96, 95, 0.12); +} + +.main-nav > a, +.nav-trigger { + display: inline-flex; + align-items: center; + gap: 7px; + min-height: 34px; + padding: 0 2px; + border: 0; + border-bottom: 2px solid transparent; + border-radius: 0; + background: transparent; + color: var(--color-neutral-gray-700); + font-size: 12px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; + cursor: pointer; + white-space: nowrap; +} + +.main-nav > a:hover, +.nav-item:hover .nav-trigger, +.nav-item:focus-within .nav-trigger { + border-bottom-color: var(--color-primary-wine-100); + background: transparent; + color: var(--color-primary-wine-100); +} + +.nav-chevron { + width: 10px; + height: 10px; + display: inline-grid; + place-items: center; + line-height: 0; +} + +.nav-chevron svg { + width: 9px; + height: 6px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.6; +} + +.nav-item { + position: static; +} + +.nav-item::after { + content: ""; + position: fixed; + left: 0; + right: 0; + top: 102px; + z-index: 19; + display: none; + height: 34px; +} + +.mega-menu { + position: absolute; + left: 50%; + top: 118px; + width: min(var(--container), calc(100vw - 40px)); + max-height: calc(100vh - 142px); + overflow: auto; + padding: 22px; + border: 1px solid rgba(102, 96, 95, 0.18); + background: #f8fafc; + box-shadow: var(--shadow-lift); + transform: translateX(-50%); + display: none; +} + +.nav-item:hover::after, +.nav-item:focus-within::after, +.nav-item:hover .mega-menu, +.nav-item:focus-within .mega-menu { + display: block; +} + +.mega-intro { + display: grid; + grid-template-columns: minmax(220px, 0.7fr) minmax(320px, 1fr); + gap: 18px 28px; + align-items: end; + padding-bottom: 18px; + border-bottom: 1px solid rgba(102, 96, 95, 0.18); +} + +.mega-intro h2 { + font-size: 26px; + font-weight: 800; + text-transform: uppercase; +} + +.eyebrow, +.section-title, +.muted-caps { + margin: 0; + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; +} + +.mega-intro h2, +.section-heading h2, +.hero h1, +.product-card h3 { + margin: 0; + font-family: var(--font-heading); + line-height: 1.08; +} + +.mega-intro p:last-child { + margin: 0; + color: var(--color-neutral-gray-600); +} + +.menu-grid { + display: grid; + grid-template-columns: 1.05fr 0.82fr 1.25fr 0.88fr; + gap: 22px; + padding-top: 22px; +} + +.menu-column { + display: flex; + flex-direction: column; + gap: 10px; + min-width: 0; +} + +.menu-column a { + width: fit-content; + max-width: 100%; + color: var(--color-neutral-gray-700); + font-size: 14px; + font-weight: 600; +} + +.menu-column a:hover { + color: var(--color-primary-wine-80); +} + +.visual-column { + gap: 12px; +} + +.visual-column img { + width: 100%; + aspect-ratio: 4 / 3; + object-fit: cover; + border-radius: var(--radius-sm); +} + +.visual-column p { + margin: 0; + color: var(--color-neutral-gray-600); + font-size: 13px; + line-height: 1.42; +} + +.appellations { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 9px 18px; + align-content: start; +} + +.appellations .section-title { + grid-column: 1 / -1; + margin-bottom: 0; +} + +.appellation-group { + display: flex; + flex-direction: column; + gap: 9px; +} + +.country-link { + font-weight: 800; + text-transform: uppercase; +} + +.popular-list, +.hero-actions, +.product-footer { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12px; +} + +.popular-list a, +.tag { + min-height: 34px; + padding: 7px 12px; + border: 1px solid rgba(75, 15, 36, 0.18); + border-radius: var(--radius-sm); + background: var(--color-surface); + color: var(--color-primary-wine-100); + font-size: 13px; + font-weight: 700; +} + +.tag--filled { + background: var(--color-primary-wine-100); + color: var(--color-surface); +} + +.button { + min-height: 48px; + padding: 12px 22px; + border: 1px solid transparent; + border-radius: var(--radius-sm); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + font-weight: 800; + cursor: pointer; +} + +.button--primary { + background: var(--color-primary-wine-100); + color: var(--color-surface); + box-shadow: 0 10px 22px rgba(75, 15, 36, 0.16); +} + +.button--secondary { + border-color: rgba(75, 15, 36, 0.24); + color: var(--color-primary-wine-100); + background: rgba(248, 250, 252, 0.78); +} + +.button--sm { + min-height: 38px; + padding: 8px 14px; + font-size: 14px; +} + +.hero { + min-height: calc(100vh - 124px); + display: grid; + align-items: end; + padding: 104px 0 72px; + background: + linear-gradient(100deg, rgba(22, 20, 17, 0.84) 0%, rgba(22, 20, 17, 0.58) 38%, rgba(22, 20, 17, 0.12) 72%), + url("https://images.unsplash.com/photo-1560493676-04071c5f467b?auto=format&fit=crop&w=1800&q=80"); + background-position: center right; + background-size: cover; + color: #f8fafc; +} + +.hero-copy { + width: min(100% - 40px, var(--container)); + max-width: none; + margin: 0 auto; + display: grid; + grid-template-columns: minmax(0, 0.62fr) minmax(220px, 0.38fr); +} + +.hero-copy > * { + grid-column: 1; +} + +.hero h1 { + margin: 12px 0 20px; + max-width: 860px; + font-size: clamp(44px, 6vw, 78px); + font-weight: 800; + text-transform: uppercase; +} + +.hero p:not(.eyebrow) { + max-width: 610px; + color: rgba(255, 253, 250, 0.84); + font-size: 18px; +} + +.section { + padding: 80px 0; +} + +.section-heading { + display: grid; + gap: 8px; + margin-bottom: 32px; +} + +.section-heading--split { + grid-template-columns: minmax(0, 0.9fr) minmax(280px, 0.7fr); + gap: 28px; + align-items: end; +} + +.section-heading--split > p { + margin: 0; + color: var(--color-neutral-gray-600); +} + +.section-heading h2 { + font-size: clamp(32px, 4vw, 50px); + font-weight: 800; + text-transform: uppercase; +} + +.producer-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; +} + +.producer-card { + min-height: 148px; + padding: 20px; + border: 1px solid rgba(102, 96, 95, 0.14); + border-radius: var(--radius-sm); + background: var(--color-surface); + display: grid; + align-content: space-between; + transition: border-color 0.18s ease, transform 0.18s ease; +} + +.producer-card:hover { + border-color: rgba(75, 15, 36, 0.34); + transform: translateY(-2px); +} + +.producer-card span, +.news-card span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.producer-card strong { + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: 24px; + line-height: 1.14; + text-transform: uppercase; +} + +.news-section { + background: #eef2f6; +} + +.news-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.news-card { + min-width: 0; + border-radius: var(--radius-sm); + background: var(--color-surface); + overflow: hidden; + box-shadow: var(--shadow-soft); +} + +.news-card > div:last-child { + padding: 18px; + display: grid; + gap: 8px; +} + +.news-card h3 { + margin: 0; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: 20px; + line-height: 1.2; + text-transform: uppercase; +} + +.news-card__image { + min-height: 190px; + background-position: center; + background-size: cover; +} + +.news-card__image--catena { + background-image: linear-gradient(rgba(22, 22, 22, 0.1), rgba(22, 22, 22, 0.1)), url("https://images.unsplash.com/photo-1556760544-74068565f05c?auto=format&fit=crop&w=900&q=80"); +} + +.news-card__image--brand { + background-image: linear-gradient(rgba(22, 22, 22, 0.1), rgba(22, 22, 22, 0.1)), url("https://images.unsplash.com/photo-1506377247377-2a5b3b417ebb?auto=format&fit=crop&w=900&q=80"); +} + +.news-card__image--italy { + background-image: linear-gradient(rgba(22, 22, 22, 0.1), rgba(22, 22, 22, 0.1)), url("https://images.unsplash.com/photo-1528823872057-9c018a7a7553?auto=format&fit=crop&w=900&q=80"); +} + +.type-lab-section { + background: #eef2f6; +} + +.type-options { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 18px; +} + +.type-options--five { + grid-template-columns: repeat(5, minmax(0, 1fr)); +} + +.type-card { + min-width: 0; + min-height: 390px; + padding: 24px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 28px; +} + +.type-card.is-selected { + border-color: rgba(75, 15, 36, 0.48); + background: linear-gradient(180deg, #ffffff 0%, #eef2f6 100%); + box-shadow: var(--shadow-lift); +} + +.type-card.is-selected::before { + content: "Выбрано для системы"; + width: fit-content; + padding: 7px 10px; + border-radius: var(--radius-sm); + background: var(--color-primary-wine-100); + color: var(--color-surface); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.type-card.is-selected-soft { + border-color: rgba(185, 150, 91, 0.62); + background: #f7f4ea; +} + +.type-card.is-selected-soft::before { + content: "Новый компактный"; + width: fit-content; + padding: 7px 10px; + border-radius: var(--radius-sm); + background: var(--color-accent-gold); + color: var(--color-neutral-black); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.type-card__meta { + display: flex; + justify-content: space-between; + gap: 14px; + color: var(--color-neutral-gray-600); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.type-card__meta strong { + color: var(--color-primary-wine-100); +} + +.type-card h3 { + margin: 0; + color: var(--color-neutral-black); +} + +.type-card p { + margin: 0; + color: var(--color-neutral-gray-600); +} + +.type-usage { + padding-top: 14px; + border-top: 1px solid rgba(102, 96, 95, 0.14); + display: grid; + gap: 6px; +} + +.type-usage strong { + color: var(--color-primary-wine-100); + font-size: 11px; + font-weight: 800; + text-transform: uppercase; +} + +.type-usage span { + color: var(--color-neutral-gray-600); + font-size: 13px; + line-height: 1.42; +} + +.type-scale { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.type-scale span { + padding: 6px 9px; + border: 1px solid rgba(75, 15, 36, 0.16); + border-radius: var(--radius-sm); + color: var(--color-primary-wine-100); + font-size: 12px; + font-weight: 800; +} + +.type-card--editorial { + font-family: "Manrope", "Inter", Arial, sans-serif; +} + +.type-card--editorial h3 { + font-family: "Cormorant Garamond", Georgia, serif; + font-size: 46px; + font-weight: 700; + line-height: 0.98; +} + +.type-card--neo { + font-family: "Manrope", "Inter", Arial, sans-serif; +} + +.type-card--neo h3 { + font-family: "Manrope", "Inter", Arial, sans-serif; + font-size: 34px; + font-weight: 800; + line-height: 1.08; +} + +.type-card--classic { + font-family: "Inter", Arial, sans-serif; +} + +.type-card--classic h3 { + font-family: "Playfair Display", Georgia, serif; + font-size: 38px; + font-weight: 700; + line-height: 1.04; +} + +.type-card--retail { + font-family: "Inter", Arial, sans-serif; +} + +.type-card--retail h3 { + font-family: "Montserrat", "Inter", Arial, sans-serif; + font-size: 31px; + font-weight: 800; + line-height: 1.14; + text-transform: uppercase; +} + +.type-card--compact { + font-family: "Inter", Arial, sans-serif; +} + +.type-card--compact h3 { + font-family: "Montserrat", "Inter", Arial, sans-serif; + font-size: 25px; + font-weight: 800; + line-height: 1.16; + text-transform: uppercase; +} + +.compact-type { + font-size: 15px; + line-height: 1.46; +} + +.compact-type .section { + padding: 56px 0; +} + +.compact-type .section-heading { + margin-bottom: 24px; +} + +.compact-type .section-heading h2 { + font-size: clamp(28px, 3.2vw, 40px); + line-height: 1.12; +} + +.catalog-section .catalog-layout { + grid-template-columns: 250px minmax(0, 1fr); + gap: 22px; +} + +.compact-type .filters-panel { + padding: 20px; + gap: 12px; +} + +.compact-type .filters-panel h3 { + margin: 0 0 2px; + font-size: 18px; + line-height: 1.2; +} + +.product-grid--compact { + gap: 16px; +} + +.product-grid--compact .product-card { + padding: 14px; + gap: 12px; +} + +.product-grid--compact .product-media { + min-height: 176px; +} + +.product-grid--compact .bottle { + transform: scale(0.82); +} + +.product-grid--compact .product-card h3 { + font-size: 17px; + line-height: 1.22; +} + +.product-grid--compact .product-card p { + font-size: 13px; +} + +.product-grid--compact .product-footer strong { + font-size: 16px; +} + +.product-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; +} + +.product-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); + display: grid; + gap: 16px; +} + +.product-media { + min-height: 220px; + border-radius: var(--radius-sm); + overflow: hidden; + display: grid; + place-items: center; + background: linear-gradient(140deg, #5d1027, #c8a45d); +} + +.product-photo { + width: auto; + max-width: 132px; + height: 190px; + object-fit: contain; + object-position: center; + border: 0; + box-shadow: none; +} + +.product-media--amber { + background: linear-gradient(140deg, #a8632a, #dde4ec); +} + +.product-media--green { + background: linear-gradient(140deg, #1f4d3a, #e8eadb); +} + +.bottle { + width: 54px; + height: 152px; + border-radius: 16px 16px 10px 10px; + background: linear-gradient(90deg, #161616, #2f2a29 44%, #0c0c0c); + box-shadow: 18px 18px 44px rgba(22, 22, 22, 0.24); + position: relative; +} + +.bottle::before { + content: ""; + position: absolute; + top: -58px; + left: 17px; + width: 20px; + height: 72px; + border-radius: 8px 8px 2px 2px; + background: #171212; +} + +.bottle::after { + content: ""; + position: absolute; + inset: 54px 8px auto; + height: 42px; + border-radius: 4px; + background: #eef2f6; +} + +.product-card h3 { + margin-top: 8px; + font-size: 21px; + font-weight: 800; + text-transform: uppercase; +} + +.product-card p { + margin: 6px 0 0; + color: var(--color-neutral-gray-600); +} + +.product-footer { + justify-content: space-between; +} + +.product-footer strong { + color: var(--color-primary-wine-100); + font-size: 18px; +} + +.catalog-layout { + display: grid; + grid-template-columns: 280px minmax(0, 1fr); + gap: 28px; +} + +.catalog-head { + margin-bottom: 28px; + display: grid; + grid-template-columns: minmax(0, 0.8fr) minmax(520px, 1fr); + gap: 24px; + align-items: end; +} + +.catalog-head h1 { + margin: 6px 0 0; + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: clamp(34px, 4vw, 52px); + font-weight: 800; + line-height: 1.12; +} + +.catalog-actions { + display: flex; + align-items: center; + justify-content: flex-end; + flex-wrap: wrap; + gap: 14px; +} + +.catalog-actions > span, +.catalog-toolbar > span { + color: var(--color-neutral-gray-700); + font-size: 17px; +} + +.catalog-toolbar { + margin-bottom: 22px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 18px; +} + +.catalog-sort { + width: min(100%, 320px); + min-height: 40px; + padding: 7px 12px; +} + +.product-list { + display: grid; + gap: 18px; +} + +.product-card--list { + min-height: 250px; + padding: 20px; + grid-template-columns: 210px minmax(0, 1fr) 220px; + gap: 28px; + align-items: center; + border-color: rgba(102, 96, 95, 0.08); +} + +.product-image { + min-height: 214px; + max-height: 224px; + overflow: hidden; + display: grid; + place-items: center; +} + +.product-image img { + width: auto; + max-width: 132px; + height: 208px; + object-fit: contain; + object-position: center; + border: 0; + box-shadow: none; +} + +.product-info { + min-width: 0; + display: grid; + gap: 12px; +} + +.product-info h3 { + margin: 0; + color: var(--color-neutral-black); + font-size: clamp(22px, 2.4vw, 32px); + font-weight: 800; + line-height: 1.18; + text-transform: none; +} + +.product-info p { + margin: 0; + color: var(--color-neutral-gray-600); + font-size: 16px; + line-height: 1.38; +} + +.product-info .product-origin { + font-size: 15px; +} + +.product-buy { + min-height: 170px; + display: grid; + align-content: end; + justify-items: end; + gap: 56px; +} + +.product-buy strong { + color: var(--color-neutral-black); + font-size: 28px; + font-weight: 800; + line-height: 1; + white-space: nowrap; +} + +.product-buy .button { + min-width: 180px; +} + +.card-lab-section { + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.7), rgba(244, 246, 249, 0.96)), + var(--color-background-base); +} + +.card-lab-head { + margin-bottom: 42px; + display: grid; + grid-template-columns: minmax(0, 0.72fr) minmax(320px, 0.42fr); + gap: 32px; + align-items: end; +} + +.card-lab-head h1 { + margin: 8px 0 0; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: clamp(38px, 5vw, 72px); + font-weight: 800; + line-height: 0.98; + text-transform: uppercase; +} + +.card-lab-head > p { + margin: 0; + color: var(--color-neutral-gray-600); + font-size: 18px; + line-height: 1.55; +} + +.card-variant-block { + display: grid; + gap: 18px; +} + +.card-variant-block + .card-variant-block { + margin-top: 48px; +} + +.card-variant-title { + display: flex; + justify-content: space-between; + gap: 24px; + align-items: end; +} + +.card-variant-title h2 { + margin: 2px 0 0; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: clamp(24px, 2.6vw, 34px); + font-weight: 800; +} + +.bottle-card-grid, +.bottle-card-mix { + display: grid; + gap: 20px; +} + +.bottle-card-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.bottle-card-mix { + grid-template-columns: minmax(0, 0.92fr) minmax(0, 0.78fr) minmax(320px, 1.3fr); + align-items: stretch; +} + +.bottle-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.12); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: 0 18px 46px rgba(18, 25, 38, 0.08); + display: grid; + gap: 16px; +} + +.bottle-card__media { + min-height: 224px; + border-radius: var(--radius-sm); + overflow: hidden; + display: grid; + place-items: center; + background: linear-gradient(135deg, #6a1330 0%, #9e6a4e 48%, #d3b966 100%); +} + +.bottle-card__photo { + width: auto; + max-width: 142px; + height: 198px; + object-fit: contain; + object-position: center; + border: 0; + box-shadow: none; +} + +.bottle-card__body { + min-width: 0; +} + +.bottle-card__region { + margin: 0 0 9px; + color: #b59a5a; + font-size: 13px; + font-weight: 800; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.bottle-card h3 { + margin: 0; + color: var(--color-neutral-black); + font-size: clamp(22px, 2.1vw, 28px); + font-weight: 800; + line-height: 1.08; + text-transform: uppercase; +} + +.bottle-card p { + margin: 8px 0 0; + color: var(--color-neutral-gray-600); + font-size: 16px; + line-height: 1.42; +} + +.bottle-card__details { + font-size: 15px; +} + +.bottle-card__footer { + margin-top: 4px; + display: flex; + justify-content: space-between; + gap: 16px; + align-items: center; +} + +.bottle-card__footer strong { + color: var(--color-primary-wine-100); + font-size: 22px; + font-weight: 800; + white-space: nowrap; +} + +.bottle-card__footer .button { + min-width: 132px; +} + +.bottle-card--tuscany .bottle-card__media { + background: linear-gradient(135deg, #b16d2c 0%, #c8ad94 52%, #dfe5eb 100%); +} + +.bottle-card--mosel .bottle-card__media { + background: linear-gradient(135deg, #214f3d 0%, #8aa38e 48%, #e8ebdc 100%); +} + +.bottle-card--clean .bottle-card__media { + background: linear-gradient(135deg, #edf1f5 0%, #d7dee7 100%); +} + +.bottle-card--clean .bottle-card__photo { + height: 214px; +} + +.bottle-card--compact { + align-content: start; +} + +.bottle-card--compact .bottle-card__media { + min-height: 178px; + background: linear-gradient(135deg, #f3f5f8 0%, #dbe2ea 100%); +} + +.bottle-card--compact .bottle-card__photo { + height: 154px; +} + +.bottle-card--compact h3 { + font-size: 20px; +} + +.bottle-card--compact p { + font-size: 15px; +} + +.bottle-card--horizontal { + grid-template-columns: 180px minmax(0, 1fr); + gap: 20px; + align-items: center; +} + +.bottle-card--horizontal .bottle-card__media { + min-height: 230px; + background: linear-gradient(135deg, #e9eef4 0%, #cfd8e3 100%); +} + +.bottle-card--horizontal .bottle-card__photo { + height: 208px; +} + +.bottle-card__content { + min-width: 0; + display: grid; + gap: 24px; +} + +.catalog-card-variants { + display: grid; + gap: 18px; +} + +.catalog-card-sample { + display: grid; + gap: 10px; +} + +.catalog-card-sample__label { + margin: 0; + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; +} + +.product-card--list-compact { + min-height: 198px; + grid-template-columns: 160px minmax(0, 1fr) 190px; + gap: 22px; +} + +.product-card--list-compact .product-image { + min-height: 164px; + max-height: 174px; +} + +.product-card--list-compact .product-image img { + max-width: 104px; + height: 156px; +} + +.product-card--list-compact .product-info { + gap: 8px; +} + +.product-card--list-compact .product-info h3 { + font-size: clamp(19px, 2vw, 25px); +} + +.product-card--list-compact .product-info p { + font-size: 14px; +} + +.product-card--list-compact .product-buy { + min-height: 132px; + gap: 28px; +} + +.product-card--list-hover { + border-color: rgba(75, 15, 36, 0.28); + box-shadow: 0 22px 54px rgba(25, 37, 62, 0.13); + transform: translateY(-2px); +} + +.product-card--list-hover .product-image { + border-radius: var(--radius-sm); + background: linear-gradient(135deg, #eef2f6 0%, #dde6ef 100%); +} + +.product-card--list-hover .button { + border-color: var(--color-primary-wine-100); +} + +.product-card--list-color { + border-color: rgba(185, 150, 91, 0.24); +} + +.product-card--list-color .product-image { + min-height: 214px; + border-radius: var(--radius-sm); +} + +.product-image--gold { + background: linear-gradient(135deg, #b9965b 0%, #d7c18b 48%, #eef2f6 100%); +} + +.product-image--wine { + background: linear-gradient(135deg, #6d1c36 0%, #9b5366 46%, #e6dce1 100%); +} + +.product-image--green { + background: linear-gradient(135deg, #1f4d3a 0%, #88a28e 48%, #eef2e5 100%); +} + +.product-card--list-b2b { + min-height: 226px; + grid-template-columns: 176px minmax(0, 1fr) 190px; + gap: 24px; +} + +.product-card--list-b2b .product-image { + min-height: 184px; + max-height: 194px; +} + +.product-card--list-b2b .product-image img { + max-width: 108px; + height: 178px; +} + +.product-params { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px 14px; +} + +.product-params span { + min-width: 0; + color: var(--color-neutral-gray-600); + font-size: 14px; + line-height: 1.32; +} + +.product-card--list-b2b .product-buy { + min-height: 148px; + gap: 34px; +} + +.content-page { + background: var(--color-background-base); +} + +.page-hero { + padding: 78px 0; + color: #f8fafc; + background: + linear-gradient(100deg, rgba(22, 20, 17, 0.86), rgba(22, 20, 17, 0.48) 54%, rgba(22, 20, 17, 0.22)), + url("https://images.unsplash.com/photo-1506377247377-2a5b3b417ebb?auto=format&fit=crop&w=1800&q=80"); + background-position: center; + background-size: cover; +} + +.page-hero--about { + background-image: + linear-gradient(100deg, rgba(22, 20, 17, 0.84), rgba(22, 20, 17, 0.46) 54%, rgba(22, 20, 17, 0.18)), + url("https://images.unsplash.com/photo-1568213816046-0ee1c42bd559?auto=format&fit=crop&w=1800&q=80"); +} + +.page-hero--contacts { + background-image: + linear-gradient(100deg, rgba(22, 20, 17, 0.86), rgba(22, 20, 17, 0.5) 54%, rgba(22, 20, 17, 0.2)), + url("https://images.unsplash.com/photo-1510812431401-41d2bd2722f3?auto=format&fit=crop&w=1800&q=80"); +} + +.page-hero--guidelines { + background-image: + linear-gradient(100deg, rgba(22, 20, 17, 0.86), rgba(22, 20, 17, 0.5) 54%, rgba(22, 20, 17, 0.22)), + url("https://images.unsplash.com/photo-1516594798947-e65505dbb29d?auto=format&fit=crop&w=1800&q=80"); +} + +.page-hero__inner { + display: grid; + grid-template-columns: minmax(0, 0.72fr) minmax(280px, 0.28fr); + gap: 36px; + align-items: end; +} + +.page-hero h1 { + max-width: 980px; + margin: 10px 0 18px; + font-family: var(--font-heading); + font-size: clamp(40px, 5.6vw, 76px); + font-weight: 800; + line-height: 0.98; + text-transform: uppercase; +} + +.page-hero p { + max-width: 740px; + margin: 0; + font-size: 19px; + line-height: 1.55; +} + +.page-hero__meta, +.info-card, +.feature-card, +.contact-panel, +.contact-form { + border: 1px solid rgba(217, 222, 229, 0.9); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); +} + +.page-hero__meta { + padding: 22px; + color: var(--color-neutral-black); +} + +.page-hero__meta span, +.info-card span, +.feature-card span, +.contact-panel span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.page-hero__meta strong { + display: block; + margin: 10px 0 8px; + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: 26px; + line-height: 1.1; + text-transform: uppercase; +} + +.page-hero__meta p { + color: var(--color-neutral-gray-600); + font-size: 15px; + line-height: 1.45; +} + +.article-layout, +.contacts-layout { + display: grid; + grid-template-columns: minmax(0, 0.68fr) minmax(300px, 0.32fr); + gap: 34px; + align-items: start; +} + +.about-grid { + display: grid; + grid-template-columns: minmax(0, 0.58fr) minmax(360px, 0.42fr); + gap: 34px; + align-items: start; +} + +.article-body { + max-width: 860px; +} + +.article-body .lead { + color: var(--color-neutral-black); + font-size: 22px; + line-height: 1.48; +} + +.article-body h2 { + margin: 34px 0 12px; + font-family: var(--font-heading); + font-size: clamp(28px, 3vw, 40px); + font-weight: 800; + line-height: 1.08; + text-transform: uppercase; +} + +.article-body p { + color: var(--color-neutral-gray-600); + font-size: 17px; + line-height: 1.72; +} + +.article-body blockquote { + margin: 30px 0; + padding: 22px 24px; + border-left: 4px solid var(--color-primary-wine-100); + background: #eef2f6; + color: var(--color-neutral-black); + font-size: 20px; + font-weight: 700; + line-height: 1.45; +} + +.article-aside, +.contact-stack { + display: grid; + gap: 16px; +} + +.info-card { + padding: 22px; +} + +.info-card dl { + margin: 18px 0 0; + display: grid; + gap: 12px; +} + +.info-card dl div { + display: flex; + justify-content: space-between; + gap: 18px; + padding-bottom: 10px; + border-bottom: 1px solid rgba(102, 96, 95, 0.14); +} + +.info-card dt { + color: var(--color-neutral-gray-600); +} + +.info-card dd { + margin: 0; + color: var(--color-neutral-black); + font-weight: 800; + text-align: right; +} + +.info-card--accent { + background: #eef2f6; +} + +.info-card--accent p { + color: var(--color-neutral-gray-600); + line-height: 1.55; +} + +.feature-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; +} + +.feature-card { + min-height: 210px; + padding: 22px; + display: grid; + align-content: space-between; +} + +.feature-card h3 { + margin: 18px 0 8px; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: 22px; + text-transform: uppercase; +} + +.feature-card p, +.contact-panel p { + margin: 0; + color: var(--color-neutral-gray-600); + line-height: 1.55; +} + +.muted-section { + background: #eef2f6; +} + +.contact-panel, +.contact-form { + padding: 24px; +} + +.contact-panel a { + display: block; + margin: 8px 0 10px; + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: clamp(24px, 3vw, 34px); + font-weight: 800; + line-height: 1.1; +} + +.contact-form { + display: grid; + gap: 16px; +} + +.contact-form h2 { + margin: 0; + font-family: var(--font-heading); + font-size: 30px; + text-transform: uppercase; +} + +.contact-form label { + display: grid; + gap: 7px; + color: var(--color-neutral-gray-700); + font-weight: 800; +} + +.contact-form textarea.input { + min-height: 132px; + resize: vertical; +} + +.contact-auth-gate { + position: relative; + overflow: hidden; +} + +.contact-auth-gate::before { + content: ""; + position: absolute; + inset: 0 0 auto; + height: 6px; + background: linear-gradient(90deg, var(--color-primary-wine-100), var(--color-accent-gold)); +} + +.auth-gate__badge { + width: fit-content; + padding: 7px 10px; + border-radius: var(--radius-sm); + background: rgba(75, 15, 36, 0.08); + color: var(--color-primary-wine-100); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.contact-auth-gate > p { + margin: 0; + color: var(--color-neutral-gray-600); + line-height: 1.62; +} + +.auth-gate__actions { + display: flex; + flex-wrap: wrap; + gap: 12px; +} + +.auth-gate__note { + padding: 16px; + border: 1px solid rgba(185, 150, 91, 0.28); + border-radius: var(--radius-sm); + background: #f8fafc; + display: grid; + gap: 6px; +} + +.auth-gate__note strong { + color: var(--color-neutral-black); +} + +.auth-gate__note span { + color: var(--color-neutral-gray-600); + line-height: 1.48; +} + +.locked-form-preview { + padding-top: 16px; + border-top: 1px solid rgba(102, 96, 95, 0.14); + display: grid; + gap: 12px; + opacity: 0.62; +} + +.locked-form-preview label { + display: grid; + gap: 7px; + color: var(--color-neutral-gray-600); + font-weight: 800; +} + +.locked-form-preview .input:disabled { + cursor: not-allowed; + background: #eef2f6; + color: var(--color-neutral-gray-600); +} + +.guideline-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.guideline-card, +.guideline-checklist { + border: 1px solid rgba(217, 222, 229, 0.9); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); +} + +.guideline-card { + min-width: 0; + padding: 24px; + display: grid; + gap: 14px; + align-content: start; +} + +.guideline-card--lead { + grid-column: span 2; + background: #eef2f6; +} + +.guideline-card span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; +} + +.guideline-card h2, +.guideline-checklist h2 { + margin: 0; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: clamp(24px, 2.6vw, 34px); + font-weight: 800; + line-height: 1.08; + text-transform: uppercase; +} + +.guideline-card p { + margin: 0; + color: var(--color-neutral-gray-600); + line-height: 1.55; +} + +.guideline-card ul, +.guideline-checklist ul { + margin: 0; + padding-left: 18px; + color: var(--color-neutral-gray-700); + line-height: 1.62; +} + +.guideline-card li + li, +.guideline-checklist li + li { + margin-top: 8px; +} + +.guideline-checklist { + padding: 28px; + display: grid; + grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr); + gap: 28px; + align-items: start; +} + +.news-editorial { + background: #f4f6f9; +} + +.editorial-hero { + padding: 54px 0 34px; + background: #f8fafc; + border-bottom: 1px solid rgba(102, 96, 95, 0.14); +} + +.editorial-hero__inner { + display: grid; + grid-template-columns: minmax(0, 0.55fr) minmax(360px, 0.45fr); + gap: 38px; + align-items: end; +} + +.editorial-hero h1 { + margin: 10px 0 18px; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: clamp(42px, 5.6vw, 76px); + font-weight: 800; + line-height: 0.98; + text-transform: uppercase; +} + +.editorial-meta { + display: flex; + gap: 12px; + flex-wrap: wrap; +} + +.editorial-meta span { + padding: 8px 12px; + border: 1px solid rgba(75, 15, 36, 0.16); + border-radius: var(--radius-sm); + color: var(--color-primary-wine-100); + font-size: 13px; + font-weight: 800; +} + +.editorial-hero__image { + margin: 0; + border-radius: var(--radius-sm); + overflow: hidden; + box-shadow: 0 22px 58px rgba(25, 37, 62, 0.12); +} + +.editorial-hero__image img { + width: 100%; + aspect-ratio: 4 / 3; + object-fit: cover; +} + +.editorial-section { + padding: 48px 0; +} + +.editorial-layout { + display: grid; + grid-template-columns: 260px minmax(0, 780px); + gap: 56px; + align-items: start; + justify-content: center; +} + +.editorial-side { + position: sticky; + top: 154px; + padding: 18px 0 0; + border-top: 2px solid var(--color-primary-wine-100); +} + +.editorial-side span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.editorial-side p { + margin: 12px 0 0; + color: var(--color-neutral-gray-600); + line-height: 1.55; +} + +.editorial-side ol { + margin: 16px 0 0; + padding: 0; + display: grid; + gap: 12px; + list-style: none; +} + +.editorial-side li { + display: grid; + gap: 2px; +} + +.editorial-side strong { + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: 22px; +} + +.editorial-side small { + color: var(--color-neutral-gray-600); + font-size: 13px; +} + +.editorial-body .lead { + color: var(--color-neutral-black); + font-size: clamp(22px, 2.4vw, 30px); + line-height: 1.38; +} + +.editorial-body p { + color: var(--color-neutral-gray-600); + font-size: 18px; + line-height: 1.74; +} + +.editorial-body blockquote { + margin: 34px 0; + padding: 28px; + border-left: 4px solid var(--color-primary-wine-100); + background: #eef2f6; + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: clamp(22px, 3vw, 34px); + font-weight: 800; + line-height: 1.2; +} + +.editorial-image { + margin-top: 0; + margin-bottom: 0; + border-radius: var(--radius-sm); + overflow: hidden; +} + +.editorial-image img { + width: 100%; + max-height: 540px; + object-fit: cover; +} + +.editorial-photo-grid { + display: grid; + grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); + gap: 18px; +} + +.editorial-photo-grid figure { + margin: 0; + border-radius: var(--radius-sm); + overflow: hidden; +} + +.editorial-photo-grid img { + width: 100%; + height: 100%; + min-height: 360px; + object-fit: cover; +} + +.editorial-section--final { + padding-bottom: 82px; +} + +.editorial-outro { + color: var(--color-primary-wine-100) !important; + font-family: var(--font-heading); + font-size: clamp(28px, 4vw, 46px) !important; + font-weight: 800; + line-height: 1.1 !important; + text-transform: uppercase; +} + +.filters-panel, +.info-panel { + padding: 24px; + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); +} + +.filters-panel { + display: grid; + gap: 14px; + align-content: start; +} + +.checkbox { + display: flex; + align-items: center; + gap: 10px; + color: var(--color-neutral-gray-600); + font-weight: 700; +} + +.checkbox input { + width: 18px; + height: 18px; + accent-color: var(--color-primary-wine-100); +} + +.product-detail { + display: grid; + grid-template-columns: minmax(320px, 0.9fr) minmax(0, 1.1fr); + gap: 40px; + align-items: start; +} + +.product-detail .product-media { + min-height: 520px; +} + +.product-detail .product-photo { + max-width: 220px; + height: 420px; +} + +.detail-copy h1 { + margin: 10px 0 18px; + font-family: var(--font-heading); + font-size: clamp(38px, 5vw, 62px); + line-height: 1.08; + font-weight: 800; + text-transform: uppercase; +} + +.meta-list { + display: grid; + gap: 12px; + margin: 28px 0; +} + +.meta-list div { + display: flex; + justify-content: space-between; + gap: 18px; + padding-bottom: 12px; + border-bottom: 1px solid rgba(102, 96, 95, 0.16); +} + +.meta-list span { + color: var(--color-neutral-gray-600); +} + +.site-footer { + margin-top: auto; + padding: 32px 0 40px; + border-top: 1px solid rgba(102, 96, 95, 0.12); + background: var(--color-background-base); +} + +.footer-container { + padding: 24px 28px 20px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-surface); + box-shadow: var(--shadow-soft); +} + +.footer-main { + display: grid; + grid-template-columns: minmax(170px, 210px) minmax(0, 1fr) minmax(210px, 250px); + gap: 24px 32px; + align-items: start; +} + +.footer-brand-block { + min-width: 0; + display: grid; + gap: 8px; +} + +.footer-brand { + display: inline-flex; + width: fit-content; + line-height: 0; +} + +.footer-brand img { + width: 156px; + height: auto; +} + +.footer-brand-subtitle { + margin: 0; + color: var(--color-neutral-gray-600); + font-size: 13px; + line-height: 1.35; +} + +.social-links { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 2px; +} + +.social-links a { + display: inline-grid; + place-items: center; + width: 34px; + height: 34px; + border: 1px solid rgba(75, 15, 36, 0.14); + border-radius: var(--radius-sm); + background: transparent; + color: var(--color-primary-wine-100); + transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease; +} + +.social-links svg { + width: 18px; + height: 18px; + fill: currentColor; +} + +.social-links a:hover, +.social-links a:focus-visible { + border-color: rgba(75, 15, 36, 0.36); + background: rgba(75, 15, 36, 0.06); + transform: translateY(-1px); +} + +.contacts-card { + display: grid; + gap: 8px; + justify-items: start; + align-content: start; +} + +.contacts-card h2, +.nav-group h2 { + margin: 0 0 10px; + font-size: 13px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; +} + +.contact-link { + display: block; + width: fit-content; + color: var(--color-neutral-gray-700); + font-size: 14px; + line-height: 1.35; + transition: color 0.18s ease; +} + +.contact-link:hover, +.contact-link:focus-visible { + color: var(--color-primary-wine-100); +} + +.contact-phone { + color: var(--color-accent-blue); + font-size: 18px; + font-weight: 800; +} + +.footer-nav { + display: grid; + grid-template-columns: repeat(3, minmax(140px, 1fr)); + gap: 24px; + align-items: start; +} + +.nav-group ul { + margin: 0; + padding: 0; + list-style: none; +} + +.nav-group li + li { + margin-top: 7px; +} + +.nav-group a, +.footer-legal { + color: var(--color-neutral-gray-600); +} + +.nav-group a { + display: inline-flex; + padding: 2px 0; + font-size: 14px; + line-height: 1.35; + transition: color 0.18s ease; +} + +.nav-group a:hover, +.nav-group a:focus-visible { + color: var(--color-primary-wine-100); +} + +.footer-legal { + grid-column: 1 / -1; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 20px; + padding-top: 16px; + border-top: 1px solid rgba(102, 96, 95, 0.16); + font-size: 12px; + line-height: 1.45; +} + +.footer-legal p { + margin: 0; +} + +.footer-legal p:first-child { + max-width: 760px; +} + +.footer-legal p:last-child { + flex: 0 0 auto; + color: var(--color-neutral-gray-700); + font-weight: 800; +} + +.footer-legal a { + color: var(--color-primary-wine-80); + font-weight: 800; +} + +.footer-legal a:hover, +.footer-legal a:focus-visible { + color: var(--color-primary-wine-100); +} + +@media (max-width: 1080px) { + .header-top, + .footer-main, + .catalog-layout, + .product-detail { + grid-template-columns: 1fr; + } + + .header-top { + padding: 16px 0; + } + + .footer-main { + grid-template-columns: minmax(180px, 0.7fr) minmax(220px, 1fr); + } + + .footer-nav, + .footer-legal { + grid-column: 1 / -1; + } + + .contacts-card { + justify-self: end; + } + + .header-actions { + justify-content: space-between; + } + + .phone-link { + font-size: 14px; + } + + .main-nav { + justify-content: flex-start; + } + + .menu-grid, + .product-grid, + .bottle-card-grid, + .producer-grid, + .news-grid, + .type-options--five { + grid-template-columns: 1fr 1fr; + } + + .card-lab-head, + .bottle-card-mix, + .page-hero__inner, + .editorial-hero__inner, + .editorial-layout, + .article-layout, + .about-grid, + .contacts-layout, + .guideline-grid, + .guideline-checklist { + grid-template-columns: 1fr; + } + + .type-options { + grid-template-columns: 1fr 1fr; + } + + .catalog-head { + grid-template-columns: 1fr; + } + + .catalog-actions { + justify-content: flex-start; + } + + .product-card--list { + grid-template-columns: 150px minmax(0, 1fr); + } + + .product-card--list-compact, + .product-card--list-b2b { + grid-template-columns: 140px minmax(0, 1fr); + } + + .product-buy { + grid-column: 2; + min-height: auto; + align-content: start; + justify-items: start; + gap: 16px; + } + + .mega-menu { + top: 172px; + } + + .nav-item::after { + top: 150px; + height: 34px; + } +} + +@media (max-width: 720px) { + .container { + width: min(100% - 28px, var(--container)); + } + + .header-top { + gap: 14px; + padding: 16px 0; + } + + .header-actions { + align-items: center; + flex-direction: row; + gap: 10px; + } + + .phone-link { + display: none; + } + + .main-nav { + min-height: 54px; + } + + .mega-menu { + top: 184px; + padding: 18px; + } + + .nav-item::after { + top: 160px; + height: 34px; + } + + .mega-intro, + .menu-grid, + .appellations, + .product-grid, + .bottle-card-grid, + .producer-grid, + .news-grid, + .type-options--five, + .type-options, + .section-heading--split, + .footer-nav { + grid-template-columns: 1fr; + } + + .hero { + min-height: 620px; + padding: 56px 0; + } + + .hero-copy { + width: min(100% - 28px, var(--container)); + grid-template-columns: 1fr; + } + + .section { + padding: 56px 0; + } + + .card-lab-head { + gap: 18px; + margin-bottom: 32px; + } + + .card-lab-head h1 { + font-size: 36px; + } + + .card-variant-title { + align-items: flex-start; + flex-direction: column; + gap: 6px; + } + + .page-hero { + padding: 56px 0; + } + + .page-hero h1 { + font-size: 36px; + } + + .page-hero p, + .article-body .lead { + font-size: 17px; + } + + .editorial-side { + position: static; + } + + .editorial-photo-grid { + grid-template-columns: 1fr; + } + + .feature-grid { + grid-template-columns: 1fr; + } + + .guideline-card--lead { + grid-column: auto; + } + + .bottle-card { + padding: 14px; + } + + .bottle-card__media { + min-height: 190px; + } + + .bottle-card__photo { + height: 168px; + } + + .bottle-card h3 { + font-size: 22px; + } + + .bottle-card__footer { + align-items: stretch; + flex-direction: column; + } + + .bottle-card__footer .button { + width: 100%; + } + + .bottle-card--horizontal { + grid-template-columns: 1fr; + } + + .catalog-toolbar, + .catalog-actions { + align-items: stretch; + flex-direction: column; + } + + .catalog-sort { + width: 100%; + } + + .product-card--list { + min-height: auto; + grid-template-columns: 108px minmax(0, 1fr); + gap: 16px; + padding: 16px; + } + + .product-card--list-compact, + .product-card--list-b2b { + grid-template-columns: 96px minmax(0, 1fr); + } + + .product-image { + min-height: 180px; + max-height: 186px; + } + + .product-image img { + max-width: 98px; + height: 172px; + } + + .product-info h3 { + font-size: 19px; + } + + .product-info p { + font-size: 14px; + } + + .product-params { + grid-template-columns: 1fr; + } + + .product-photo { + max-width: 98px; + height: 164px; + } + + .product-buy { + grid-column: 1 / -1; + display: flex; + align-items: center; + justify-content: space-between; + } + + .product-buy strong { + font-size: 22px; + } + + .footer-container { + padding: 22px 18px; + } + + .footer-main { + grid-template-columns: 1fr; + gap: 32px; + } + + .footer-nav { + grid-template-columns: 1fr; + } + + .contacts-card { + justify-self: start; + } + + .footer-legal { + flex-direction: column; + gap: 12px; + } +} diff --git a/src/css/tokens.css b/src/css/tokens.css new file mode 100644 index 0000000..3c27676 --- /dev/null +++ b/src/css/tokens.css @@ -0,0 +1,34 @@ +:root { + --color-primary-wine-100: #4b0f24; + --color-primary-wine-80: #6d1c36; + --color-neutral-black: #161616; + --color-neutral-gray-700: #30343a; + --color-neutral-gray-600: #66605f; + --color-neutral-gray-300: #d9dee6; + --color-background-base: #f4f6f9; + --color-surface: #ffffff; + --color-accent-gold: #b9965b; + --color-accent-blue: #1f3476; + + --font-heading: "Montserrat", "Inter", Arial, sans-serif; + --font-body: "Inter", Arial, sans-serif; + --font-heading-classic: "Playfair Display", Georgia, serif; + --font-body-classic: "Inter", Arial, sans-serif; + --font-heading-retail: "Montserrat", "Inter", Arial, sans-serif; + + --spacing-4: 4px; + --spacing-8: 8px; + --spacing-16: 16px; + --spacing-24: 24px; + --spacing-32: 32px; + --spacing-48: 48px; + --spacing-64: 64px; + + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 24px; + + --shadow-soft: 0 12px 32px rgba(22, 22, 22, 0.08); + --shadow-lift: 0 20px 52px rgba(75, 15, 36, 0.14); + --container: 1240px; +} diff --git a/src/css/ui-kit.css b/src/css/ui-kit.css new file mode 100644 index 0000000..897d468 --- /dev/null +++ b/src/css/ui-kit.css @@ -0,0 +1,1390 @@ +:root { + --color-primary-wine-100: #4b0f24; + --color-primary-wine-80: #6d1c36; + --color-neutral-black: #161616; + --color-gray-600: #66605f; + --color-gray-300: #d9dee6; + --color-background-base: #f4f6f9; + --color-accent-gold: #b9965b; + --color-white: #ffffff; + --color-error: #a33a2f; + + --font-heading: "Montserrat", "Inter", Arial, sans-serif; + --font-body: "Inter", Arial, sans-serif; + + --spacing-1: 4px; + --spacing-2: 8px; + --spacing-3: 16px; + --spacing-4: 24px; + --spacing-5: 32px; + --spacing-6: 48px; + --spacing-7: 64px; + + --radius-sm: 8px; + --radius-md: 12px; + --shadow-soft: 0 12px 32px rgba(22, 22, 22, 0.08); + --shadow-lift: 0 20px 52px rgba(75, 15, 36, 0.14); +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + background: var(--color-background-base); + color: var(--color-neutral-black); + font-family: var(--font-body); + font-size: 16px; + line-height: 1.5; +} + +a { + color: inherit; + text-decoration: none; +} + +button, +input, +select { + font: inherit; +} + +.sidebar { + position: fixed; + inset: 0 auto 0 0; + width: 280px; + max-height: 100vh; + padding: 24px; + background: #f8fafc; + border-right: 1px solid rgba(102, 96, 95, 0.18); + display: flex; + flex-direction: column; + gap: 32px; + z-index: 5; +} + +.brand { + display: inline-flex; + align-items: center; + gap: 12px; +} + +.brand__mark { + width: 44px; + height: 44px; + border-radius: var(--radius-sm); + background: var(--color-primary-wine-100); + color: var(--color-accent-gold); + display: inline-grid; + place-items: center; + font-family: var(--font-heading); + font-weight: 700; +} + +.brand strong, +.brand small { + display: block; +} + +.brand small { + color: var(--color-gray-600); + font-size: 13px; +} + +.brand--compact .brand__mark { + width: 36px; + height: 36px; +} + +.side-nav { + min-height: 0; + overflow-y: auto; + padding-right: 4px; + display: grid; + gap: 22px; + overscroll-behavior: contain; + scrollbar-width: thin; + scrollbar-color: rgba(75, 15, 36, 0.34) transparent; +} + +.side-nav::-webkit-scrollbar { + width: 6px; +} + +.side-nav::-webkit-scrollbar-thumb { + border-radius: 999px; + background: rgba(75, 15, 36, 0.28); +} + +.side-nav__group { + display: grid; + gap: 8px; +} + +.side-nav__group span { + padding: 0 12px; + color: var(--color-accent-gold); + font-size: 11px; + font-weight: 800; + letter-spacing: 0; + text-transform: uppercase; +} + +.side-nav a { + padding: 10px 12px; + border-radius: var(--radius-sm); + color: var(--color-gray-600); + font-weight: 600; +} + +.side-nav a:hover { + background: rgba(75, 15, 36, 0.07); + color: var(--color-primary-wine-100); +} + +.page-shell { + margin-left: 280px; + min-width: 0; +} + +.kit-hero { + min-height: 92vh; + padding: 56px clamp(24px, 5vw, 72px); + display: grid; + grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr); + align-items: center; + gap: 48px; + background: + radial-gradient(circle at 82% 28%, rgba(185, 150, 91, 0.25), transparent 24%), + linear-gradient(135deg, #ffffff 0%, #eef2f6 58%, #dde4ec 100%); +} + +.kit-hero__content { + max-width: 720px; +} + +.eyebrow, +.muted-caps { + margin: 0; + color: var(--color-accent-gold); + font-size: 12px; + line-height: 16px; + font-weight: 700; + letter-spacing: 0; + text-transform: uppercase; +} + +h1, +h2, +h3, +p { + margin-top: 0; +} + +h1, +h2, +h3 { + font-family: var(--font-heading); + line-height: 1.1; +} + +h1 { + max-width: 780px; + margin-bottom: 20px; + font-size: clamp(40px, 5.5vw, 72px); + font-weight: 800; + text-transform: uppercase; +} + +h2 { + margin-bottom: 0; + font-size: 40px; + font-weight: 800; + text-transform: uppercase; +} + +h3 { + margin-bottom: 16px; + font-size: 24px; + font-weight: 800; +} + +.kit-hero p:not(.eyebrow) { + max-width: 640px; + color: var(--color-gray-600); + font-size: 18px; + line-height: 28px; +} + +.hero-actions, +.component-row, +.chip-row { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12px; +} + +.kit-hero__visual { + justify-self: center; + width: min(100%, 420px); +} + +.button { + min-height: 48px; + padding: 12px 22px; + border: 1px solid transparent; + border-radius: var(--radius-sm); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + color: var(--color-neutral-black); + background: transparent; + font-weight: 700; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; +} + +.button:hover, +.button.is-hover { + transform: translateY(-1px); +} + +.button--primary { + background: var(--color-primary-wine-100); + color: var(--color-white); + box-shadow: 0 10px 22px rgba(75, 15, 36, 0.16); +} + +.button--primary:hover, +.button--primary.is-hover { + background: var(--color-primary-wine-80); + box-shadow: var(--shadow-lift); +} + +.button--secondary { + border-color: rgba(75, 15, 36, 0.24); + background: rgba(255, 255, 255, 0.55); + color: var(--color-primary-wine-100); +} + +.button--ghost { + color: var(--color-primary-wine-100); +} + +.button--sm { + min-height: 38px; + padding: 8px 14px; + font-size: 14px; +} + +.icon-style-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.icon-style-card { + min-width: 0; + padding: 18px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: grid; + gap: 14px; +} + +.icon-demo-row { + min-height: 86px; + padding: 14px; + border-radius: var(--radius-sm); + background: #eef2f6; + display: flex; + align-items: center; + gap: 12px; +} + +.kit-icon { + color: var(--color-primary-wine-100); + display: inline-grid; + place-items: center; + flex: 0 0 auto; +} + +.kit-icon svg { + width: 22px; + height: 22px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.75; +} + +.kit-icon--line { + width: 44px; + height: 44px; +} + +.kit-icon--soft, +.kit-icon--filled { + width: 46px; + height: 46px; + border-radius: var(--radius-sm); +} + +.kit-icon--soft { + border: 1px solid rgba(75, 15, 36, 0.14); + background: var(--color-white); +} + +.kit-icon--filled { + background: var(--color-primary-wine-100); + color: var(--color-white); + box-shadow: 0 10px 22px rgba(75, 15, 36, 0.16); +} + +.kit-icon--tiny { + width: 28px; + height: 28px; +} + +.kit-icon--tiny svg { + width: 16px; + height: 16px; + stroke-width: 1.6; +} + +.icon-style-card > span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.icon-style-card p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; + line-height: 1.45; +} + +.icon-style-card code { + padding: 10px; + border-radius: var(--radius-sm); + background: #eef2f6; + white-space: normal; +} + +.section { + padding: 72px clamp(24px, 5vw, 72px); + border-top: 1px solid rgba(102, 96, 95, 0.16); +} + +.section--last { + padding-bottom: 96px; +} + +.section-heading { + display: grid; + gap: 8px; + margin-bottom: 40px; +} + +.section-heading--split { + grid-template-columns: minmax(0, 0.58fr) minmax(280px, 0.42fr); + gap: 32px; + align-items: end; +} + +.section-heading--split > p { + margin: 0; + color: var(--color-gray-600); + line-height: 1.6; +} + +.subsection { + margin-top: 40px; +} + +.spec-grid { + margin-top: 18px; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; +} + +.spec-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: rgba(255, 255, 255, 0.72); +} + +.spec-card span { + display: block; + margin-bottom: 8px; + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.spec-card p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; + line-height: 1.45; +} + +.status-grid, +.checklist-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; +} + +.status-card, +.production-rules article, +.checklist-card { + min-width: 0; + padding: 20px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); +} + +.status-card { + min-height: 190px; + display: grid; + align-content: space-between; + gap: 14px; +} + +.status-card span, +.production-rules span, +.checklist-card span { + width: fit-content; + padding: 6px 9px; + border-radius: var(--radius-sm); + font-size: 11px; + font-weight: 800; + text-transform: uppercase; +} + +.status-card--ready span { + background: rgba(31, 77, 58, 0.12); + color: #1f4d3a; +} + +.status-card--review span { + background: rgba(185, 150, 91, 0.18); + color: #7c5f26; +} + +.status-card--draft span { + background: rgba(102, 96, 95, 0.12); + color: var(--color-gray-600); +} + +.status-card strong { + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: 22px; + line-height: 1.12; + text-transform: uppercase; +} + +.status-card p, +.production-rules p { + margin: 0; + color: var(--color-gray-600); + line-height: 1.5; +} + +.production-rules { + margin-top: 18px; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; +} + +.production-rules span, +.checklist-card span { + margin-bottom: 14px; + display: inline-block; + background: rgba(75, 15, 36, 0.08); + color: var(--color-primary-wine-100); +} + +.checklist-card ul { + margin: 0; + padding-left: 18px; + color: var(--color-gray-600); + line-height: 1.58; +} + +.checklist-card li + li { + margin-top: 8px; +} + +.swatch-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.swatch, +.template-card, +.mini-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: rgba(255, 255, 255, 0.74); +} + +.swatch span { + display: block; + height: 88px; + margin-bottom: 14px; + border: 1px solid rgba(22, 22, 22, 0.08); + border-radius: var(--radius-sm); + background: var(--swatch); +} + +.swatch strong, +.swatch code, +.template-card span, +.template-card strong { + display: block; +} + +code { + color: var(--color-primary-wine-80); + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; + font-size: 13px; +} + +.typography-specimen { + display: grid; + gap: 18px; +} + +.type-row { + padding-bottom: 18px; + border-bottom: 1px solid rgba(102, 96, 95, 0.16); + display: grid; + grid-template-columns: 280px minmax(0, 1fr); + gap: 24px; + align-items: baseline; +} + +.type-row span { + color: var(--color-gray-600); + font-size: 13px; +} + +.type-row p { + margin: 0; +} + +.text-h1, +.text-h2, +.text-h3 { + font-family: var(--font-heading); + font-weight: 800; + text-transform: uppercase; +} + +.text-h1 { + font-size: 48px; + line-height: 56px; +} + +.text-h2 { + font-size: 36px; + line-height: 44px; +} + +.text-h3 { + font-size: 28px; + line-height: 36px; +} + +.text-body { + font-size: 16px; + line-height: 24px; +} + +.text-label { + font-size: 12px; + line-height: 16px; + font-weight: 700; + text-transform: uppercase; +} + +.grid-demo { + height: 120px; + padding: 16px; + border-radius: var(--radius-sm); + background: rgba(75, 15, 36, 0.06); + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: 16px; +} + +.grid-demo span { + border-radius: 4px; + background: rgba(75, 15, 36, 0.18); +} + +.spacing-scale { + margin-top: 20px; + display: flex; + align-items: end; + flex-wrap: wrap; + gap: 18px; +} + +.spacing-scale span { + width: var(--space); + height: var(--space); + min-width: 4px; + min-height: 4px; + background: var(--color-accent-gold); + color: var(--color-neutral-black); + font-size: 12px; + font-weight: 700; + display: grid; + place-items: center; +} + +.token-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; +} + +.token-grid code { + padding: 14px; + border-radius: var(--radius-sm); + background: #fff; +} + +.shadow-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.shadow-card { + min-height: 220px; + padding: 18px; + border: 1px solid rgba(102, 96, 95, 0.14); + border-radius: var(--radius-sm); + background: var(--color-white); + display: grid; + align-content: space-between; + gap: 12px; +} + +.shadow-card span { + color: var(--color-accent-gold); + font-size: 11px; + font-weight: 800; + text-transform: uppercase; +} + +.shadow-card strong { + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: 20px; + line-height: 1.1; + text-transform: uppercase; +} + +.shadow-card p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; + line-height: 1.45; +} + +.shadow-card code { + width: fit-content; + max-width: 100%; + padding: 7px 9px; + border-radius: var(--radius-sm); + background: #eef2f6; + color: var(--color-primary-wine-100); + font-size: 12px; + white-space: normal; +} + +.shadow-card--none { + box-shadow: none; +} + +.shadow-card--header { + box-shadow: 0 10px 28px rgba(22, 22, 22, 0.05); +} + +.shadow-card--soft { + box-shadow: var(--shadow-soft); +} + +.shadow-card--card { + box-shadow: 0 18px 46px rgba(18, 25, 38, 0.08); +} + +.shadow-card--hover { + box-shadow: 0 22px 54px rgba(25, 37, 62, 0.13); +} + +.shadow-card--lift { + box-shadow: var(--shadow-lift); +} + +.shadow-card--editorial { + box-shadow: 0 22px 58px rgba(25, 37, 62, 0.12); +} + +.shadow-card--focus { + box-shadow: 0 0 0 4px rgba(75, 15, 36, 0.08); +} + +.product-grid { + display: grid; + gap: 20px; +} + +.product-grid--3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.product-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: grid; + gap: 16px; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.product-card:hover, +.product-card--hover, +.product-card--featured { + transform: translateY(-3px); + box-shadow: var(--shadow-lift); +} + +.product-card--compact { + grid-template-columns: 90px minmax(0, 1fr); + align-items: center; +} + +.product-card--compact .product-footer { + grid-column: 2; +} + +.product-media { + position: relative; + min-height: 220px; + border-radius: var(--radius-sm); + overflow: hidden; + display: grid; + place-items: center; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.42), transparent 48%), + var(--media-bg, #dde4ec); +} + +.product-photo { + width: auto; + max-width: 132px; + height: 190px; + object-fit: contain; + object-position: center; + border: 0; + box-shadow: none; +} + +.product-card--compact .product-media { + min-height: 130px; +} + +.product-media--wine { + --media-bg: linear-gradient(140deg, #5d1027, #c8a45d); +} + +.product-media--amber { + --media-bg: linear-gradient(140deg, #a8632a, #dde4ec); +} + +.product-media--green { + --media-bg: linear-gradient(140deg, #1f4d3a, #e8eadb); +} + +.bottle { + width: 54px; + height: 152px; + border-radius: 16px 16px 10px 10px; + background: linear-gradient(90deg, #161616, #2f2a29 44%, #0c0c0c); + box-shadow: 18px 18px 44px rgba(22, 22, 22, 0.24); + position: relative; +} + +.bottle::before { + content: ""; + position: absolute; + top: -58px; + left: 17px; + width: 20px; + height: 72px; + border-radius: 8px 8px 2px 2px; + background: #171212; +} + +.bottle::after { + content: ""; + position: absolute; + inset: 54px 8px auto; + height: 42px; + border-radius: 4px; + background: #eef2f6; +} + +.product-meta { + min-width: 0; +} + +.product-meta h3 { + margin: 8px 0 6px; + font-size: 21px; + text-transform: uppercase; +} + +.product-meta p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; +} + +.product-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.product-footer strong { + color: var(--color-primary-wine-100); + font-size: 18px; +} + +.image-bg-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; +} + +.image-bg-card { + min-width: 0; + padding: 16px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: grid; + gap: 12px; +} + +.image-bg-preview { + min-height: 190px; + border-radius: var(--radius-sm); + overflow: hidden; + display: grid; + place-items: center; +} + +.image-bg-preview img { + width: auto; + max-width: 120px; + height: 164px; + object-fit: contain; + border: 0; + box-shadow: none; +} + +.product-image--gold { + background: linear-gradient(135deg, #b9965b 0%, #d7c18b 48%, #eef2f6 100%); +} + +.product-image--wine { + background: linear-gradient(135deg, #6d1c36 0%, #9b5366 46%, #e6dce1 100%); +} + +.product-image--green { + background: linear-gradient(135deg, #1f4d3a 0%, #88a28e 48%, #eef2e5 100%); +} + +.image-bg-preview--neutral { + background: linear-gradient(135deg, #eef2f6 0%, #dde6ef 100%); +} + +.image-bg-card span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.image-bg-card p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; + line-height: 1.45; +} + +.image-bg-card code { + padding: 10px; + border-radius: var(--radius-sm); + background: #eef2f6; + color: var(--color-primary-wine-100); + font-size: 12px; + line-height: 1.45; + white-space: normal; +} + +.header-demo { + padding: 16px; + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; +} + +.header-demo nav { + display: flex; + flex-wrap: wrap; + gap: 18px; + color: var(--color-gray-600); + font-weight: 600; +} + +.component-columns, +.catalog-pattern, +.template-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 24px; +} + +.control-stack { + padding: 20px; + border-radius: var(--radius-sm); + background: var(--color-white); + display: grid; + gap: 14px; + box-shadow: var(--shadow-soft); +} + +.checkbox { + display: flex; + align-items: center; + gap: 10px; + color: var(--color-gray-600); + font-weight: 600; +} + +.checkbox input { + width: 18px; + height: 18px; + accent-color: var(--color-primary-wine-100); +} + +.chip, +.tag { + min-height: 34px; + padding: 7px 12px; + border: 1px solid rgba(75, 15, 36, 0.18); + border-radius: var(--radius-sm); + background: var(--color-white); + color: var(--color-primary-wine-100); + font-size: 13px; + font-weight: 700; +} + +.chip { + cursor: pointer; +} + +.chip--active, +.tag--filled { + background: var(--color-primary-wine-100); + color: var(--color-white); +} + +.tag--outline { + background: transparent; + border-color: var(--color-accent-gold); + color: var(--color-primary-wine-100); +} + +.range { + display: grid; + gap: 8px; + color: var(--color-gray-600); + font-weight: 600; +} + +.range input { + accent-color: var(--color-primary-wine-100); +} + +.input { + width: 100%; + min-height: 48px; + padding: 12px 14px; + border: 1px solid rgba(102, 96, 95, 0.24); + border-radius: var(--radius-sm); + background: var(--color-white); + color: var(--color-neutral-black); +} + +.input--focus, +.input:focus { + border-color: var(--color-primary-wine-100); + box-shadow: 0 0 0 3px rgba(75, 15, 36, 0.1); + outline: none; +} + +.input--error { + border-color: var(--color-error); + color: var(--color-error); +} + +.table-wrap { + overflow-x: auto; + border-radius: var(--radius-sm); + box-shadow: var(--shadow-soft); +} + +table { + width: 100%; + min-width: 720px; + border-collapse: collapse; + background: var(--color-white); +} + +th, +td { + padding: 16px; + border-bottom: 1px solid rgba(102, 96, 95, 0.16); + text-align: left; +} + +th { + background: #e8edf3; + color: var(--color-primary-wine-100); + font-size: 12px; + text-transform: uppercase; +} + +tbody tr:hover { + background: rgba(75, 15, 36, 0.04); +} + +.filters-panel { + padding: 24px; + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: grid; + gap: 14px; + align-content: start; +} + +.mini-card { + min-height: 120px; + display: grid; + place-items: center; + color: var(--color-primary-wine-100); + font-family: var(--font-heading); + font-size: 20px; + font-weight: 800; + text-transform: uppercase; + text-align: center; +} + +.template-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +.template-card { + min-height: 148px; + display: grid; + align-content: space-between; +} + +.template-card span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 700; + text-transform: uppercase; +} + +.template-card strong { + font-family: var(--font-heading); + font-size: 20px; + font-weight: 800; + line-height: 1.2; + text-transform: uppercase; +} + +.template-spec-grid { + margin-top: 24px; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; +} + +.template-spec { + min-width: 0; + padding: 20px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: var(--color-white); + box-shadow: var(--shadow-soft); + display: grid; + gap: 10px; +} + +.template-spec span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.template-spec h3 { + margin: 0; + font-size: 22px; + line-height: 1.12; + text-transform: uppercase; +} + +.template-spec p { + margin: 0; + color: var(--color-gray-600); + font-size: 14px; + line-height: 1.48; +} + +.template-spec a { + color: var(--color-primary-wine-100); + font-weight: 800; + text-decoration: underline; + text-underline-offset: 3px; +} + +.template-spec em { + margin-top: 4px; + color: var(--color-primary-wine-100); + font-size: 13px; + font-style: normal; + font-weight: 800; +} + +.screen-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.screen-card { + min-height: 230px; + padding: 20px; + border: 1px solid rgba(102, 96, 95, 0.16); + border-radius: var(--radius-sm); + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.98)), + var(--screen-accent, #eef2f6); + box-shadow: var(--shadow-soft); + display: grid; + align-content: space-between; + gap: 18px; + transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease; +} + +.screen-card:hover { + border-color: rgba(75, 15, 36, 0.28); + box-shadow: 0 22px 54px rgba(25, 37, 62, 0.13); + transform: translateY(-2px); +} + +.screen-card span { + color: var(--color-accent-gold); + font-size: 12px; + font-weight: 800; + text-transform: uppercase; +} + +.screen-card strong { + color: var(--color-neutral-black); + font-family: var(--font-heading); + font-size: 24px; + line-height: 1.1; + text-transform: uppercase; +} + +.screen-card p { + margin: 0; + color: var(--color-gray-600); + line-height: 1.5; +} + +.screen-card--home { + --screen-accent: linear-gradient(135deg, #4b0f24, #b9965b); +} + +.screen-card--catalog { + --screen-accent: linear-gradient(135deg, #eef2f6, #d9dee6); +} + +.screen-card--product, +.screen-card--cards { + --screen-accent: linear-gradient(135deg, #6d1c36, #e6dce1); +} + +.screen-card--news, +.screen-card--guidelines { + --screen-accent: linear-gradient(135deg, #1f4d3a, #e8eadb); +} + +.screen-card--about, +.screen-card--contacts, +.screen-card--auth { + --screen-accent: linear-gradient(135deg, #1f3476, #dde4ec); +} + +.screen-qa-grid { + margin-top: 24px; +} + +@media (max-width: 1100px) { + .sidebar { + position: static; + width: auto; + border-right: none; + border-bottom: 1px solid rgba(102, 96, 95, 0.18); + } + + .side-nav { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .page-shell { + margin-left: 0; + } + + .kit-hero, + .component-columns, + .catalog-pattern { + grid-template-columns: 1fr; + } + + .swatch-grid, + .shadow-grid, + .image-bg-grid, + .icon-style-grid, + .status-grid, + .production-rules, + .checklist-grid, + .template-grid, + .template-spec-grid, + .screen-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 760px) { + .sidebar { + padding: 18px; + } + + .side-nav { + grid-template-columns: 1fr 1fr; + } + + .kit-hero, + .section { + padding: 40px 18px; + } + + .kit-hero { + min-height: auto; + } + + h1 { + font-size: 42px; + } + + h2 { + font-size: 34px; + } + + .swatch-grid, + .shadow-grid, + .image-bg-grid, + .icon-style-grid, + .status-grid, + .production-rules, + .checklist-grid, + .product-grid--3, + .template-grid, + .template-spec-grid, + .screen-grid, + .token-grid, + .spec-grid { + grid-template-columns: 1fr; + } + + .type-row { + grid-template-columns: 1fr; + gap: 8px; + } + + .header-demo { + align-items: flex-start; + flex-direction: column; + } + + .product-card--compact { + grid-template-columns: 1fr; + } + + .product-card--compact .product-footer { + grid-column: auto; + } + + .screen-card { + min-height: 190px; + } +} diff --git a/src/index.njk b/src/index.njk new file mode 100644 index 0000000..195234f --- /dev/null +++ b/src/index.njk @@ -0,0 +1,90 @@ +--- +title: "DP Trade — Home" +layout: layouts/default +permalink: / +--- +
+
+
+

DP Trade

+

Премиальный каталог вина для торговли

+

Регионы, производители, партии и коммерческие условия собраны в одном интерфейсе для быстрых закупочных решений.

+ +
+
+ +
+
+
+
+

Producers

+

Производители

+
+

Ключевые винные дома и хозяйства из портфеля DP Trade: от классических брендов до эксклюзивных партнеров.

+
+ +
+
+ +
+
+
+
+

Latest news

+

Последние новости

+
+ Все новости +
+
+
+
+
Интервью

Интервью с Лаурой Катеной

+
+
+
+
Бренды

Catena Zapata вновь признана самым почитаемым винным брендом мира

+
+
+
+
Италия

Villa Raiano: от оливкового масла к одному из лучших фиано Италии

+
+
+
+
+ +
+
+
+

Recommendations

+

Рекомендации недели

+
+
+
+
Chateau Laroque Grand Cru
+
Bordeaux

Chateau Laroque Grand Cru

France · Red dry · 2019 · 0.75 L

+ +
+
+
Brunello di Montalcino
+
Tuscany

Brunello di Montalcino

Italy · Red dry · 2018 · 0.75 L

+ +
+
+
Riesling Kabinett
+
Mosel

Riesling Kabinett

Germany · White · 2021 · 0.75 L

+ +
+
+
+
+
diff --git a/src/js/inspector.js b/src/js/inspector.js new file mode 100644 index 0000000..d5d9de8 --- /dev/null +++ b/src/js/inspector.js @@ -0,0 +1,624 @@ +(function () { + 'use strict'; + + // ── Конфиг ───────────────────────────────────────────────────────────────── + + const TOKEN_PREFIXES = ['--color-', '--font-', '--spacing-', '--radius-', '--shadow-', '--container']; + + // layout-свойства для секции «Стили» (типографика — отдельная секция) + const LAYOUT_PROPS = [ + 'display', 'position', 'flexDirection', 'flexWrap', + 'gridTemplateColumns', 'gridTemplateRows', 'gap', 'alignItems', 'justifyContent', + 'width', 'maxWidth', 'minHeight', 'height', + 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', + 'margin', 'marginTop', 'marginBottom', + 'backgroundColor', 'borderRadius', 'boxShadow', 'opacity', + ]; + + const SKIP_VALUES = new Set([ + 'none', 'normal', 'auto', '0px', 'rgba(0, 0, 0, 0)', 'transparent', + 'start', 'static', 'visible', 'nowrap', 'row', 'inline', + '0px 0px 0px 0px rgba(0, 0, 0, 0)', + ]); + + const TOKEN_PROP_MAP = { + '--color-': ['color', 'background-color', 'border-top-color', + 'border-bottom-color', 'border-left-color', 'border-right-color'], + '--font-': ['font-family'], + '--spacing-': ['padding-top', 'padding-right', 'padding-bottom', 'padding-left', + 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', + 'row-gap', 'column-gap'], + '--radius-': ['border-top-left-radius'], + '--shadow-': ['box-shadow'], + '--container': ['max-width'], + }; + + // ── Состояние ─────────────────────────────────────────────────────────────── + + let enabled = false; + let pinned = null; + + // ── Утилиты: цвет ─────────────────────────────────────────────────────────── + + function rgbToHex(rgb) { + const m = rgb.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/); + if (!m) return null; + return '#' + [m[1], m[2], m[3]] + .map(n => parseInt(n).toString(16).padStart(2, '0')) + .join('').toUpperCase(); + } + + function hexToRgb(hex) { + hex = hex.replace(/^#/, ''); + if (hex.length === 3) hex = hex.split('').map(c => c + c).join(''); + const r = parseInt(hex.slice(0, 2), 16); + const g = parseInt(hex.slice(2, 4), 16); + const b = parseInt(hex.slice(4, 6), 16); + return `rgb(${r}, ${g}, ${b})`; + } + + function normalizeColor(val) { + val = val.trim().toLowerCase(); + if (/^#[0-9a-f]{3,8}$/.test(val)) return hexToRgb(val); + return val.replace(/\s+/g, ''); + } + + function firstFont(val) { + return val.split(',')[0].trim().replace(/["']/g, '').toLowerCase(); + } + + function formatColor(val) { + if (/^#/.test(val.trim())) return val.trim().toUpperCase(); + if (/^rgba?\(/.test(val.trim())) return rgbToHex(val) || val; + return val; + } + + // ── Токены из :root ────────────────────────────────────────────────────────── + + let _rootTokens = null; + function getRootTokens() { + if (_rootTokens) return _rootTokens; + _rootTokens = {}; + for (const sheet of document.styleSheets) { + try { + for (const rule of sheet.cssRules) { + if (rule.selectorText === ':root') { + for (const prop of rule.style) { + if (TOKEN_PREFIXES.some(p => prop.startsWith(p))) { + _rootTokens[prop] = rule.style.getPropertyValue(prop).trim(); + } + } + } + } + } catch (_) {} + } + return _rootTokens; + } + + // ── Обратный маппинг: значение → имя токена ───────────────────────────────── + // Используется в секции Типографика, чтобы показать + // «Inter → --font-body» и «#30343A → --color-neutral-gray-700». + + let _colorMap = null; + let _fontMap = null; + + function getColorTokenMap() { + if (_colorMap) return _colorMap; + _colorMap = {}; + for (const [name, val] of Object.entries(getRootTokens())) { + if (!name.startsWith('--color-')) continue; + try { _colorMap[normalizeColor(val)] = name; } catch (_) {} + } + return _colorMap; + } + + function getFontTokenMap() { + if (_fontMap) return _fontMap; + _fontMap = {}; + for (const [name, val] of Object.entries(getRootTokens())) { + if (!name.startsWith('--font-')) continue; + const key = firstFont(val); + // Приоритет: --font-heading > --font-heading-* > --font-body > etc. + // Первый встреченный побеждает, поэтому не перезаписываем. + if (!_fontMap[key]) _fontMap[key] = { name, fullValue: val }; + } + return _fontMap; + } + + // ── Токены, активные на элементе (для секции «Токены») ────────────────────── + + function getElementTokens(el) { + const tokens = getRootTokens(); + const cs = getComputedStyle(el); + const found = new Map(); + + for (const [tokenName, tokenRaw] of Object.entries(tokens)) { + const prefix = TOKEN_PREFIXES.find(p => tokenName.startsWith(p)); + if (!prefix) continue; + const propsToCheck = TOKEN_PROP_MAP[prefix] || []; + + for (const cssProp of propsToCheck) { + const computed = cs.getPropertyValue(cssProp).trim(); + if (!computed) continue; + let match = false; + + if (prefix === '--color-') { + try { match = normalizeColor(computed) === normalizeColor(tokenRaw); } catch (_) {} + } else if (prefix === '--font-') { + match = firstFont(computed) === firstFont(tokenRaw); + } else if (prefix === '--spacing-' || prefix === '--radius-' || prefix === '--container') { + match = computed === tokenRaw.trim(); + } else if (prefix === '--shadow-') { + match = computed.includes(tokenRaw.split(' ').slice(0, 3).join(' ')); + } + + if (match) { + if (!found.has(tokenName)) { + found.set(tokenName, { raw: tokenRaw, usedIn: [] }); + } + found.get(tokenName).usedIn.push(cssProp); + break; + } + } + } + return found; + } + + // ── Типографика элемента ───────────────────────────────────────────────────── + + function getTypography(el) { + const cs = getComputedStyle(el); + const colorMap = getColorTokenMap(); + const fontMap = getFontTokenMap(); + + const rawFont = cs.fontFamily; + const rawColor = cs.color; + const fontKey = firstFont(rawFont); + const fontEntry = fontMap[fontKey]; + + // Название шрифта — первый, без кавычек + const fontName = fontKey.charAt(0).toUpperCase() + fontKey.slice(1); + + // Токен шрифта — ищем точное совпадение первого шрифта + const fontToken = fontEntry ? fontEntry.name : null; + + // Цвет текста + const colorHex = formatColor(rawColor); + const colorToken = colorMap[normalizeColor(rawColor)] || null; + + // Линейная высота — упрощаем до числа если возможно + const lhRaw = cs.lineHeight; + const lhNum = parseFloat(lhRaw); + const fsNum = parseFloat(cs.fontSize); + const lh = (fsNum && lhNum) + ? (lhNum / fsNum).toFixed(2).replace(/\.?0+$/, '') + : lhRaw; + + // Letter-spacing + const ls = cs.letterSpacing !== '0px' ? cs.letterSpacing : null; + + // Text-transform + const tt = cs.textTransform !== 'none' ? cs.textTransform : null; + + return { + fontName, + fontToken, + fontFull: rawFont, + fontSize: cs.fontSize, + fontWeight: cs.fontWeight, + lineHeight: lh, + letterSpacing: ls, + textTransform: tt, + colorHex, + colorToken, + }; + } + + // ── Layout-стили (без типографики) ────────────────────────────────────────── + + function getLayoutStyles(el) { + const cs = getComputedStyle(el); + const result = []; + for (const prop of LAYOUT_PROPS) { + let val = cs[prop]; + if (!val || SKIP_VALUES.has(val)) continue; + if (/^rgba?\(/.test(val)) val = formatColor(val); + result.push({ prop: camelToKebab(prop), value: val }); + } + return result; + } + + function camelToKebab(s) { + return s.replace(/[A-Z]/g, c => '-' + c.toLowerCase()); + } + + function formatTokenValue(raw) { + const t = raw.trim(); + if (/^#[0-9a-fA-F]{3,6}$/.test(t)) return t.toUpperCase(); + if (/^rgba?\(/.test(t)) return rgbToHex(t) || t; + return t; + } + + // ── DOM ───────────────────────────────────────────────────────────────────── + + const panel = document.createElement('div'); + panel.id = 'dp-inspector-panel'; + panel.innerHTML = ` +
+ + + + + Инспектор + + +
+
+

Кликните на элемент

+
+ `; + document.body.appendChild(panel); + + const toggle = document.createElement('button'); + toggle.id = 'dp-inspector-toggle'; + toggle.title = 'Инспектор элементов (Alt+I)'; + toggle.innerHTML = ` + + + `; + document.body.appendChild(toggle); + + const highlight = document.createElement('div'); + highlight.id = 'dp-inspector-highlight'; + document.body.appendChild(highlight); + + const tooltip = document.createElement('div'); + tooltip.id = 'dp-inspector-tooltip'; + document.body.appendChild(tooltip); + + // ── Стили ─────────────────────────────────────────────────────────────────── + + const style = document.createElement('style'); + style.textContent = ` + #dp-inspector-toggle { + position: fixed; bottom: 24px; right: 24px; z-index: 99998; + width: 44px; height: 44px; border-radius: 50%; border: none; + background: #4b0f24; color: #fff; cursor: pointer; + display: flex; align-items: center; justify-content: center; + box-shadow: 0 4px 16px rgba(75,15,36,.35); + transition: background .15s, transform .15s; + } + #dp-inspector-toggle:hover { background: #6d1c36; transform: scale(1.08); } + #dp-inspector-toggle.active { background: #b9965b; } + + #dp-inspector-panel { + position: fixed; top: 0; right: -360px; width: 340px; height: 100vh; + z-index: 99999; background: #fff; + border-left: 1px solid rgba(102,96,95,.18); + box-shadow: -12px 0 40px rgba(22,22,22,.10); + display: flex; flex-direction: column; + font-family: 'Inter', system-ui, sans-serif; font-size: 13px; + transition: right .25s cubic-bezier(.4,0,.2,1); overflow: hidden; + } + #dp-inspector-panel.open { right: 0; } + + .dpi-header { + display: flex; align-items: center; justify-content: space-between; + padding: 14px 16px; background: #4b0f24; color: #fff; flex-shrink: 0; + } + .dpi-title { + display: flex; align-items: center; gap: 7px; + font-weight: 700; font-size: 13px; + letter-spacing: .04em; text-transform: uppercase; + } + .dpi-close { + background: none; border: none; color: rgba(255,255,255,.7); + cursor: pointer; font-size: 15px; padding: 2px 4px; line-height: 1; + } + .dpi-close:hover { color: #fff; } + + .dpi-body { flex: 1; overflow-y: auto; padding: 0 0 80px; } + .dpi-empty { color: #66605f; text-align: center; padding: 40px 16px; margin: 0; } + + .dpi-section { padding: 12px 16px; border-bottom: 1px solid rgba(102,96,95,.12); } + .dpi-section:last-child { border-bottom: none; } + + .dpi-section-title { + font-size: 10px; font-weight: 800; letter-spacing: .08em; + text-transform: uppercase; color: #b9965b; margin: 0 0 8px; + } + + /* Элемент */ + .dpi-element-tag { + font-family: 'Menlo','Monaco',monospace; font-size: 12px; + color: #4b0f24; font-weight: 600; margin: 0 0 6px; word-break: break-all; + } + .dpi-classes { display: flex; flex-wrap: wrap; gap: 5px; } + .dpi-class { + padding: 2px 8px; border-radius: 4px; + background: rgba(75,15,36,.08); color: #4b0f24; + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + font-weight: 600; cursor: pointer; user-select: all; + } + .dpi-class:hover { background: rgba(75,15,36,.16); } + + /* Типографика */ + .dpi-type-row { + display: grid; grid-template-columns: 76px 1fr; + align-items: baseline; gap: 6px; + padding: 3px 0; border-bottom: 1px solid rgba(102,96,95,.07); + } + .dpi-type-row:last-child { border-bottom: none; } + .dpi-type-label { + font-size: 10px; font-weight: 700; text-transform: uppercase; + letter-spacing: .06em; color: #66605f; + } + .dpi-type-val { + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + color: #161616; font-weight: 600; + } + .dpi-type-token { + font-family: 'Menlo','Monaco',monospace; font-size: 10px; + color: #b9965b; margin-left: 6px; font-weight: 400; + } + .dpi-color-dot { + display: inline-block; width: 10px; height: 10px; + border-radius: 2px; border: 1px solid rgba(0,0,0,.12); + margin-right: 5px; vertical-align: middle; flex-shrink: 0; + } + + /* Токены */ + .dpi-token { + display: grid; grid-template-columns: 16px 1fr auto; + align-items: start; gap: 7px; + padding: 5px 0; border-bottom: 1px solid rgba(102,96,95,.07); + } + .dpi-token:last-child { border-bottom: none; } + .dpi-token-swatch { + width: 14px; height: 14px; border-radius: 3px; + border: 1px solid rgba(0,0,0,.12); margin-top: 1px; + } + .dpi-token-swatch.no-color { + background: repeating-linear-gradient(45deg,#ddd 0 3px,#fff 3px 6px); + } + .dpi-token-info { min-width: 0; } + .dpi-token-name { + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + color: #30343a; display: block; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + } + .dpi-token-uses { + font-size: 10px; color: #b9965b; margin-top: 1px; + display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + } + .dpi-token-value { + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + color: #4b0f24; font-weight: 600; white-space: nowrap; margin-top: 1px; + } + + /* Стили */ + .dpi-style { + display: flex; justify-content: space-between; gap: 8px; + padding: 3px 0; border-bottom: 1px solid rgba(102,96,95,.07); + } + .dpi-style:last-child { border-bottom: none; } + .dpi-style-prop { + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + color: #30343a; flex-shrink: 0; + } + .dpi-style-val { + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + color: #4b0f24; font-weight: 600; + text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + } + + /* Highlight */ + #dp-inspector-highlight { + position: fixed; pointer-events: none; z-index: 99990; + border: 2px solid #4b0f24; background: rgba(75,15,36,.06); + border-radius: 3px; display: none; + transition: top .05s, left .05s, width .05s, height .05s; + } + body.dp-inspect-mode #dp-inspector-highlight { display: block; } + + #dp-inspector-tooltip { + position: fixed; pointer-events: none; z-index: 99995; + background: #4b0f24; color: #fff; + font-family: 'Menlo','Monaco',monospace; font-size: 11px; + padding: 3px 8px; border-radius: 4px; white-space: nowrap; + display: none; max-width: 300px; + overflow: hidden; text-overflow: ellipsis; + } + body.dp-inspect-mode #dp-inspector-tooltip { display: block; } + + body.dp-inspect-mode * { cursor: crosshair !important; } + body.dp-inspect-mode #dp-inspector-toggle, + body.dp-inspect-mode #dp-inspector-panel, + body.dp-inspect-mode #dp-inspector-panel * { cursor: default !important; } + `; + document.head.appendChild(style); + + // ── Рендер панели ─────────────────────────────────────────────────────────── + + function buildPanel(el) { + const tag = el.tagName.toLowerCase(); + const id = el.id ? `#${el.id}` : ''; + const classes = [...el.classList]; + const typo = getTypography(el); + const tokens = getElementTokens(el); + const layout = getLayoutStyles(el); + + let html = ''; + + // ── Элемент ────────────────────────────────────────────────────────────── + html += `
+

Элемент

+

<${tag}${id}>

`; + html += classes.length + ? `
${classes.map(c => `.${c}`).join('')}
` + : `

Нет классов

`; + html += `
`; + + // ── Типографика ────────────────────────────────────────────────────────── + html += `
+

Типографика

`; + + // Шрифт + const fontToken = typo.fontToken + ? `${typo.fontToken}` : ''; + html += `
+ Шрифт + ${typo.fontName}${fontToken} +
`; + + // Размер + html += `
+ Размер + ${typo.fontSize} +
`; + + // Насыщенность + html += `
+ Насыщ. + ${typo.fontWeight} +
`; + + // Межстрочный + html += `
+ Line-height + ${typo.lineHeight} +
`; + + // Letter-spacing + if (typo.letterSpacing) { + html += `
+ Tracking + ${typo.letterSpacing} +
`; + } + + // Text-transform + if (typo.textTransform) { + html += `
+ Transform + ${typo.textTransform} +
`; + } + + // Цвет текста + const colorDot = ``; + const colorToken = typo.colorToken + ? `${typo.colorToken}` : ''; + html += `
+ Цвет + ${colorDot}${typo.colorHex}${colorToken} +
`; + + html += `
`; + + // ── Токены ─────────────────────────────────────────────────────────────── + html += `
+

Токены${tokens.size ? ` (${tokens.size})` : ''}

`; + + if (tokens.size) { + for (const [name, { raw, usedIn }] of tokens) { + const display = formatTokenValue(raw); + const isColor = name.startsWith('--color-'); + const swatch = isColor + ? `` + : ``; + html += `
+ ${swatch} + + ${name} + ${usedIn.join(', ')} + + ${display} +
`; + } + } else { + html += `

Нет прямых совпадений с tokens.css

`; + } + html += `
`; + + // ── Стили (layout) ─────────────────────────────────────────────────────── + if (layout.length) { + html += `
+

Стили

`; + for (const { prop, value } of layout) { + html += `
+ ${prop} + ${value} +
`; + } + html += `
`; + } + + panel.querySelector('.dpi-body').innerHTML = html; + } + + // ── Управление ────────────────────────────────────────────────────────────── + + function enable() { + enabled = true; + document.body.classList.add('dp-inspect-mode'); + toggle.classList.add('active'); + panel.classList.add('open'); + panel.querySelector('.dpi-body').innerHTML = '

Кликните на элемент

'; + } + + function disable() { + enabled = false; pinned = null; + document.body.classList.remove('dp-inspect-mode'); + toggle.classList.remove('active'); + panel.classList.remove('open'); + highlight.style.display = 'none'; + tooltip.style.display = 'none'; + } + + function isInspectable(el) { + if (!el || el === document.body || el === document.documentElement) return false; + if (['dp-inspector-panel','dp-inspector-toggle', + 'dp-inspector-highlight','dp-inspector-tooltip'].includes(el.id)) return false; + if (el.closest('#dp-inspector-panel, #dp-inspector-toggle')) return false; + return true; + } + + // ── События ───────────────────────────────────────────────────────────────── + + toggle.addEventListener('click', () => enabled ? disable() : enable()); + panel.querySelector('.dpi-close').addEventListener('click', disable); + + document.addEventListener('keydown', e => { + if (e.altKey && e.key === 'i') { e.preventDefault(); enabled ? disable() : enable(); } + if (e.key === 'Escape' && enabled) disable(); + }); + + document.addEventListener('mousemove', e => { + if (!enabled) return; + const el = document.elementFromPoint(e.clientX, e.clientY); + if (!isInspectable(el) || el === pinned) return; + + const r = el.getBoundingClientRect(); + Object.assign(highlight.style, { + display: 'block', top: r.top + 'px', left: r.left + 'px', + width: r.width + 'px', height: r.height + 'px', + }); + + const cls = [...el.classList].map(c => '.' + c).join(''); + tooltip.textContent = el.tagName.toLowerCase() + (el.id ? '#' + el.id : '') + cls; + tooltip.style.display = 'block'; + tooltip.style.left = Math.min(e.clientX + 12, window.innerWidth - tooltip.offsetWidth - 8) + 'px'; + tooltip.style.top = (e.clientY + 20) + 'px'; + }); + + document.addEventListener('click', e => { + if (!enabled) return; + const el = document.elementFromPoint(e.clientX, e.clientY); + if (!isInspectable(el)) return; + e.preventDefault(); e.stopPropagation(); + pinned = el; + buildPanel(el); + }, true); + +})(); diff --git a/src/news-villa-raiano-v2.njk b/src/news-villa-raiano-v2.njk new file mode 100644 index 0000000..d21e037 --- /dev/null +++ b/src/news-villa-raiano-v2.njk @@ -0,0 +1,78 @@ +--- +title: "DP Trade — Villa Raiano editorial" +layout: layouts/default +permalink: /news-villa-raiano-v2.html +bodyClass: compact-type +--- +
+
+
+
+
+

Новости / Villa Raiano

+

Villa Raiano: от оливкового масла к одному из лучших фиано Италии

+
6 апреля, 2026Ирпиния, Кампания
+
+
+ Винодельня Villa Raiano среди холмов Ирпинии +
+
+
+ +
+
+ +
+

Рассказываем о семье Бассо и винодельне Villa Raiano, совершившей небольшую революцию в Ирпинии, сменив курс с красных вин на белые. Судя по нашим последним дегустациям, у них это получилось.

+

На холмах Сан-Микеле-ди-Серино, в провинции Авеллино, расположена винодельня семьи Бассо. Название связано с корнями: Villa Raiano — историческая местность коммуны Серино, где находилась старая оливковая плантация семьи.

+
+
+
+ +
+ Сбор белого винограда Villa Raiano +
+ +
+
+ +
+

В середине 1990-х с основанием винодельни в Ирпинии начался винодельческий бум. Первые годы для семьи Бассо были скорее хобби: они делали и разливали вино на семейной маслобойне. С 1999 по 2008 год они стали сотрудничать с энологом Луиджи Мойо, который учился вместе с Сабино Бассо в аграрном институте Авеллино.

+
«В 2008 году мы купили новое оборудование, начали сотрудничество с Фортунато Себастьяно и построили винодельню на вершине холма в Сан-Микеле-ди-Серино», — рассказывает сын Сабино Бассо, Федерико.
+

Открытие в 2009 году совпало с новым курсом: появились четыре белых вина с отдельных виноградников — три Fiano di Avellino и один Greco di Tufo. Через десять лет к работе подключилось новое поколение: «В компанию пришли я, мой брат Фабрицио и наша кузина Брунелла, дочь Симоне».

+
+
+
+ +
+
Ящики с белым виноградом Villa Raiano
+
Работа в погребе Villa Raiano
+
+ +
+
+ +
+

В 2024 году открылась новая подземная винодельня, полностью интегрированная в ландшафт. Сегодня Villa Raiano владеет 30 гектарами виноградников: хозяйство работает по биологическим принципам и сертифицировано с 2011 года.

+
«Мы уверены, что наш регион — земля великих белых вин», — говорит Федерико. «Сила наших DOC — в огромных различиях, которые один и тот же сорт может проявлять в разных условиях».
+

Континентальный климат позволяет ягодам созревать медленно, что делает вина особенными — как красные, так и белые. На последних дегустациях Gambero Rosso Fiano di Avellino 2024 года особенно впечатлил итальянских экспертов, получив премию Miglior Qualità Prezzo Regionale гида BereBene 2026.

+

Чем не повод самому проверить мнение Gambero Rosso?

+
+
+
+
+
diff --git a/src/news-villa-raiano.njk b/src/news-villa-raiano.njk new file mode 100644 index 0000000..0c7cff1 --- /dev/null +++ b/src/news-villa-raiano.njk @@ -0,0 +1,53 @@ +--- +title: "DP Trade — Villa Raiano" +layout: layouts/default +permalink: /news-villa-raiano.html +bodyClass: compact-type +--- +
+
+
+
+

Новости / Италия

+

Villa Raiano: от оливкового масла к одному из лучших Fiano Италии

+

История семейного хозяйства из Кампании, где любовь к Ирпинии выросла из маслобойного производства в современную винодельню.

+
+ +
+
+ +
+
+
+

Villa Raiano появилась в 1996 году по инициативе семьи Бассо, известной производством оливкового масла. Первые вина делались в помещениях старого маслобойного завода, а в 2009 году хозяйство переехало в новую винодельню в Ирпинии.

+

Для DP Trade эта история важна не только как биография производителя. Villa Raiano показывает, как локальная ремесленная культура Кампании может стать точной, современной и очень узнаваемой винной стилистикой.

+

Почему Fiano di Avellino

+

Фьяно из Авеллино ценят за минеральность, плотную фактуру и способность к развитию в бутылке. В молодых винах часто появляются цитрусовые, груша, персик, травы и медовые оттенки; с возрастом они становятся глубже, прянее и сложнее.

+

Villa Raiano работает с традиционными сортами региона: Fiano, Greco, Falanghina и Aglianico. Такой фокус помогает хозяйству говорить не универсальным языком международного вина, а языком конкретного места.

+
Фокус карточки новости: семейная история, локальный сорт и ценность производителя для профессионального каталога.
+

Что показать в каталоге

+

Для товарной страницы и подборок можно вынести происхождение, сорт, стиль, потенциал выдержки и гастрономические пары. В B2B-сценарии особенно полезны быстрые маркеры: регион, апелласьон, тип вина, крепость, объем и доступность партии.

+
+ +
+
+
diff --git a/src/product.njk b/src/product.njk new file mode 100644 index 0000000..7f21620 --- /dev/null +++ b/src/product.njk @@ -0,0 +1,26 @@ +--- +title: "DP Trade — Product" +layout: layouts/default +permalink: /product.html +--- +
+
+
Chateau Laroque Grand Cru
+
+

Product / Default

+

Chateau Laroque Grand Cru

+

Премиальная позиция из Bordeaux для ресторанных карт и специализированной розницы.

+
+
РегионBordeaux
+
ТипRed dry
+
Год2019
+
Объем0.75 L
+
Цена3 890 ₽
+
+ +
+
+
diff --git a/src/ui-kit.njk b/src/ui-kit.njk new file mode 100644 index 0000000..20e2b7e --- /dev/null +++ b/src/ui-kit.njk @@ -0,0 +1,1168 @@ +--- +title: "DP Trade — Design System" +layout: layouts/ui-kit +permalink: /ui-kit.html +--- + + +
+
+
+

DP Trade — Design System

+

UI-kit для премиального торгового каталога

+

+ Живая HTML/CSS витрина компонентов, токенов, паттернов и экранов для сайта DP Trade. + Структура повторяет Figma-файл и использует критичный naming format. +

+ +
+
+ +
+
+ +
+
+
+

00 Production Status

+

Статус дизайн-системы

+
+

Этот блок показывает, насколько UI-kit готов к production handoff: что можно использовать сразу, что требует детализации, и какие правила обязательны для новых экранов.

+
+
+
+ Ready + Catalog List Cards +

Есть варианты, состояния, фоны изображений, shadows и реальная страница для проверки.

+
+
+ Ready + Navigation / Mega-menu +

Header, dropdown, hover bridge, ширина контейнера и базовые состояния зафиксированы.

+
+
+ Ready + Foundations +

Цветовые роли, типографика, сетка, spacing, tokens и shadows описаны для dev handoff.

+
+
+ Review + Forms / Inputs +

Есть default/focus/error, но нужны helper text, required, disabled, textarea и validation patterns.

+
+
+ Ready + Templates +

Шаблоны описывают обязательные блоки, компоненты, screen-ссылки и статус готовности.

+
+
+ Review + Responsive QA +

Есть checklist и адаптивные правила, но перед релизом нужен визуальный проход по всем страницам.

+
+
+
+
+ Production rule +

Новый компонент нельзя считать готовым без anatomy, variants, states, usage, CSS hook и responsive notes.

+
+
+ Screen rule +

Новый экран должен быть связан с template, иметь статус, ссылку на HTML и список QA-проверок.

+
+
+ Content rule +

Все изображения должны иметь понятный alt, стабильные размеры контейнера и не ломать layout на mobile.

+
+
+
+

Readiness Matrix

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
РазделAnatomyStatesUsageResponsiveStatus
FoundationsДаДаДаДаReady
ButtonsДаPartialДаДаReview
Product CardsДаДаДаДаReady
NavigationДаPartialДаPartialReview
Forms / ControlsДаPartialДаДаReview
Templates / ScreensДаДаДаДаReady
+
+
+
+ +
+
+

01 Foundations

+

База системы

+
+ +
+

Colors

+
+
+ + Color / Primary / Wine / 100 + #4B0F24 +
+
+ + Color / Primary / Wine / 80 + #6D1C36 +
+
+ + Color / Neutral / Black + #161616 +
+
+ + Color / Neutral / Gray / 600 + #66605F +
+
+ + Color / Neutral / Gray / 300 + #D8D3CF +
+
+ + Color / Background / Base + #F4F6F9 +
+
+ + Color / Accent / Gold + #B9965B +
+
+
+
+ Text roles +

`color.text.primary` = #161616 для заголовков и основного текста. `color.text.muted` = #66605F для meta, captions, описаний и вторичных ссылок.

+
+
+ Surface roles +

`color.background.base` = #F4F6F9 для страницы. `color.surface.default` = #FFFFFF для карточек, форм, таблиц и dropdown.

+
+
+ Brand roles +

`color.primary.wine.100` для CTA, активных состояний и важных ссылок. `color.accent.gold` для labels, eyebrow и editorial accents.

+
+
+ State roles +

Error использует #A33A2F. Success/review/draft пока локальные в UI-kit; перед разработкой их нужно вынести в state tokens.

+
+
+
+ +
+

Typography

+
+ Text / Heading / H1 / Montserrat / 48 / 56 +

Rare wines for trade

+
+
+ Text / Heading / H2 / Montserrat / 36 / 44 +

Catalog collections

+
+
+ Text / Heading / H3 / Montserrat / 28 / 36 +

Producer selection

+
+
+ Text / Body / Regular / Inter / 16 / 24 +

Вина, регионы, партии и коммерческие условия в единой системе.

+
+
+ Text / Label / Caps / Inter / 12 / 16 +

FEATURED REGION

+
+
+
+ Hero / H1 +

Montserrat 700-800, uppercase, clamp 44-78px, line-height около 0.98-1.08. Используется на главной и крупных внутренних hero.

+
+
+ Catalog / Product title +

Montserrat 800, 22-32px для list-card. Не использовать uppercase в текущем каталоге, чтобы длинные названия читались легче.

+
+
+ Article / Lead +

Inter 22-30px, line-height 1.38-1.48. Используется как первый смысловой абзац в редакционных материалах.

+
+
+ Button / Label +

Inter 700-800, 14-16px. Текст должен помещаться без переноса на desktop; на mobile кнопка может становиться full-width.

+
+
+
+ +
+

Grid & Spacing

+
+ + +
+
+ 4 + 8 + 16 + 24 + 32 + 48 + 64 +
+
+
+ Container +

`--container: 1240px`. Desktop width: `min(100% - 40px, var(--container))`; mobile width: `min(100% - 28px, var(--container))`.

+
+
+ Breakpoints +

Desktop default. Tablet: max-width 1080/1100px. Mobile: max-width 720/760px depending on site vs UI-kit shell.

+
+
+ Spacing rule +

Компоненты: 8-16px gap. Карточки/формы: 16-24px padding. Секции: 56-72px vertical padding.

+
+
+
+ +
+

Tokens

+
+ color.primary = #4B0F24 + color.text = #161616 + spacing.md = 16px + radius.sm = 8px + shadow.soft = 0 12px 32px rgba(22,22,22,.08) + shadow.lift = 0 20px 52px rgba(75,15,36,.14) +
+
+
+ Color tokens +

`color.primary.wine.100`, `color.primary.wine.80`, `color.accent.gold`, `color.accent.blue`, `color.background.base`, `color.surface.default`.

+
+
+ Layout tokens +

`container.max = 1240px`, `spacing.4/8/16/24/32/48/64`, `radius.sm = 8px`, `radius.md = 12px`, `radius.lg = 24px`.

+
+
+ Typography tokens +

`font.heading = Montserrat`, `font.body = Inter`. Размеры текста хранятся как semantic styles, а не только raw px.

+
+
+
+ +
+

Elevation & Shadows

+
+
+ Shadow / None + none +

Изображения бутылок, прозрачные PNG/JPG внутри карточек, плоские служебные элементы.

+ box-shadow: none; +
+
+ Shadow / Header / Sticky + Navigation depth +

Только для sticky header: лёгкое отделение от контента при скролле.

+ 0 10px 28px rgba(22,22,22,.05) +
+
+ Shadow / Soft + Base surface +

Основной токен для карточек, footer-контейнера, форм, contact panels и info-card.

+ 0 12px 32px rgba(22,22,22,.08) +
+
+ Shadow / Card / Product + Product card +

Для bottle-card и визуальных карточек с изображением, когда нужно чуть больше воздуха.

+ 0 18px 46px rgba(18,25,38,.08) +
+
+ Shadow / Card / Hover + Interactive lift +

Hover/active состояние list-card. Используется вместе с border-color, без изменения размеров.

+ 0 22px 54px rgba(25,37,62,.13) +
+
+ Shadow / Lift + Mega-menu +

Высокий слой: dropdown, mega-menu, временно поднятые панели.

+ 0 20px 52px rgba(75,15,36,.14) +
+
+ Shadow / Editorial / Image + Hero media +

Крупные изображения в статье, где фото должно отделяться от фона страницы.

+ 0 22px 58px rgba(25,37,62,.12) +
+
+ Shadow / Focus Ring + Input focus +

Не декоративная тень, а доступное состояние focus для search/input.

+ 0 0 0 4px rgba(75,15,36,.08) +
+
+
+
+ +
+
+

02 Components

+

Компоненты

+
+ +
+

Component Readiness

+
+
+ Required anatomy +

Каждый production-компонент должен иметь anatomy, variants, states, sizes, usage, CSS hooks и responsive notes.

+
+
+ Required states +

Default, Hover, Focus, Active, Disabled. Для data-heavy компонентов также Loading, Empty, Error, Selected.

+
+
+ CSS hooks +

Использовать стабильные классы: `.button--primary`, `.product-card--list`, `.product-image--gold`, `.contact-auth-gate`.

+
+
+
+ +
+

Buttons

+
+ + + + +
+
+
+ Анатомия +

Button / Background + Label. Высота 48px, compact 38px, radius 8px, padding 12/22.

+
+
+ Состояния +

Default, Hover, Focus, Disabled. Hover меняет фон/тень, focus должен иметь видимый outline.

+
+
+ Использование +

Primary для главного CTA, Secondary для каталогов и избранного, Ghost для тихих действий.

+
+
+ Production gap +

Добавить disabled, loading, icon-only, full-width mobile. Loading не должен менять ширину кнопки.

+
+
+
+ +
+

Icon Styles

+
+
+
+ + + +
+ Icon / Line / Default +

Основной стиль для header, account, cart, menu chevrons и вторичных действий. Stroke 1.75px, без заливки.

+ stroke-width: 1.75; width: 22px; +
+
+
+ + + +
+ Icon / Soft Container +

Для кликабельных icon buttons: header account/cart, toolbar actions, карточки избранного. Контейнер 44-48px.

+ background: #fff; border: rgba(75,15,36,.14); +
+
+
+ + + +
+ Icon / Filled Action +

Акцентный вариант для primary icon-only действий, selected states и важных быстрых команд. Использовать дозированно.

+ background: color.primary; color: #fff; +
+
+
+ + + +
+ Icon / Utility / Small +

Для chevron, accordion, table sorting и compact filters. Stroke 1.6px, размер 14-18px, без отдельного контейнера.

+ width: 16px; stroke-width: 1.6; +
+
+
+
+ Size scale +

Utility 16px, navigation 20-22px, icon button 44/48px container, primary action 48px container. SVG всегда квадратный.

+
+
+ Stroke rule +

Базовый stroke 1.75px. Не использовать тяжёлые 2.5-3px иконки в header: они спорят с логотипом и типографикой.

+
+
+ States +

Default, Hover, Focus, Active, Disabled, Selected. Hover меняет border/background, а не толщину линии.

+
+
+ CSS hooks +

`.kit-icon--line`, `.kit-icon--soft`, `.kit-icon--filled`, `.kit-icon--tiny`. В рабочем header использовать тот же визуальный принцип.

+
+
+
+ +
+

Product Card

+
+
+
Product bottle
+
+ Tuscany +

Brunello di Montalcino

+

Italy · Red dry · 2018 · 0.75 L

+
+ +
+
+
Product bottle
+
+ Rioja +

Reserva Seleccion Especial

+

Spain · Red dry · 2017 · 0.75 L

+
+ +
+
+
Product bottle
+
+ Mosel +

Riesling Kabinett

+

Germany · White · 2021

+
+ +
+
+
+
+ Варианты +

Card / Product / Default, Hover, Compact, List. List используется в каталоге и поисковой выдаче.

+
+
+ Анатомия +

Image, Meta, Name, Details, Price, CTA. Для list-card добавляется Product info + Product buy.

+
+
+ Состояния +

Default, Hover, Favorite, Out of stock. Hover усиливает border/shadow без изменения размеров.

+
+
+
+ +
+

Catalog List Cards

+
+
+ Card / Product / List / Default +

Текущая карточка каталога: Image, Product info, Price, CTA. Используется для B2B-выдачи и страниц стран.

+
+
+ Card / Product / List / Compact +

Сниженная высота, меньше изображение и короче details. Подходит для плотной выдачи и избранного.

+
+
+ Card / Product / List / Color Image +

Цветной фон только в зоне изображения: Gold, Wine, Green. Бутылка остаётся реальной фотографией без shadow.

+
+
+ Card / Product / List / B2B Dense +

Дополнительные параметры: тип, сорт, упаковка, артикул. Для профессионального сравнения SKU.

+
+
+ Shadow +

Default использует Shadow / Soft. Hover использует Shadow / Card / Hover + border rgba(75,15,36,.28). Картинки бутылок всегда shadow none.

+
+
+ +
+ +
+

Image Backgrounds

+
+
+
Bottle on gold gradient
+ Image Background / Gold +

Для белых, сладких, премиальных и акцентных карточек. Хорошо работает с бутылками без прозрачного фона.

+ .product-image--gold { background: linear-gradient(135deg, #b9965b 0%, #d7c18b 48%, #eef2f6 100%); } +
+
+
Bottle on wine gradient
+ Image Background / Wine +

Для красных вин, премиальных подборок и карточек, где нужен более сильный брендовый акцент.

+ .product-image--wine { background: linear-gradient(135deg, #6d1c36 0%, #9b5366 46%, #e6dce1 100%); } +
+
+
Bottle on green gradient
+ Image Background / Green +

Для белых, органики, свежих регионов и спокойных карточек с холодным фоном.

+ .product-image--green { background: linear-gradient(135deg, #1f4d3a 0%, #88a28e 48%, #eef2e5 100%); } +
+
+
Bottle on neutral gradient
+ Image Background / Neutral +

Для hover, B2B dense и ситуаций, где цвет не должен спорить с информацией.

+ background: linear-gradient(135deg, #eef2f6 0%, #dde6ef 100%); +
+
+
+
+ Правило +

Градиент применяется только к контейнеру изображения, не к карточке целиком. Так карточка остаётся читаемой и не превращается в баннер.

+
+
+ Изображение +

Бутылка всегда `object-fit: contain`, `box-shadow: none`, без вылета за блок. Для JPG без прозрачности контейнер должен скрывать переполнение.

+
+
+ CSS hook +

Для list-card использовать `.product-image product-image--gold|wine|green`. Для плиток использовать модификаторы media-контейнера.

+
+
+
+ +
+

Editorial Components

+
+
+ Article / Hero / Split +

Заголовок, дата/мета, крупное фото. Для новостей производителей и экспертных материалов.

+
+
+ Article / Body +

Lead, paragraph, blockquote, wide image, photo grid. Не больше 4 текстовых абзацев без визуальной паузы.

+
+
+ Article / Sidebar +

Sticky fact block, timeline или recognition. На мобильном становится обычным блоком над текстом.

+
+
+ Guidelines +

Отдельная страница с требованиями к заголовкам, тексту, фото, SEO и pre-publish checklist.

+
+
+ Shadow +

Editorial hero image использует Shadow / Editorial / Image. Текстовые блоки и сайдбар остаются без декоративной тени, чтобы читать было спокойнее.

+
+
+ Production gap +

Добавить компоненты: Article meta, Article quote, Article image caption, Related products, Related producer.

+
+
+ +
+ + + +
+
+

Filters

+
+ + +
+ + + +
+ +
+
+
+

Tags & Inputs

+
+
+ Tag / Default + Tag / Filled + Tag / Outline +
+ + + + +
+
+
+
+

Controls Specs

+
+
+ Filters +

Checkbox Default/Active/Disabled, Chip Default/Active, Range Slider Default/Dragging.

+
+
+ Inputs +

Input Default/Focus/Error/Disabled. Error меняет border и helper text, не меняет высоту поля.

+
+
+ Tags +

Default для метаданных, Filled для выбранного статуса, Outline для мягких категорий.

+
+
+ Production gap +

Нужны helper/error text, required label, disabled controls, textarea, select open state, clear all для фильтров.

+
+
+
+ +
+

Tables / B2B

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
SKUNameRegionStockTrade price
DP-1042Chateau Laroque Grand CruBordeaux48 cases3 890 ₽
DP-1188Riesling KabinettMosel32 cases2 150 ₽
+
+
+
+

Table Specs

+
+
+ Анатомия +

Table Header, Row, Cell, Numeric cell, Actions. Горизонтальный scroll на мобильных.

+
+
+ Состояния +

Row Default/Hover/Selected, Header, Empty, Loading. Hover используется для B2B-сканирования.

+
+
+ Использование +

Прайс-листы, остатки, коммерческие условия и сравнение SKU.

+
+
+ Production gap +

Добавить Empty, Loading, Selected, Actions column, numeric alignment, sticky header и mobile fallback.

+
+
+
+
+ +
+
+

03 Patterns

+

Паттерны

+
+
+ +
+

Pattern / Product Grid / 3 col

+
+
Bordeaux Grand Cru
+
Tuscany Reserve
+
Mosel Riesling
+
+
+
+
+

Content & Inner Pages

+
+
+ Pattern / News Article / Editorial +

Split hero, date meta, lead, wide image, timeline sidebar, quote, photo grid, final CTA.

+
+
+ Pattern / About Page / Default +

Hero + короткая история + сетка преимуществ. Подходит для корпоративной страницы без перегруза.

+
+
+ Pattern / Contacts / Form +

Контактные панели + форма заявки менеджеру. На мобильном блоки идут одной колонкой.

+
+
+ Pattern / Contacts / Auth Gate +

Контакты открыты, заявка заблокирована для гостя. Показываем CTA входа/регистрации и disabled-preview формы.

+
+
+ Pattern / Editorial Guidelines +

Guideline cards + checklist. Используется как внутренняя документация для редакции и контент-менеджера.

+
+
+
+
+ +
+
+
+

04 Templates

+

Шаблоны

+
+

Templates описывают каркас страницы: обязательные блоки, опциональные зоны, компоненты и связь с реальным screen. Это не финальный экран, а правило сборки.

+
+
+
+ Template / Home + Hero + regions + recommendations +
+
+ Template / Catalog + Filters + product grid + table mode +
+
+ Template / Product Page + Gallery + meta + CTA + availability +
+
+ Template / Producer Page + Story + region + producer catalog +
+
+ Template / News Article + Editorial story + media + timeline +
+
+ Template / About + Company story + advantages +
+
+ Template / Contacts + Contact panels + manager request +
+
+ Template / Contacts Auth + Open contacts + gated request form +
+
+ Template / Article Guidelines + Rules + checklist + photo requirements +
+
+
+
+ Template / Catalog +

Product listing

+

Required: Header, catalog head, toolbar, product list, footer.

+

Components: Catalog List Card, Select, Button Secondary, Mega-menu.

+

Screen: catalog.html

+ Status: Review, needs mobile QA for dense list. +
+
+ Template / News Article +

Editorial story

+

Required: Article hero, date/meta, lead, body, image block, footer.

+

Optional: timeline, quote, photo grid, related products.

+

Screen: news-villa-raiano-v2.html

+ Status: Ready, content/photo rules documented. +
+
+ Template / Contacts Auth +

Gated request

+

Required: contacts hero, open contacts, auth gate, disabled preview, footer.

+

Components: Contact Panel, Contact Auth Gate, Button Primary/Secondary.

+

Screen: contacts-auth.html

+ Status: Review, needs real login/register routes. +
+
+ Template / Home +

Commercial landing

+

Required: asymmetrical hero, producer block, news block, footer.

+

Components: Header, Mega-menu, Button Primary, News Card, Producer Card.

+

Screen: index.html

+ Status: Ready, visual direction approved. +
+
+ Template / Article Guidelines +

Internal documentation

+

Required: page intro, rule cards, photo requirements, writing checklist.

+

Components: Guideline Card, Checklist Card, Editorial Specs.

+

Screen: article-guidelines.html

+ Status: Ready, supports content production. +
+
+ Template / Product Page +

Product detail

+

Required: product media, details, price/CTA, characteristics, recommendations.

+

Components: Product Media, Product Meta, Table, Product Card.

+

Screen: product.html

+ Status: Draft, needs final product content model. +
+
+
+ +
+
+
+

05 Screens

+

Реальные экраны

+
+

Этот раздел ведёт на конкретные HTML-страницы проекта. В отличие от Templates, здесь фиксируются уже собранные экраны с реальным контентом, header/footer и состояниями.

+
+
+ + Screen / Home / v1 + Главная +

Hero, производители, новости, рекомендации и общий визуальный тон сайта.

+
+ + Screen / Catalog / v1 + Каталог +

Список товаров, toolbar, сортировка, текущая горизонтальная карточка каталога.

+
+ + Screen / Product / v1 + Карточка товара +

Продуктовый detail layout: изображение, описание, метаданные и CTA.

+
+ + Screen / Cards Lab / v1 + Варианты карточек +

Лаборатория карточек бутылок и текущих list-card состояний.

+
+ + Screen / News / v2 + Villa Raiano editorial +

Журнальная статья с крупными фото, таймлайном, цитатами и финальным акцентом.

+
+ + Screen / About / v1 + О компании +

Корпоративная страница: описание, преимущества, спокойная B2B-подача.

+
+ + Screen / Contacts / v1 + Контакты +

Открытая форма заявки, контактные панели, юридический информационный блок.

+
+ + Screen / Contacts / Auth + Контакты auth +

Вариант, где заявка доступна только после входа или регистрации.

+
+ + Screen / Guidelines / v1 + Редакционный гайд +

Требования к статьям, фотографиям, заголовкам, SEO и pre-publish checklist.

+
+
+
+
+ Screen status +

Ready: Home, News v2, Guidelines, Cards Lab. Review: Catalog, Contacts Auth. Draft: Product, если не утверждена модель данных.

+
+
+ Screen QA +

Каждый экран проверяется на desktop/tablet/mobile: header/footer, links, image loading, hover/focus states, overflow и читаемость текста.

+
+
+ Template link +

Каждый screen должен соответствовать одному template. Если меняется template, связанные screens обновляются вместе с ним.

+
+
+
+ +
+
+
+

06 Handoff

+

Production checklist

+
+

Финальный список проверок перед передачей дизайна в разработку или публикацией новой страницы в UI-kit.

+
+
+
+ Design +
    +
  • Компонент использует существующие tokens: color, spacing, radius, shadow.
  • +
  • Есть все состояния: default, hover, focus, active, disabled, error/loading где нужно.
  • +
  • Размеры стабильны: hover, текст и динамический контент не двигают layout.
  • +
  • Компонент не дублирует уже существующий паттерн без причины.
  • +
+
+
+ Development +
    +
  • Есть CSS hook или class naming по схеме Category / Type / Variant / State.
  • +
  • В UI-kit указан usage: где компонент применяется и где не применяется.
  • +
  • Все ссылки в demo/screens ведут на реальные HTML-файлы.
  • +
  • Нет inline-логики, которая мешает переиспользовать компонент.
  • +
+
+
+ Responsive +
    +
  • Проверены desktop, tablet и mobile.
  • +
  • Карточки, таблицы и формы не переполняют контейнер.
  • +
  • Текст в кнопках и карточках не обрезается и не накладывается.
  • +
  • Таблицы имеют horizontal scroll или мобильную альтернативу.
  • +
+
+
+ Accessibility +
    +
  • Интерактивные элементы имеют видимый focus.
  • +
  • Изображения имеют осмысленный alt.
  • +
  • Кнопки и ссылки различимы по роли и тексту.
  • +
  • Цвет не является единственным способом передать состояние.
  • +
+
+
+ Content +
    +
  • Заголовки соответствуют иерархии H1/H2/H3.
  • +
  • Для статей есть лид, визуальные паузы, alt и финальный CTA.
  • +
  • Даты, имена, регионы, апелласьоны и награды проверены.
  • +
  • Изображения достаточно крупные и не выглядят случайно обрезанными.
  • +
+
+
+ Ready criteria +
    +
  • Раздел имеет описание назначения.
  • +
  • Есть пример, спецификация и ссылка на screen, если применимо.
  • +
  • Компонент или экран можно собрать без дополнительных устных пояснений.
  • +
  • Статус готовности понятен: Ready, Review или Draft.
  • +
+
+
+
+