glubokoe-intervyu/design.md

12 KiB
Raw Permalink Blame History

Дизайн-система KT AI — по ней собирается весь UI

В папке проекта лежит design-system/ — это дизайн-система KT AI (источник: github.com/erjan-A/kt-ai-design-system, MIT, версия в design-system/VERSION). Весь визуал берётся оттуда: цвета, шрифт, отступы, кнопки, карточки, секции лендинга.

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

Если папки design-system/ в проекте нет (старый проект) — принеси её один раз:

cp -r /srv/opencode/design-system/kt-ai design-system

🔒 Три правила, которые нельзя нарушать

  1. Цвета и размеры — только токенами var(--kt-ai-…). Сырой hex (#0F1218, #fff) в вёрстке запрещён: он ломает светлую/тёмную тему.
  2. Никакого Bootstrap / Tailwind / Material / Font Awesome / Google Fonts. Шрифт (Inter) уже внутри ДС и работает офлайн. Всё, что нужно лендингу, в ДС уже есть.
  3. Свой <style> — только на мелочи, которых нет в ДС (позиционирование, картинка-фон). Не переопределяй кнопки, карточки и типографику.

Старт: index.html

Это рабочий каркас лендинга. Копируй его целиком и меняй содержание.

В новом проекте этот каркас уже лежит как index.html — не создавай файл заново: read index.html → edit. Если проект старый и файла нет — скопируй каркас ниже целиком. Если проект не про веб-страницу — стартовый index.html можно удалить.

<!DOCTYPE html>
<html lang="ru" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Название проекта</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<style>
  /* ДС рисует кнопки для <button>; у ссылки-кнопки браузер добавляет подчёркивание */
  a.kt-ai-btn { text-decoration: none; }
</style>
</head>
<body>

<header class="kt-ai-pagehead">
  <div class="kt-ai-wrap kt-ai-pagehead-in">
    <strong>Название</strong>
    <span class="kt-ai-spacer"></span>
    <a class="kt-ai-btn" data-variant="ghost" href="#about">О нас</a>
    <a class="kt-ai-btn" data-variant="primary" href="#contacts">Оставить заявку</a>
  </div>
</header>

<section class="kt-ai-hero" data-align="center">
  <div class="kt-ai-wrap">
    <h1>Главное обещание в одну строку</h1>
    <p class="kt-ai-hero-sub">Подзаголовок: кому это и почему стоит остаться.</p>
    <div class="kt-ai-hero-actions">
      <a class="kt-ai-btn" data-variant="primary" data-size="lg" href="#contacts">Оставить заявку</a>
      <a class="kt-ai-btn" data-size="lg" href="#about">Подробнее</a>
    </div>
  </div>
</section>

<section id="about" class="kt-ai-section" data-divider="true">
  <div class="kt-ai-wrap">
    <div class="kt-ai-section-head">
      <h2>Что вы получите</h2>
      <p>Одно-два предложения пояснения к секции.</p>
    </div>
    <div class="kt-ai-grid" style="margin-top:var(--kt-ai-space-9)">
      <article class="kt-ai-tile"><h3>Пункт первый</h3><p>Коротко и по делу.</p></article>
      <article class="kt-ai-tile"><h3>Пункт второй</h3><p>Коротко и по делу.</p></article>
      <article class="kt-ai-tile"><h3>Пункт третий</h3><p>Коротко и по делу.</p></article>
    </div>
  </div>
</section>

<section id="contacts" class="kt-ai-cta">
  <div class="kt-ai-wrap">
    <h2>Призыв к действию</h2>
    <p>Город, адрес, часы работы — то, что нужно, чтобы дойти.</p>
    <a class="kt-ai-btn" data-variant="primary" data-size="lg" href="#">Написать</a>
  </div>
</section>

<footer class="kt-ai-wrap kt-ai-pagefoot">
  <span>© 2026 Название</span>
  <span class="kt-ai-spacer"></span>
  <span>Контакты</span>
</footer>

</body>
</html>

Блоки страницы (kt-ai-page.css)

Класс Что это
.kt-ai-wrap контейнер по центру (1080px). data-width="narrow" — 720px, "wide" — 1200px
.kt-ai-pagehead + .kt-ai-pagehead-in липкая шапка страницы
.kt-ai-hero, .kt-ai-hero-sub, .kt-ai-hero-actions первый экран. data-align="center" — по центру
.kt-ai-section + .kt-ai-section-head (h2 + p) обычная секция. data-divider="true" — линия сверху
.kt-ai-grid + .kt-ai-tile (h3 + p) сетка плиток «возможности». data-cols="2"/"4", у плитки data-span="2"/"full"
.kt-ai-tile-icon иконка над заголовком плитки (спрайт — design-system/icons/)
.kt-ai-cta финальный блок с призывом
.kt-ai-pagefoot подвал
.kt-ai-spacer распорка внутри шапки/подвала (толкает остальное вправо)
.kt-ai-centered одна карточка по центру экрана — для страницы входа и 404

Отступы между секциями ДС ставит сама. Адаптив (3→2→1 колонка) — тоже, @media писать не нужно.

Элементы (kt-ai-components.css)

Класс Как применять
.kt-ai-btn кнопка / ссылка-кнопка. data-variant="primary" — главная, "ghost" — прозрачная, "danger" — опасная. data-size="sm"/"lg"
.kt-ai-card карточка контента
.kt-ai-chip статус-пилюля / тег
.kt-ai-link текстовая ссылка
.kt-ai-field + .kt-ai-input / .kt-ai-textarea / .kt-ai-select поле формы с подписью

Один primary на экран. Остальные кнопки — обычные или ghost.

Токены (kt-ai-tokens.css)

Цвет: --kt-ai-bg, --kt-ai-bg-soft, --kt-ai-fg, --kt-ai-fg-muted, --kt-ai-fg-faint, --kt-ai-border, --kt-ai-divider, --kt-ai-card-bg, --kt-ai-card-border, --kt-ai-primary, --kt-ai-link, --kt-ai-danger.

Отступы: --kt-ai-space-1…12 (2px → 64px). Скругления: --kt-ai-radius-md/lg/xl/2xl/3xl/full. Текст: --kt-ai-text-xs…3xl. Вес: --kt-ai-weight-regular/medium/semibold/bold. Шрифты: --kt-ai-font-sans (Inter), --kt-ai-font-mono.

Тема — атрибут на <html>: data-theme="auto" (по системной, ставь его по умолчанию), "light", "dark". Проверь страницу в обеих темах — с токенами это бесплатно.


Не лендинг, а приложение (дашборд, таблица, очередь заявок, чат)

Тогда экран собирается не вёрсткой руками, а конфигом:

  1. Возьми design-system/templates/kt-ai-app-shell.html — самодостаточный HTML-каркас приложения (без React и npm).
  2. Опиши экран JSON-конфигом по design-system/docs/PRODUCT_CONTRACT.md и положи его в тег <script id="kt-app-config" type="application/json">…</script> внутри каркаса — он сам отрисует таблицу, KPI, фильтры, drawer и темы.
  3. Проверь конфиг: python3 design-system/scripts/validate_product.py config.json --strict → нужен 0/0.

Полные правила для сложных экранов — design-system/AGENTS.md, список компонентов — design-system/COMPONENTS.md, приёмка — design-system/CHECKLIST.md. Читай их, когда лендинга уже мало.


📦 Готовые рецепты

Фото без ключей

  • Одно и то же слово → одна и та же картинка: https://picsum.photos/seed/coffee/800/600
  • По теме: https://loremflickr.com/800/600/coffee (тег прямо в URL)

Вставляй с рамкой ДС: <img src="…" alt="…" style="width:100%;border-radius:var(--kt-ai-radius-3xl)">

Кнопка WhatsApp

<a class="kt-ai-btn" data-variant="primary" data-size="lg"
   href="https://wa.me/7XXXXXXXXXX?text=Здравствуйте!">Написать в WhatsApp</a>

7XXXXXXXXXX — номер в международном формате без +.

Форма заявки без бэкенда

<form action="https://formsubmit.co/EMAIL" method="POST" style="max-width:420px">
  <div class="kt-ai-field"><label>Имя</label><input class="kt-ai-input" name="name" required></div>
  <div class="kt-ai-field"><label>Телефон</label><input class="kt-ai-input" name="phone" required></div>
  <button class="kt-ai-btn" data-variant="primary" type="submit">Отправить</button>
</form>

Скажи юзеру: замени EMAIL на свою почту — заявки будут приходить туда (первая заявка активирует форму).

Favicon-эмодзи (без файла)

<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>☕</text></svg>">

Карта

На maps.google.com: место → «Поделиться» → «Встроить карту» → вставь iframe как есть:

<iframe src="https://www.google.com/maps/embed?pb=..." width="100%" height="320"
        style="border:0;border-radius:var(--kt-ai-radius-3xl)" loading="lazy"></iframe>

Плавные появления при скролле

<style>
.reveal{opacity:0;transform:translateY(20px);transition:opacity .6s ease,transform .6s ease}
.reveal.in{opacity:1;transform:none}
</style>
<script>
var io=new IntersectionObserver(function(entries){
  entries.forEach(function(e){ if(e.isIntersecting) e.target.classList.add('in'); });
},{threshold:.15});
document.querySelectorAll('.reveal').forEach(function(el){ io.observe(el); });
</script>

Перед тем как сказать «готово»

  • Подключены все четыре CSS из design-system/, папка лежит в проекте (не забудь закоммитить её).
  • В вёрстке нет сырых hex-цветов и чужих шрифтов.
  • Страница нормально выглядит в светлой и тёмной теме и на телефоне (узкое окно).
  • Один data-variant="primary" на экран, тексты — про юзера, а не «Lorem ipsum».