# ТЗ: Кнопка "📖 Подробнее об экосистеме" с модальным окном

## Обзор компонента

Кнопка открывает модальное окно (Dialog) с "глубинным уровнем" экосистемы проекта — картой ссылок, философией и манифестом.

---

## Часть 1: Зависимости

```json
{
  "dependencies": {
    "@radix-ui/react-dialog": "^1.1.14",
    "lucide-react": "^0.462.0",
    "tailwind-merge": "^2.6.0",
    "clsx": "^2.1.1",
    "class-variance-authority": "^0.7.1"
  }
}
```

---

## Часть 2: Компоненты UI

### 2.1 Утилита cn (обязательно)

```typescript
// src/lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
```

### 2.2 Button компонент

```typescript
// src/components/ui/button.tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-sm font-medium transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "bg-gradient-to-r from-primary to-primary-glow text-primary-foreground shadow-medium hover:shadow-glow hover:scale-105",
        destructive: "bg-gradient-to-r from-destructive to-red-600 text-destructive-foreground shadow-soft hover:shadow-medium hover:scale-105",
        outline: "bg-background/50 backdrop-blur-sm text-foreground shadow-soft hover:bg-gradient-hover hover:shadow-medium hover:scale-105",
        secondary: "bg-gradient-to-r from-secondary to-yellow-500 text-secondary-foreground shadow-soft hover:shadow-glow-accent hover:scale-105",
        ghost: "hover:bg-accent/10 hover:text-accent-foreground hover:shadow-soft",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        icon: "h-10 w-10",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  },
);

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button";
    return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
  },
);
Button.displayName = "Button";

export { Button, buttonVariants };
```

### 2.3 Dialog компонент

```typescript
// src/components/ui/dialog.tsx
import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";

const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = DialogPrimitive.Portal;
const DialogClose = DialogPrimitive.Close;

const DialogOverlay = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Overlay
    ref={ref}
    className={cn(
      "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
      className,
    )}
    {...props}
  />
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;

const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
        className,
      )}
      {...props}
    >
      {children}
      <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
        <X className="h-4 w-4" />
        <span className="sr-only">Close</span>
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;

const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} />
);
DialogHeader.displayName = "DialogHeader";

const DialogTitle = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Title
    ref={ref}
    className={cn("text-lg font-semibold leading-none tracking-tight", className)}
    {...props}
  />
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;

export {
  Dialog,
  DialogPortal,
  DialogOverlay,
  DialogClose,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
};
```

---

## Часть 3: Реализация кнопки с модальным окном

```tsx
// Использование в любом компоненте
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { ExternalLink } from "lucide-react";

// Данные для карты экосистемы (вынести в отдельный файл при необходимости)
const ecosystemLinks = [
  {
    url: "https://skills-panel.ru/",
    title: "Skills Panel",
    description: "Инфраструктура управления человеческим капиталом"
  },
  {
    url: "https://dragon-business.ru/strategic-documents",
    title: "Стратегические документы",
    description: "Визия, дорожная карта, партнёрство"
  },
  {
    url: "https://champions-english.ru/",
    title: "Champions English",
    description: "Методика изучения английского для спорта"
  },
  {
    url: "https://spark-time.ru/glory",
    title: "SparkTime Glory",
    description: "Манифест и хронология проекта"
  },
  {
    url: "https://dragon-russian.ru/competencies",
    title: "Компетенции",
    description: "Команда и экспертиза проекта"
  },
  {
    url: "https://dragon-english.ru/project/2501/vision/memo",
    title: "Memo",
    description: "Краткий обзор проекта для инвесторов"
  },
  {
    url: "https://2050.moscow/",
    title: "2050.Moscow",
    description: "Визуализация будущего"
  },
  {
    url: "https://dragon-quest.ru/",
    title: "Dragon Quest",
    description: "Геймификация обучения"
  }
];

// JSX компонента
const EcosystemButton = () => (
  <div className="flex justify-center py-4">
    <Dialog>
      {/* Триггер-кнопка */}
      <DialogTrigger asChild>
        <Button 
          variant="ghost" 
          className="bg-[#1a2b4b] text-white border-l-2 border-r-2 border-y-0 border-amber-500 hover:bg-[#243a5f] transition-all rounded-full px-6 py-2 shadow-lg"
        >
          📖 Подробнее об экосистеме
        </Button>
      </DialogTrigger>

      {/* Модальное окно */}
      <DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto bg-gradient-to-br from-[#1a2b4b] to-[#0d1a30] border-amber-500/30 text-white">
        <DialogHeader>
          <DialogTitle className="text-xl md:text-2xl font-bold text-amber-400 text-center">
            Глубинный уровень: для тех, кто отвечает за будущие поколения
          </DialogTitle>
        </DialogHeader>
        
        <div className="space-y-6 pt-4">
          
          {/* Блок 1: Люди будущего */}
          <div className="p-4 rounded-xl bg-white/5 border border-white/10">
            <h4 className="text-lg font-semibold text-amber-300 mb-3">🌟 Люди будущего</h4>
            <p className="text-white/80 text-sm leading-relaxed">
              В эпоху ИИ и автоматизации миллионы людей рискуют быть «списанными» как неэффективные. 
              DET создаёт <span className="text-amber-300 font-medium">универсальных людей</span> — способных учиться всю жизнь, 
              адаптироваться и создавать ценность. Таких людей невыгодно «списывать» — они становятся фундаментом новой экономики.
            </p>
          </div>
          
          {/* Блок 2: Карта экосистемы */}
          <div className="p-4 rounded-xl bg-white/5 border border-white/10">
            <h4 className="text-lg font-semibold text-amber-300 mb-4">🗺️ Карта экосистемы Dragon</h4>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
              {ecosystemLinks.map((link) => (
                <a 
                  key={link.url}
                  href={link.url} 
                  target="_blank" 
                  rel="noopener noreferrer" 
                  className="flex items-center justify-between p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-all group"
                >
                  <div>
                    <p className="font-medium text-white group-hover:text-amber-300 transition-colors">
                      {link.title}
                    </p>
                    <p className="text-xs text-white/50">{link.description}</p>
                  </div>
                  <ExternalLink className="w-4 h-4 text-white/30 group-hover:text-amber-400" />
                </a>
              ))}
            </div>
          </div>
          
          {/* Блок 3: Философия */}
          <div className="p-4 rounded-xl bg-white/5 border border-white/10">
            <h4 className="text-lg font-semibold text-amber-300 mb-3">💡 Философия DET</h4>
            <p className="text-white/80 text-sm leading-relaxed">
              Мы не работаем для «одарённых от природы». Наша технология — для тех, кто не смог выучить язык другими методами. 
              Мы даём <span className="text-amber-300 font-medium">«второй родной»</span> — предрасположенность к обучению, 
              которую традиционное образование у многих отнимает.
            </p>
          </div>
          
        </div>
      </DialogContent>
    </Dialog>
  </div>
);

export default EcosystemButton;
```

---

## Часть 4: Стили кнопки (разбор)

| Класс | Назначение |
|-------|------------|
| `bg-[#1a2b4b]` | Тёмный navy фон (контраст на светлом фоне) |
| `text-white` | Белый текст |
| `border-l-2 border-r-2` | Боковые границы (левая и правая) |
| `border-y-0` | Без верхней/нижней границы |
| `border-amber-500` | Золотой/янтарный цвет границы |
| `hover:bg-[#243a5f]` | Осветление фона при hover |
| `rounded-full` | Полностью скруглённые края |
| `px-6 py-2` | Паддинг: 24px по бокам, 8px сверху/снизу |
| `shadow-lg` | Большая тень для "отрыва" от фона |
| `transition-all` | Плавные переходы всех свойств |

---

## Часть 5: Стили модального окна

| Класс | Назначение |
|-------|------------|
| `max-w-4xl` | Максимальная ширина ~896px |
| `max-h-[80vh]` | Макс. высота 80% viewport |
| `overflow-y-auto` | Вертикальный скролл при переполнении |
| `bg-gradient-to-br from-[#1a2b4b] to-[#0d1a30]` | Градиент от navy к тёмному |
| `border-amber-500/30` | Полупрозрачная золотая граница |
| `text-white` | Белый текст по умолчанию |

---

## Часть 6: Карточка ссылки в сетке

```tsx
<a 
  href={url} 
  target="_blank" 
  rel="noopener noreferrer" 
  className="flex items-center justify-between p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-all group"
>
  <div>
    <p className="font-medium text-white group-hover:text-amber-300 transition-colors">
      {title}
    </p>
    <p className="text-xs text-white/50">{description}</p>
  </div>
  <ExternalLink className="w-4 h-4 text-white/30 group-hover:text-amber-400" />
</a>
```

**Эффекты:**
- При hover фон осветляется (5% → 10% белого)
- Заголовок меняет цвет на amber
- Иконка меняет цвет на amber

---

## Часть 7: Цветовая палитра

```css
/* Основные цвета компонента */
--navy-dark: #1a2b4b;      /* Фон кнопки и модального окна */
--navy-darker: #0d1a30;    /* Конец градиента */
--navy-hover: #243a5f;     /* Hover-состояние */
--amber-500: #f59e0b;      /* Акцентный цвет (границы, заголовки) */
--amber-300: #fcd34d;      /* Выделенный текст */
--amber-400: #fbbf24;      /* Заголовки в модальном окне */
```

---

## Часть 8: Чек-лист внедрения

1. **Зависимости**
   - [ ] Установить `@radix-ui/react-dialog`
   - [ ] Установить `lucide-react`
   - [ ] Установить `tailwind-merge`, `clsx`, `class-variance-authority`

2. **Файлы**
   - [ ] Создать `src/lib/utils.ts`
   - [ ] Создать `src/components/ui/button.tsx`
   - [ ] Создать `src/components/ui/dialog.tsx`

3. **Tailwind**
   - [ ] Убедиться что `tailwindcss` настроен
   - [ ] Добавить цвета amber в конфиг (если не стандартные)

4. **Использование**
   - [ ] Импортировать компоненты
   - [ ] Добавить данные ecosystemLinks
   - [ ] Вставить JSX в нужное место
