Remove granim dependency

This commit is contained in:
Ruslan Bakiev
2026-02-10 16:52:21 +07:00
parent c7846996bc
commit 27dc375f33

View File

@@ -1,6 +1,5 @@
<template>
<div data-theme="silk" class="min-h-screen bg-mesh text-neutral">
<canvas id="canvas-basic" class="gradient-canvas" aria-hidden="true"></canvas>
<div class="relative z-10">
<div
class="pointer-events-none absolute -top-24 left-1/2 h-72 w-[1100px] -translate-x-1/2 rounded-full bg-[radial-gradient(circle_at_center,rgba(67,56,118,0.25),transparent_70%)] blur-3xl"
@@ -10,25 +9,25 @@
<div class="grid gap-8 lg:grid-cols-[220px_1fr]">
<aside class="hidden lg:block">
<div class="glass-panel sticky top-10 rounded-3xl border border-base-300 p-5 shadow-soft">
<div class="text-xs uppercase tracking-[0.2em] text-neutral/50">Навигация</div>
<nav class="mt-4 space-y-2 text-sm">
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#context">Контекст</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#problem">Проблемы</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#core">Core-фича</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#flow">Как работает</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#value">Value Proposition</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#prototype">Прототип</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#monetization">Монетизация</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#metrics">Метрики</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#roadmap">Roadmap</a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#final">Итог</a>
<nav class="space-y-2 text-sm">
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#context"><span class="nav-num">01</span><span class="nav-text">Контекст</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#alternatives"><span class="nav-num">02</span><span class="nav-text">Альтернативы</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#problem"><span class="nav-num">03</span><span class="nav-text">Проблемы</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#core"><span class="nav-num">04</span><span class="nav-text">Core-фича</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#flow"><span class="nav-num">05</span><span class="nav-text">Key user flow</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#value"><span class="nav-num">06</span><span class="nav-text">Value Proposition</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#prototype"><span class="nav-num">07</span><span class="nav-text">Прототип</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#monetization"><span class="nav-num">08</span><span class="nav-text">Монетизация</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#metrics"><span class="nav-num">09</span><span class="nav-text">Метрики</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#roadmap"><span class="nav-num">10</span><span class="nav-text">Roadmap</span></a>
<a class="nav-link block rounded-2xl px-3 py-2 text-neutral/70 border border-transparent" href="#final"><span class="nav-num">11</span><span class="nav-text">Контакты</span></a>
</nav>
</div>
</aside>
<div class="space-y-10">
<section id="context" class="slide">
<div class="slide-top">Контекст</div>
<div class="slide-top"><span class="slide-num">01</span><span class="slide-label">Контекст</span></div>
<div class="slide-head">
<h2 class="slide-title">Ремонт редкий и дорогой опыт</h2>
<p class="slide-preamble">
@@ -42,8 +41,41 @@
<div class="slide-main"></div>
</section>
<section id="alternatives" class="slide">
<div class="slide-top"><span class="slide-num">02</span><span class="slide-label">Альтернативы</span></div>
<div class="slide-head">
<h2 class="slide-title">Сегодня все держится на «костылях»</h2>
<p class="slide-preamble">
Пока нет единого стандарта, люди собирают процесс из разрозненных инструментов. Это
разрывает коммуникацию, создает разные версии правды и делает контроль почти невозможным.
</p>
</div>
<div class="slide-main">
<div class="grid gap-6 md:grid-cols-3 md:items-end">
<div class="glass-card rounded-3xl p-6 shadow-soft md:translate-y-6">
<h3 class="font-display text-2xl">Мессенджеры</h3>
<p class="mt-3 text-sm text-neutral/70">
Фото и обсуждения разъезжаются по чатам, решения теряются в переписке.
</p>
</div>
<div class="glass-card rounded-3xl p-6 shadow-soft md:translate-y-12">
<h3 class="font-display text-2xl">Таблицы и документы</h3>
<p class="mt-3 text-sm text-neutral/70">
Сметы и списки ведутся вручную, версии расходятся, правки не фиксируются.
</p>
</div>
<div class="glass-card rounded-3xl p-6 shadow-soft">
<h3 class="font-display text-2xl">Фотоархивы и звонки</h3>
<p class="mt-3 text-sm text-neutral/70">
Статусы передаются голосом, нет доказуемых критериев качества.
</p>
</div>
</div>
</div>
</section>
<section id="problem" class="slide">
<div class="slide-top">Проблемы</div>
<div class="slide-top"><span class="slide-num">03</span><span class="slide-label">Проблемы</span></div>
<div class="slide-head">
<h2 class="slide-title">Ключевые проблемы</h2>
<p class="slide-preamble">
@@ -80,7 +112,7 @@
</section>
<section id="core" class="slide">
<div class="slide-top">Core-фича</div>
<div class="slide-top"><span class="slide-num">04</span><span class="slide-label">Core-фича</span></div>
<div class="slide-head">
<h2 class="slide-title">Ноу-хау: приемка как сервис</h2>
<p class="slide-preamble">
@@ -118,35 +150,35 @@
</section>
<section id="flow" class="slide">
<div class="slide-top">Как работает</div>
<div class="slide-top"><span class="slide-num">05</span><span class="slide-label">Key user flow</span></div>
<div class="slide-head">
<h2 class="slide-title">Простой сценарий в три шага</h2>
<h2 class="slide-title">Как это работает: key user flow</h2>
<p class="slide-preamble">
Мы переводим идею в простой процесс: три шага, которые последовательно ведут клиента от
неопределенности к прозрачной приемке и защищенной оплате для обеих сторон.
Описываем ключевой путь пользователя от старта этапа до приемки: где возникают трения и
как сервис их снимает через регламент, доказуемую проверку и эскроу.
</p>
</div>
<div class="slide-main">
<div class="grid gap-6 md:grid-cols-3">
<div class="glass-card rounded-3xl p-6 shadow-soft">
<div class="text-xs font-semibold text-neutral/60">Шаг 1</div>
<h3 class="mt-2 font-display text-2xl">Вход и расчет</h3>
<h3 class="font-display text-2xl">Старт проекта</h3>
<p class="mt-3 text-sm text-neutral/70">
Заказчик загружает объект, система сразу считает смету и формирует план.
Заказчик добавляет объект (фото/видео/обмеры), получает смету, этапы и критерии. Точка
трения снимается заранее: все ожидают одинаковый результат.
</p>
</div>
<div class="glass-card rounded-3xl p-6 shadow-soft">
<div class="text-xs font-semibold text-neutral/60">Шаг 2</div>
<h3 class="mt-2 font-display text-2xl">Регламент и работа</h3>
<h3 class="font-display text-2xl">Ведение этапа</h3>
<p class="mt-3 text-sm text-neutral/70">
Этапы и критерии фиксируются, исполнитель ведет работы по чек-листам.
Исполнитель работает по регламенту и чек-листам, прогресс фиксируется. Заказчик видит
прозрачный статус без переписки.
</p>
</div>
<div class="glass-card rounded-3xl p-6 shadow-soft">
<div class="text-xs font-semibold text-neutral/60">Шаг 3</div>
<h3 class="mt-2 font-display text-2xl">Независимая проверка</h3>
<h3 class="font-display text-2xl">Приемка и расчет</h3>
<p class="mt-3 text-sm text-neutral/70">
Инспектор подтверждает качество, сервис переводит эскроу исполнителю по результату.
Независимый инспектор сверяет критерии, сервис фиксирует решение и переводит эскроу.
Спор заменяется фактами.
</p>
</div>
</div>
@@ -154,12 +186,12 @@
</section>
<section id="value" class="slide">
<div class="slide-top">Value Proposition</div>
<div class="slide-top"><span class="slide-num">06</span><span class="slide-label">Value Proposition</span></div>
<div class="slide-head">
<h2 class="slide-title">Что получает каждая сторона</h2>
<p class="slide-preamble">
Итог сценария должен быть очевиден для обеих ролей. Мы фиксируем ценность отдельно для
заказчика и для исполнителя, чтобы не было перекоса и спора за «справедливость».
Value Proposition: прозрачный регламент + независимая приемка = доверие между сторонами.
Мы фиксируем ценность отдельно для заказчика и исполнителя, чтобы не было перекоса.
</p>
</div>
<div class="slide-main">
@@ -183,7 +215,7 @@
</section>
<section id="prototype" class="slide">
<div class="slide-top">Прототип</div>
<div class="slide-top"><span class="slide-num">07</span><span class="slide-label">Прототип</span></div>
<div class="slide-head">
<h2 class="slide-title">Один экран один смысл</h2>
<p class="slide-preamble">
@@ -212,7 +244,7 @@
</section>
<section id="monetization" class="slide">
<div class="slide-top">Монетизация</div>
<div class="slide-top"><span class="slide-num">08</span><span class="slide-label">Монетизация</span></div>
<div class="slide-head">
<h2 class="slide-title">Прозрачные источники выручки</h2>
<p class="slide-preamble">
@@ -255,7 +287,7 @@
</section>
<section id="metrics" class="slide">
<div class="slide-top">Метрики</div>
<div class="slide-top"><span class="slide-num">09</span><span class="slide-label">Метрики</span></div>
<div class="slide-head">
<h2 class="slide-title">Проверяем, что продукт работает</h2>
<p class="slide-preamble">
@@ -267,9 +299,10 @@
<div class="grid gap-6 md:grid-cols-[1fr_1fr]">
<div>
<h3 class="font-display text-2xl">North Star Metric</h3>
<p class="mt-3 text-sm text-neutral/70">Доля этапов, принятых с первого раза.</p>
<p class="mt-3 text-sm text-neutral/70">Доля этапов, принятых с первого раза без спора.</p>
<p class="mt-3 text-sm text-neutral/70">
Влияют: точность автосметы, скорость приемки, доля зеленых оценок.
Input-метрики: доля этапов с зафиксированными критериями, среднее время согласования
этапа, точность автосметы, доля приемок с «зеленым» статусом.
</p>
</div>
<div class="grid gap-4">
@@ -291,18 +324,19 @@
</section>
<section id="roadmap" class="slide">
<div class="slide-top">Roadmap</div>
<div class="slide-top"><span class="slide-num">10</span><span class="slide-label">Roadmap</span></div>
<div class="slide-head">
<h2 class="slide-title">Валидация и масштабирование</h2>
<h2 class="slide-title">От пилота к системе приемки</h2>
<p class="slide-preamble">
В фокусе не разработка, а проверка гипотез и запуск в реальных процессах. Сначала пилот
и валидируемые результаты, затем подключение партнеров и масштабирование.
Сначала проверяем гипотезы на реальных ремонтах, затем усиливаем расчет ресурсов и выносим
независимую приемку как масштабируемый сервис.
</p>
</div>
<div class="slide-main">
<div class="glass-panel rounded-3xl border border-base-300 p-6">
<div class="grid gap-4 text-sm">
<div class="grid grid-cols-6 gap-2 text-xs text-neutral/50">
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] gap-2 text-xs text-neutral/50">
<div>Этап</div>
<div>М1</div>
<div>М2</div>
<div>М3</div>
@@ -311,29 +345,34 @@
<div>М6</div>
</div>
<div class="grid grid-cols-[160px_1fr] items-center gap-4">
<div class="text-neutral/70">Пилот и гипотезы</div>
<div class="grid grid-cols-6 gap-2">
<div class="col-span-2 rounded-full bg-primary py-2 text-center text-xs text-primary-content">М1М2</div>
<div class="col-span-4 rounded-full bg-base-300/70 py-2"></div>
</div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Пилот на ремонтах</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М1</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М2</div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
</div>
<div class="grid grid-cols-[160px_1fr] items-center gap-4">
<div class="text-neutral/70">Встраивание в процессы</div>
<div class="grid grid-cols-6 gap-2">
<div class="col-span-2 rounded-full bg-base-300/70 py-2"></div>
<div class="col-span-2 rounded-full bg-primary py-2 text-center text-xs text-primary-content">М3М4</div>
<div class="col-span-2 rounded-full bg-base-300/70 py-2"></div>
</div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Расчет ресурсной сметы</div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М3</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М4</div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
</div>
<div class="grid grid-cols-[160px_1fr] items-center gap-4">
<div class="text-neutral/70">Масштабирование</div>
<div class="grid grid-cols-6 gap-2">
<div class="col-span-4 rounded-full bg-base-300/70 py-2"></div>
<div class="col-span-2 rounded-full bg-primary py-2 text-center text-xs text-primary-content">М5М6</div>
</div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Инспектор и приемка</div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М5</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М6</div>
</div>
</div>
</div>
@@ -341,13 +380,19 @@
</section>
<section id="final" class="slide">
<div class="slide-top"><span class="slide-num">11</span><span class="slide-label">Контакты</span></div>
<div class="slide-main items-center justify-center text-center">
<div class="flex flex-col items-center gap-4">
<img src="/avatar.jpg" alt="Руслан Бакиев" class="h-28 w-28 rounded-full object-cover ring-2 ring-base-300" />
<div class="font-display text-3xl text-neutral">Спасибо за внимание</div>
<div class="text-neutral/70">
<div class="text-lg text-neutral">Руслан Бакиев</div>
<div class="text-sm">Телеграм: veikab</div>
<a class="telegram-btn mt-2 inline-flex items-center gap-2" href="https://t.me/veikab" target="_blank" rel="noopener noreferrer">
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="currentColor" aria-hidden="true">
<path d="M21.8 2.2a1.5 1.5 0 0 0-1.6-.2L3.6 9.3a1.5 1.5 0 0 0 .2 2.8l4.6 1.5 1.7 5.1a1.5 1.5 0 0 0 2.5.6l3.1-3 4.4 3.2a1.5 1.5 0 0 0 2.4-.9l3.2-14.2a1.5 1.5 0 0 0-.3-1.2ZM9.9 13.2l7.8-7.1-6.3 8.4-.3 3.5-1.4-4.2-3.6-1.2 10.8-4.3-7 5Z"/>
</svg>
<span>Телеграм: veikab</span>
</a>
</div>
</div>
</div>
@@ -360,8 +405,6 @@
</template>
<script setup>
import { onMounted, onUnmounted } from 'vue'
import Granim from 'granim'
useHead({
title: 'Контроль ремонта — презентация',
@@ -369,31 +412,6 @@ useHead({
{ name: 'description', content: 'Презентация продукта: смета, приемка, эскроу и методология ремонта.' }
]
})
let granimInstance
onMounted(() => {
granimInstance = new Granim({
element: '#canvas-basic',
direction: 'radial',
isPausedWhenNotInView: true,
states: {
'default-state': {
gradients: [
['#ff9966', '#ff5e62'],
['#00F260', '#0575E6'],
['#e1eec3', '#f05053']
]
}
}
})
onUnmounted(() => {
if (granimInstance && granimInstance.pause) granimInstance.pause()
})
})
</script>
<style>
@@ -415,18 +433,11 @@ html {
font-family: 'Space Grotesk', system-ui, sans-serif;
}
.gradient-canvas {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
filter: saturate(1.1);
}
.nav-link {
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 6px;
}
.nav-link:hover {
@@ -437,6 +448,18 @@ html {
color: rgba(20, 20, 20, 0.85);
}
.nav-num {
font-size: 0.7rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: rgba(20, 20, 20, 0.4);
width: 22px;
}
.nav-text {
flex: 1;
}
.slide {
border-radius: 2rem;
background: color-mix(in oklab, white 80%, transparent);
@@ -449,13 +472,40 @@ html {
}
.slide-top {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.2em;
color: rgba(20, 20, 20, 0.45);
margin-bottom: 1.25rem;
}
.slide-num {
color: rgba(20, 20, 20, 0.35);
}
.slide-label {
color: rgba(20, 20, 20, 0.6);
}
.telegram-btn {
padding: 8px 14px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.5);
background: rgba(255, 255, 255, 0.45);
backdrop-filter: blur(14px) saturate(1.1);
-webkit-backdrop-filter: blur(14px) saturate(1.1);
color: rgba(20, 20, 20, 0.85);
font-size: 0.85rem;
transition: all 0.2s ease;
}
.telegram-btn:hover {
background: rgba(255, 255, 255, 0.65);
border-color: rgba(255, 255, 255, 0.7);
}
.slide-title {
font-family: 'Space Grotesk', system-ui, sans-serif;
font-size: clamp(2rem, 3vw, 2.75rem);