каталог всяких штучек, которые я сделал.
сайты, сервисы, инструменты и эксперименты. если хочется посмотреть их как презентацию, .
PRODUCT
id: vvrshn
Название: VVRSHN.ru
Категория: Сайт
Порядок списка: 1
Главная: да
NEW: нет
Статус: доступен
Ссылка: https://vvrshn.ru/
Кнопка: Открыть сайт
Коротко: Главный сайт и центральная точка всех моих проектов.
Класс визуала: site-main
DESCRIPTION
Мой основной сайт и центральная точка всего, чем я занимаюсь. Здесь собраны видеосъёмка, свадьбы, отдельные проекты для event-индустрии, мои эксперименты с разработкой, сервисы, расширения и другие штуки, которые постепенно появляются вокруг моей работы.
ENDDESCRIPTION
VISUAL_HTML
<div class="site-shell">
<div class="site-left">
<div class="site-name">
Я Вова<br>
Вершинин.
</div>
<div class="site-subtitle">
Это мой сайт.
</div>
<div class="site-lines">
<div class="site-line line-a"></div>
<div class="site-line line-b"></div>
<div class="site-line line-c"></div>
</div>
</div>
<div class="site-right">
<div class="site-browser">
<div class="browser-top">
<div class="browser-dots">
<span></span>
<span></span>
<span></span>
</div>
<div class="browser-url">
vvrshn.ru
</div>
</div>
<div class="browser-content">
<div class="browser-title">
Вова<br>
Вершинин
</div>
<div class="browser-links">
<div class="browser-link link-1">
свадьбы
</div>
<div class="browser-link link-2">
показываю видео
</div>
<div class="browser-link link-3">
разработки
</div>
<div class="browser-link link-4">
vibe coding
</div>
</div>
</div>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.site-main {
background:
linear-gradient(
115deg,
#f5f4ef 0%,
#fbfaf6 49.9%,
#0d0d0e 50%,
#080809 100%
);
}
.site-main .site-shell {
position: absolute;
inset: 0;
display: grid;
grid-template-columns:
1fr
1fr;
overflow: hidden;
}
/* =========================================================
LEFT
========================================================= */
.site-main .site-left {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
padding:
10%
11%;
}
.site-main .site-name {
color: #111;
font-size:
clamp(
19px,
3.3vw,
48px
);
line-height: .9;
font-weight: 760;
letter-spacing: -.075em;
}
.site-main .site-subtitle {
margin-top: 7%;
color:
rgba(0,0,0,.38);
font-size:
clamp(
6px,
.8vw,
11px
);
letter-spacing: -.02em;
}
.site-main .site-lines {
width: 58%;
margin-top: 12%;
display: flex;
flex-direction: column;
gap:
clamp(
4px,
.55vw,
8px
);
}
.site-main .site-line {
height:
clamp(
3px,
.42vw,
6px
);
border-radius: 999px;
background:
rgba(0,0,0,.08);
}
.site-main .line-a {
width: 100%;
}
.site-main .line-b {
width: 74%;
}
.site-main .line-c {
width: 46%;
}
/* =========================================================
RIGHT
========================================================= */
.site-main .site-right {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.site-main .site-browser {
position: absolute;
left: 10%;
right: 7%;
top: 10%;
bottom: 10%;
overflow: hidden;
border:
1px solid
rgba(255,255,255,.09);
border-radius:
clamp(
15px,
2vw,
28px
);
background:
#151516;
box-shadow:
0
34px
90px
rgba(0,0,0,.42);
transform:
perspective(900px)
rotateY(-7deg)
rotateZ(1.2deg)
translateX(3%);
transition:
transform
.55s
cubic-bezier(.2,.8,.2,1);
}
.site-main:hover .site-browser {
transform:
perspective(900px)
rotateY(0deg)
rotateZ(0deg)
translateX(0);
}
/* =========================================================
BROWSER TOP
========================================================= */
.site-main .browser-top {
height: 14%;
min-height: 22px;
padding:
0
5%;
display: flex;
align-items: center;
border-bottom:
1px solid
rgba(255,255,255,.055);
background:
rgba(255,255,255,.025);
}
.site-main .browser-dots {
display: flex;
gap:
clamp(
3px,
.4vw,
5px
);
}
.site-main .browser-dots span {
width:
clamp(
3px,
.45vw,
6px
);
aspect-ratio: 1;
border-radius: 50%;
background:
rgba(255,255,255,.18);
}
.site-main .browser-url {
position: absolute;
left: 50%;
transform:
translateX(-50%);
color:
rgba(255,255,255,.24);
font-size:
clamp(
4px,
.55vw,
8px
);
letter-spacing: .02em;
}
/* =========================================================
BROWSER CONTENT
========================================================= */
.site-main .browser-content {
position: absolute;
inset:
14%
0
0;
padding:
12%;
display: flex;
flex-direction: column;
justify-content: center;
}
.site-main .browser-title {
color: #fff;
font-size:
clamp(
14px,
2.25vw,
32px
);
line-height: .92;
font-weight: 720;
letter-spacing: -.065em;
}
.site-main .browser-links {
margin-top: 13%;
display: flex;
flex-direction: column;
gap:
clamp(
5px,
.7vw,
9px
);
}
.site-main .browser-link {
width: fit-content;
position: relative;
color:
rgba(255,255,255,.42);
font-size:
clamp(
5px,
.65vw,
9px
);
line-height: 1;
transition:
color .35s ease,
transform .35s ease;
}
.site-main .browser-link::after {
content: "";
position: absolute;
left: 0;
bottom: -3px;
width: 0;
height: 1px;
background:
rgba(255,255,255,.8);
transition:
width .45s
cubic-bezier(.2,.8,.2,1);
}
.site-main:hover .link-1 {
color:
rgba(255,255,255,.86);
transform:
translateX(3px);
}
.site-main:hover .link-1::after {
width: 100%;
}
.site-main:hover .link-2 {
color:
rgba(255,255,255,.65);
transform:
translateX(6px);
}
.site-main:hover .link-3 {
color:
rgba(255,255,255,.55);
transform:
translateX(9px);
}
.site-main:hover .link-4 {
color:
rgba(255,255,255,.46);
transform:
translateX(12px);
}
/* =========================================================
LIGHT MOTION
========================================================= */
.site-main .site-browser::after {
content: "";
position: absolute;
width: 70%;
height: 150%;
left: -90%;
top: -25%;
transform:
rotate(18deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.035),
transparent
);
transition:
left
1s
cubic-bezier(.2,.8,.2,1);
pointer-events: none;
}
.site-main:hover .site-browser::after {
left: 130%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: vvrshn-watch
Название: VVRSHN Watch
Категория: Сайт
Порядок списка: 2
Главная: нет
NEW: нет
Статус: доступен
Ссылка: https://vvrshn.ru/watch
Кнопка: Открыть сайт
Коротко: Поиск и быстрый просмотр видео из моего портфолио.
Класс визуала: watch-site
DESCRIPTION
Отдельный сайт для просмотра моего видеопортфолио. Работы автоматически собираются в единую базу, а нужное видео можно найти через поиск и быстрые категории. Это способ не листать десятки страниц портфолио, а сразу находить подходящие примеры съёмок.
ENDDESCRIPTION
VISUAL_HTML
<div class="watch-window">
<div class="watch-top">
<div class="watch-logo">
watch
</div>
<div class="watch-counter">
портфолио
</div>
</div>
<div class="watch-search">
<span>
свадьба SDE репортаж
</span>
<div class="search-icon"></div>
</div>
<div class="watch-tags">
<div class="watch-tag active">
SDE
</div>
<div class="watch-tag">
свадьба
</div>
</div>
<div class="watch-grid">
<div class="watch-video video-1">
<div class="video-play"></div>
</div>
<div class="watch-video video-2">
<div class="video-play"></div>
</div>
<div class="watch-video video-3">
<div class="video-play"></div>
</div>
<div class="watch-video video-4">
<div class="video-play"></div>
</div>
</div>
<div class="watch-more">
показать ещё
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.watch-site {
background:
linear-gradient(
145deg,
#f5f5f2,
#e8e8e4
);
}
.watch-site .watch-window {
position: absolute;
left: 8%;
right: 8%;
top: 10%;
bottom: 10%;
padding: 5%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.06);
border-radius: 24px;
background:
rgba(255,255,255,.96);
box-shadow:
0
30px
80px
rgba(0,0,0,.10);
transform:
rotate(-1.2deg)
translateY(1%);
transition:
transform
.55s
cubic-bezier(.2,.8,.2,1);
}
.watch-site:hover .watch-window {
transform:
rotate(0)
translateY(0);
}
.watch-site .watch-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.watch-site .watch-logo {
color: #111;
font-size:
clamp(
13px,
1.8vw,
25px
);
line-height: 1;
font-weight: 760;
letter-spacing: -.06em;
}
.watch-site .watch-counter {
color:
rgba(0,0,0,.30);
font-size:
clamp(
5px,
.55vw,
8px
);
text-transform: uppercase;
letter-spacing: .13em;
}
.watch-site .watch-search {
position: relative;
height: 14%;
margin-top: 6%;
padding:
0
4%;
display: flex;
align-items: center;
border:
1px solid
rgba(0,0,0,.08);
border-radius: 999px;
background: #f3f3f1;
color:
rgba(0,0,0,.27);
font-size:
clamp(
6px,
.75vw,
10px
);
}
.watch-site .search-icon {
position: absolute;
right: 4%;
width:
clamp(
8px,
1vw,
13px
);
aspect-ratio: 1;
border:
1.5px solid
rgba(0,0,0,.25);
border-radius: 50%;
}
.watch-site .search-icon::after {
content: "";
position: absolute;
right: -30%;
bottom: -20%;
width: 45%;
height: 1.5px;
transform:
rotate(45deg);
transform-origin:
center;
background:
rgba(0,0,0,.25);
}
.watch-site .watch-tags {
margin-top: 4%;
display: flex;
gap: 2%;
}
.watch-site .watch-tag {
padding:
2%
4%;
border-radius: 999px;
background: #f2f2ef;
color:
rgba(0,0,0,.42);
font-size:
clamp(
5px,
.55vw,
8px
);
}
.watch-site .watch-tag.active {
background: #111;
color: #fff;
}
.watch-site .watch-grid {
height: 43%;
margin-top: 5%;
display: grid;
grid-template-columns:
repeat(
2,
1fr
);
grid-template-rows:
repeat(
2,
1fr
);
gap: 5%;
}
.watch-site .watch-video {
position: relative;
overflow: hidden;
border-radius: 10px;
background: #d8d8d4;
}
.watch-site .video-1 {
background:
linear-gradient(
135deg,
#a99a8c,
#ece0d4 47%,
#726960
);
}
.watch-site .video-2 {
background:
linear-gradient(
145deg,
#66727b,
#bac4c9 46%,
#34383d
);
}
.watch-site .video-3 {
background:
linear-gradient(
145deg,
#c5b09b,
#7b6654 52%,
#e2d6c9
);
}
.watch-site .video-4 {
background:
linear-gradient(
145deg,
#807368,
#d0c8be 48%,
#4f4b48
);
}
.watch-site .watch-video::before {
content: "";
position: absolute;
inset: 0;
background:
linear-gradient(
180deg,
rgba(255,255,255,.10),
rgba(0,0,0,.14)
);
}
.watch-site .video-play {
position: absolute;
left: 50%;
top: 50%;
width:
clamp(
14px,
2.2vw,
28px
);
aspect-ratio: 1;
transform:
translate(
-50%,
-50%
);
border-radius: 50%;
background:
rgba(255,255,255,.88);
box-shadow:
0
5px
20px
rgba(0,0,0,.12);
}
.watch-site .video-play::after {
content: "";
position: absolute;
left: 54%;
top: 50%;
transform:
translate(
-50%,
-50%
);
width: 0;
height: 0;
border-top:
3px solid
transparent;
border-bottom:
3px solid
transparent;
border-left:
5px solid
#111;
}
.watch-site .watch-more {
width: fit-content;
margin:
5%
auto
0;
color:
rgba(0,0,0,.32);
font-size:
clamp(
5px,
.55vw,
8px
);
letter-spacing: .02em;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: wfolio-tools
Название: Wfolio Tools
Категория: Расширение
Порядок списка: 1
Главная: нет
NEW: нет
Статус: личный инструмент
Коротко: Расширение, которое добавляет в Wfolio папки для страниц и нормальный редактор HTML-кода.
Класс визуала: wfolio-tools
DESCRIPTION
Моё браузерное расширение для Wfolio. Оно добавляет функции, которых мне не хватало в обычной работе с конструктором: позволяет организовывать страницы по папкам и делает редактирование больших HTML-блоков заметно удобнее. Проект появился из постоянной работы с собственными сайтами на Wfolio и постепенно превращается в набор улучшений самого рабочего интерфейса.
ENDDESCRIPTION
VISUAL_HTML
<div class="wf-window">
<div class="wf-sidebar">
<div class="wf-brand">
wfolio
</div>
<div class="wf-section-title">
СТРАНИЦЫ
</div>
<div class="wf-folder folder-open">
<div class="folder-row">
<span class="folder-icon"></span>
<span>Сайты</span>
<span class="folder-arrow"></span>
</div>
<div class="folder-pages">
<div class="wf-page active">
Главная
</div>
<div class="wf-page">
Каталог
</div>
<div class="wf-page">
Watch
</div>
</div>
</div>
<div class="wf-folder">
<div class="folder-row">
<span class="folder-icon"></span>
<span>Проекты</span>
<span class="folder-arrow"></span>
</div>
</div>
<div class="wf-folder">
<div class="folder-row">
<span class="folder-icon"></span>
<span>Архив</span>
<span class="folder-arrow"></span>
</div>
</div>
</div>
<div class="wf-editor">
<div class="editor-top">
<div class="editor-title">
HTML
</div>
<div class="editor-badge">
Wfolio Tools
</div>
</div>
<div class="editor-code">
<div class="code-line">
<span class="num">01</span>
<span class="pink"><div</span>
<span class="blue"> class</span>
<span class="white">=</span>
<span class="green">"site"</span>
<span class="pink">></span>
</div>
<div class="code-line indent">
<span class="num">02</span>
<span class="pink"><h1></span>
<span class="white">Вова Вершинин</span>
<span class="pink"></h1></span>
</div>
<div class="code-line indent">
<span class="num">03</span>
<span class="pink"><p></span>
<span class="white">Это мой сайт.</span>
<span class="pink"></p></span>
</div>
<div class="code-line">
<span class="num">04</span>
<span class="pink"></div></span>
</div>
<div class="code-line empty">
<span class="num">05</span>
</div>
<div class="code-line">
<span class="num">06</span>
<span class="purple">.site</span>
<span class="white"> {</span>
</div>
<div class="code-line indent">
<span class="num">07</span>
<span class="blue">display</span>
<span class="white">:</span>
<span class="green"> grid</span>
<span class="white">;</span>
</div>
<div class="code-line indent">
<span class="num">08</span>
<span class="blue">min-height</span>
<span class="white">:</span>
<span class="orange"> 100vh</span>
<span class="white">;</span>
</div>
<div class="code-line">
<span class="num">09</span>
<span class="white">}</span>
<span class="cursor"></span>
</div>
</div>
<div class="editor-status">
<div>
HTML / CSS
</div>
<div>
9 строк
</div>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.wfolio-tools {
background:
linear-gradient(
145deg,
#e9e9e7,
#f5f5f2
);
}
/* =========================================================
WINDOW
========================================================= */
.wfolio-tools .wf-window {
position: absolute;
left: 7%;
right: 7%;
top: 9%;
bottom: 9%;
display: grid;
grid-template-columns:
34%
66%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
15px,
2vw,
27px
);
background: #fff;
box-shadow:
0
30px
85px
rgba(0,0,0,.14);
transform:
perspective(1000px)
rotateX(1deg)
rotateY(-2deg)
translateY(1%);
transition:
transform
.55s
cubic-bezier(.2,.8,.2,1),
box-shadow
.55s
cubic-bezier(.2,.8,.2,1);
}
.wfolio-tools:hover .wf-window {
transform:
perspective(1000px)
rotateX(0deg)
rotateY(0deg)
translateY(0);
box-shadow:
0
38px
100px
rgba(0,0,0,.18);
}
/* =========================================================
SIDEBAR
========================================================= */
.wfolio-tools .wf-sidebar {
position: relative;
padding:
8%
8%;
overflow: hidden;
border-right:
1px solid
rgba(0,0,0,.07);
background:
#f4f4f2;
}
.wfolio-tools .wf-brand {
color: #111;
font-size:
clamp(
10px,
1.3vw,
18px
);
font-weight: 750;
letter-spacing: -.05em;
}
.wfolio-tools .wf-section-title {
margin-top: 14%;
margin-bottom: 7%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.48vw,
7px
);
font-weight: 650;
letter-spacing: .13em;
}
/* =========================================================
FOLDERS
========================================================= */
.wfolio-tools .wf-folder {
margin-bottom:
clamp(
6px,
.8vw,
11px
);
}
.wfolio-tools .folder-row {
min-height:
clamp(
17px,
2.4vw,
30px
);
display: flex;
align-items: center;
gap: 7%;
color:
rgba(0,0,0,.58);
font-size:
clamp(
5px,
.65vw,
9px
);
font-weight: 560;
}
.wfolio-tools .folder-icon {
position: relative;
width:
clamp(
9px,
1.15vw,
15px
);
height:
clamp(
7px,
.82vw,
11px
);
border-radius:
2px;
background:
#d5d5d0;
}
.wfolio-tools .folder-icon::before {
content: "";
position: absolute;
left: 8%;
top: -25%;
width: 48%;
height: 38%;
border-radius:
2px
2px
0
0;
background:
#d5d5d0;
}
.wfolio-tools .folder-open
.folder-icon {
background: #111;
}
.wfolio-tools .folder-open
.folder-icon::before {
background: #111;
}
.wfolio-tools .folder-arrow {
width: 4px;
height: 4px;
margin-left: auto;
border-right:
1px solid
rgba(0,0,0,.25);
border-bottom:
1px solid
rgba(0,0,0,.25);
transform:
rotate(-45deg);
}
.wfolio-tools .folder-open
.folder-arrow {
transform:
rotate(45deg)
translateY(-1px);
}
/* =========================================================
PAGES
========================================================= */
.wfolio-tools .folder-pages {
margin:
1%
0
5%
15%;
padding-left: 8%;
border-left:
1px solid
rgba(0,0,0,.08);
}
.wfolio-tools .wf-page {
position: relative;
padding:
4%
7%;
border-radius: 6px;
color:
rgba(0,0,0,.35);
font-size:
clamp(
4px,
.56vw,
8px
);
transition:
background .35s ease,
color .35s ease,
transform .35s ease;
}
.wfolio-tools .wf-page.active {
background: #fff;
color: #111;
box-shadow:
0
5px
14px
rgba(0,0,0,.05);
}
.wfolio-tools:hover
.wf-page.active {
transform:
translateX(3px);
}
/* =========================================================
EDITOR
========================================================= */
.wfolio-tools .wf-editor {
position: relative;
overflow: hidden;
background:
#151518;
}
.wfolio-tools .editor-top {
height: 16%;
min-height: 25px;
padding:
0
6%;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom:
1px solid
rgba(255,255,255,.06);
}
.wfolio-tools .editor-title {
color:
rgba(255,255,255,.86);
font-size:
clamp(
5px,
.7vw,
10px
);
font-weight: 580;
}
.wfolio-tools .editor-badge {
padding:
2%
4%;
border:
1px solid
rgba(255,255,255,.08);
border-radius: 999px;
background:
rgba(255,255,255,.05);
color:
rgba(255,255,255,.4);
font-size:
clamp(
4px,
.45vw,
7px
);
}
/* =========================================================
CODE
========================================================= */
.wfolio-tools .editor-code {
position: absolute;
left: 0;
right: 0;
top: 16%;
bottom: 12%;
padding:
7%
7%;
overflow: hidden;
font-family:
"SFMono-Regular",
Consolas,
"Liberation Mono",
monospace;
}
.wfolio-tools .code-line {
min-height:
clamp(
9px,
1.1vw,
15px
);
display: flex;
align-items: center;
white-space: nowrap;
color:
rgba(255,255,255,.74);
font-size:
clamp(
4px,
.53vw,
7.5px
);
line-height: 1.5;
}
.wfolio-tools .code-line.indent {
padding-left: 5%;
}
.wfolio-tools .num {
width: 12%;
flex: 0 0 auto;
color:
rgba(255,255,255,.16);
user-select: none;
}
.wfolio-tools .pink {
color: #ff7ab2;
}
.wfolio-tools .blue {
color: #7dcfff;
}
.wfolio-tools .green {
color: #b9e77c;
}
.wfolio-tools .orange {
color: #ffb86b;
}
.wfolio-tools .purple {
color: #bf9df7;
}
.wfolio-tools .white {
color:
rgba(255,255,255,.75);
}
/* =========================================================
CURSOR
========================================================= */
.wfolio-tools .cursor {
width: 1px;
height:
clamp(
6px,
.8vw,
10px
);
margin-left: 2px;
background:
rgba(255,255,255,.85);
animation:
wfCursor
1s
steps(1)
infinite;
}
@keyframes wfCursor {
0%,
48% {
opacity: 1;
}
49%,
100% {
opacity: 0;
}
}
/* =========================================================
STATUS BAR
========================================================= */
.wfolio-tools .editor-status {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 12%;
min-height: 18px;
padding:
0
6%;
display: flex;
align-items: center;
justify-content: space-between;
border-top:
1px solid
rgba(255,255,255,.055);
background:
rgba(255,255,255,.025);
color:
rgba(255,255,255,.25);
font-size:
clamp(
4px,
.44vw,
6.5px
);
}
/* =========================================================
SUBTLE ANIMATION
========================================================= */
.wfolio-tools .editor-code::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
background:
linear-gradient(
90deg,
transparent,
rgba(125,207,255,.25),
transparent
);
opacity: 0;
transform:
translateY(0);
transition:
opacity .3s ease;
}
.wfolio-tools:hover
.editor-code::after {
opacity: 1;
animation:
wfScan
2.4s
ease-in-out
infinite;
}
@keyframes wfScan {
0% {
transform:
translateY(5px);
}
100% {
transform:
translateY(145px);
}
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: wedding
Название: Свадебная видеосъёмка
Категория: Сайт
Порядок списка: 3
Главная: нет
NEW: нет
Статус: доступен
Ссылка: https://vvrshn.ru/wedding
Кнопка: Открыть сайт
Коротко: Сайт о свадебной видеосъёмке с интерактивным расчётом стоимости.
Класс визуала: wedding-calc
DESCRIPTION
Отдельный сайт о моей свадебной видеосъёмке. Здесь можно посмотреть, как я снимаю свадьбы, разобраться в формате работы, посмотреть примеры и самостоятельно рассчитать стоимость съёмки. Калькулятор учитывает параметры заказа и сразу показывает ориентировочную цену без необходимости сначала писать мне.
ENDDESCRIPTION
VISUAL_HTML
<div class="wedding-scene">
<div class="wedding-photo">
<div class="photo-sky"></div>
<div class="photo-ground"></div>
<div class="couple">
<div class="person groom">
<div class="head"></div>
<div class="body"></div>
</div>
<div class="person bride">
<div class="veil"></div>
<div class="head"></div>
<div class="body"></div>
</div>
</div>
<div class="wedding-copy">
<div class="wedding-label">
WEDDING FILMS
</div>
<div class="wedding-title">
Снимаю<br>
свадьбы.
</div>
<div class="wedding-small">
целый день без часов
</div>
</div>
</div>
<div class="calculator">
<div class="calc-top">
<div class="calc-title">
Рассчитать съёмку
</div>
<div class="calc-step">
03 / 04
</div>
</div>
<div class="calc-question">
Сколько часов снимаем?
</div>
<div class="hours-row">
<div class="hour">
6
</div>
<div class="hour">
8
</div>
<div class="hour active">
10
</div>
<div class="hour">
12
</div>
</div>
<div class="calc-options">
<div class="calc-option active">
<span class="check"></span>
клип
</div>
<div class="calc-option active">
<span class="check"></span>
фильм
</div>
</div>
<div class="calc-divider"></div>
<div class="calc-result">
<div>
<div class="result-label">
стоимость
</div>
<div class="result-price">
190 000 ₽
</div>
</div>
<div class="calc-arrow">
→
</div>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.wedding-calc {
background:
linear-gradient(
135deg,
#e9e3dc,
#f7f4ef
);
}
/* =========================================================
SCENE
========================================================= */
.wedding-calc .wedding-scene {
position: absolute;
inset: 7%;
display: grid;
grid-template-columns:
54%
46%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.06);
border-radius:
clamp(
16px,
2vw,
28px
);
background: #fff;
box-shadow:
0
30px
85px
rgba(0,0,0,.13);
transform:
perspective(1100px)
rotateX(.8deg)
rotateY(-1.5deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.wedding-calc:hover .wedding-scene {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
38px
100px
rgba(0,0,0,.17);
}
/* =========================================================
WEDDING VISUAL
========================================================= */
.wedding-calc .wedding-photo {
position: relative;
overflow: hidden;
background:
#cbc3b9;
}
.wedding-calc .photo-sky {
position: absolute;
inset:
0
0
42%;
background:
linear-gradient(
180deg,
#d9d6d1,
#c5c0b9
);
}
.wedding-calc .photo-ground {
position: absolute;
left: -10%;
right: -10%;
bottom: -8%;
height: 57%;
border-radius:
50%
50%
0
0;
background:
linear-gradient(
180deg,
#847d73,
#5d5851
);
}
.wedding-calc .photo-ground::after {
content: "";
position: absolute;
inset: 0;
background:
repeating-linear-gradient(
112deg,
transparent
0
9px,
rgba(255,255,255,.025)
10px
11px
);
}
/* =========================================================
COUPLE
========================================================= */
.wedding-calc .couple {
position: absolute;
z-index: 5;
left: 55%;
bottom: 12%;
width: 27%;
height: 52%;
transform:
translateX(-50%);
}
.wedding-calc .person {
position: absolute;
bottom: 0;
width: 46%;
height: 100%;
}
.wedding-calc .groom {
left: 8%;
}
.wedding-calc .bride {
right: 5%;
}
.wedding-calc .person .head {
position: absolute;
left: 50%;
top: 7%;
width: 42%;
aspect-ratio: 1;
transform:
translateX(-50%);
border-radius:
50%;
background:
#c9a88f;
}
.wedding-calc .groom .body {
position: absolute;
left: 18%;
right: 18%;
top: 28%;
bottom: 0;
border-radius:
40%
40%
8%
8%;
background:
#292929;
}
.wedding-calc .bride .body {
position: absolute;
left: 4%;
right: 4%;
top: 27%;
bottom: 0;
clip-path:
polygon(
35% 0,
65% 0,
100% 100%,
0 100%
);
background:
linear-gradient(
180deg,
#f9f8f3,
#e8e5df
);
}
.wedding-calc .veil {
position: absolute;
z-index: -1;
left: -30%;
top: 14%;
width: 105%;
height: 72%;
border-radius:
60%
10%
50%
35%;
background:
linear-gradient(
130deg,
rgba(255,255,255,.72),
rgba(255,255,255,.10)
);
transform:
rotate(10deg);
transform-origin:
top right;
transition:
transform
1s
cubic-bezier(.2,.8,.2,1);
}
.wedding-calc:hover .veil {
transform:
rotate(15deg)
translateX(-4%);
}
/* =========================================================
WEDDING COPY
========================================================= */
.wedding-calc .wedding-copy {
position: absolute;
z-index: 10;
left: 9%;
top: 12%;
}
.wedding-calc .wedding-label {
margin-bottom: 10%;
color:
rgba(0,0,0,.36);
font-size:
clamp(
4px,
.5vw,
7px
);
font-weight: 650;
letter-spacing: .15em;
}
.wedding-calc .wedding-title {
color: #111;
font-size:
clamp(
16px,
2.6vw,
37px
);
line-height: .92;
font-weight: 720;
letter-spacing: -.065em;
}
.wedding-calc .wedding-small {
margin-top: 10%;
color:
rgba(0,0,0,.43);
font-size:
clamp(
5px,
.65vw,
9px
);
}
/* =========================================================
CALCULATOR
========================================================= */
.wedding-calc .calculator {
position: relative;
padding:
9%
10%;
background:
#fff;
}
.wedding-calc .calculator::before {
content: "";
position: absolute;
left: 0;
top: 8%;
bottom: 8%;
width: 1px;
background:
rgba(0,0,0,.06);
}
.wedding-calc .calc-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.wedding-calc .calc-title {
color: #111;
font-size:
clamp(
7px,
.95vw,
13px
);
font-weight: 670;
letter-spacing: -.03em;
}
.wedding-calc .calc-step {
color:
rgba(0,0,0,.24);
font-size:
clamp(
4px,
.48vw,
7px
);
letter-spacing: .08em;
}
/* =========================================================
QUESTION
========================================================= */
.wedding-calc .calc-question {
margin-top: 15%;
color:
rgba(0,0,0,.48);
font-size:
clamp(
5px,
.65vw,
9px
);
}
/* =========================================================
HOURS
========================================================= */
.wedding-calc .hours-row {
margin-top: 7%;
display: grid;
grid-template-columns:
repeat(
4,
1fr
);
gap: 4%;
}
.wedding-calc .hour {
aspect-ratio:
1.25;
display: grid;
place-items: center;
border:
1px solid
rgba(0,0,0,.08);
border-radius:
clamp(
6px,
.7vw,
10px
);
background:
#f5f5f3;
color:
rgba(0,0,0,.42);
font-size:
clamp(
5px,
.68vw,
9px
);
transition:
transform .35s ease,
background .35s ease,
color .35s ease;
}
.wedding-calc .hour.active {
background: #111;
color: #fff;
}
.wedding-calc:hover
.hour.active {
transform:
translateY(-3px);
}
/* =========================================================
OPTIONS
========================================================= */
.wedding-calc .calc-options {
margin-top: 11%;
display: flex;
gap: 8%;
}
.wedding-calc .calc-option {
display: flex;
align-items: center;
gap:
clamp(
4px,
.5vw,
7px
);
color:
rgba(0,0,0,.35);
font-size:
clamp(
5px,
.57vw,
8px
);
}
.wedding-calc .calc-option.active {
color:
rgba(0,0,0,.70);
}
.wedding-calc .check {
position: relative;
width:
clamp(
8px,
.9vw,
12px
);
aspect-ratio: 1;
border-radius:
3px;
background: #111;
}
.wedding-calc .check::after {
content: "";
position: absolute;
left: 29%;
top: 16%;
width: 30%;
height: 50%;
border-right:
1px solid
#fff;
border-bottom:
1px solid
#fff;
transform:
rotate(42deg);
}
/* =========================================================
DIVIDER
========================================================= */
.wedding-calc .calc-divider {
height: 1px;
margin:
13%
0
9%;
background:
rgba(0,0,0,.07);
}
/* =========================================================
RESULT
========================================================= */
.wedding-calc .calc-result {
display: flex;
align-items: flex-end;
justify-content: space-between;
}
.wedding-calc .result-label {
margin-bottom: 7%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.48vw,
7px
);
text-transform: uppercase;
letter-spacing: .12em;
}
.wedding-calc .result-price {
color: #111;
font-size:
clamp(
11px,
1.7vw,
24px
);
line-height: 1;
font-weight: 720;
letter-spacing: -.055em;
}
.wedding-calc .calc-arrow {
width:
clamp(
20px,
2.7vw,
36px
);
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: #111;
color: #fff;
font-size:
clamp(
8px,
1vw,
14px
);
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1);
}
.wedding-calc:hover
.calc-arrow {
transform:
translateX(4px)
rotate(-8deg);
}
/* =========================================================
LIGHT
========================================================= */
.wedding-calc .wedding-photo::after {
content: "";
position: absolute;
z-index: 20;
top: -60%;
left: -80%;
width: 45%;
height: 220%;
transform:
rotate(20deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.16),
transparent
);
transition:
left
1.2s
cubic-bezier(.2,.8,.2,1);
pointer-events: none;
}
.wedding-calc:hover
.wedding-photo::after {
left: 130%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: catalogue
Название: Каталог разработок
Категория: Сайт
Порядок списка: 4
Главная: нет
NEW: да
Статус: beta
Ссылка: https://vvrshn.ru/catalogue
Кнопка: Открыть каталог
Коротко: Каталог всех моих сайтов, сервисов, расширений и других цифровых штук.
Класс визуала: development-catalogue
DESCRIPTION
Этот самый каталог. Здесь в одном месте собраны сайты, сервисы, браузерные расширения и небольшие инструменты, которые я делаю. Каждый новый продукт добавляется отдельным блоком с описанием и собственным визуалом, а сам каталог автоматически собирает из них список и бесконечную карусель карточек.
ENDDESCRIPTION
VISUAL_HTML
<div class="catalogue-space">
<div class="catalogue-label">
VVRSHN / PRODUCTS
</div>
<div class="catalogue-cards">
<div class="mini-card card-left">
<div class="mini-visual visual-watch">
<div class="watch-search"></div>
<div class="watch-grid">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="mini-info">
<div class="mini-type">
САЙТ
</div>
<div class="mini-title">
VVRSHN Watch
</div>
</div>
</div>
<div class="mini-card card-main">
<div class="mini-visual visual-catalogue">
<div class="visual-grid">
<span class="vg-1"></span>
<span class="vg-2"></span>
<span class="vg-3"></span>
<span class="vg-4"></span>
</div>
<div class="catalogue-new">
NEW
</div>
</div>
<div class="mini-info">
<div class="mini-type">
САЙТ
</div>
<div class="mini-title">
Каталог<br>
разработок
</div>
<div class="mini-line"></div>
<div class="mini-line short"></div>
</div>
</div>
<div class="mini-card card-right">
<div class="mini-visual visual-code">
<div class="code-bar"></div>
<div class="code-lines">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="mini-info">
<div class="mini-type">
РАСШИРЕНИЕ
</div>
<div class="mini-title">
Wfolio Tools
</div>
</div>
</div>
</div>
<div class="catalogue-description">
<span class="description-title">
всё в одном месте
</span>
<span class="description-line line-one"></span>
<span class="description-line line-two"></span>
</div>
<div class="catalogue-list-button">
Показать списком
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.development-catalogue {
background:
radial-gradient(
circle at 50% 45%,
#29292b,
#111113 46%,
#050506 100%
);
}
/* =========================================================
SPACE
========================================================= */
.development-catalogue .catalogue-space {
position: absolute;
inset: 0;
overflow: hidden;
}
/* =========================================================
LABEL
========================================================= */
.development-catalogue .catalogue-label {
position: absolute;
z-index: 30;
left: 50%;
top: 8%;
transform:
translateX(-50%);
color:
rgba(255,255,255,.28);
font-size:
clamp(
4px,
.5vw,
7px
);
font-weight: 600;
letter-spacing: .14em;
white-space: nowrap;
}
/* =========================================================
CARDS WRAPPER
========================================================= */
.development-catalogue .catalogue-cards {
position: absolute;
inset: 0;
perspective: 900px;
transform-style:
preserve-3d;
}
/* =========================================================
MINI CARD
========================================================= */
.development-catalogue .mini-card {
position: absolute;
top: 47%;
left: 50%;
width: 34%;
height: 58%;
overflow: hidden;
display: grid;
grid-template-rows:
54%
46%;
border:
1px solid
rgba(255,255,255,.10);
border-radius:
clamp(
10px,
1.4vw,
19px
);
background: #fff;
box-shadow:
0
20px
55px
rgba(0,0,0,.38);
transform-style:
preserve-3d;
transition:
transform
.7s
cubic-bezier(.2,.8,.2,1),
filter
.7s
cubic-bezier(.2,.8,.2,1),
opacity
.7s
ease;
}
/* =========================================================
MAIN CARD
========================================================= */
.development-catalogue .card-main {
z-index: 10;
transform:
translate3d(
-50%,
-50%,
0
)
scale(1);
}
/* =========================================================
LEFT CARD
========================================================= */
.development-catalogue .card-left {
z-index: 5;
opacity: .48;
filter:
blur(4px)
brightness(.62);
transform:
translate3d(
-142%,
-50%,
-130px
)
rotateY(24deg)
scale(.78);
}
/* =========================================================
RIGHT CARD
========================================================= */
.development-catalogue .card-right {
z-index: 5;
opacity: .48;
filter:
blur(4px)
brightness(.62);
transform:
translate3d(
42%,
-50%,
-130px
)
rotateY(-24deg)
scale(.78);
}
/* =========================================================
HOVER
========================================================= */
.development-catalogue:hover
.card-main {
transform:
translate3d(
-50%,
-52%,
20px
)
scale(1.025);
}
.development-catalogue:hover
.card-left {
opacity: .61;
filter:
blur(3px)
brightness(.74);
transform:
translate3d(
-146%,
-50%,
-105px
)
rotateY(20deg)
scale(.80);
}
.development-catalogue:hover
.card-right {
opacity: .61;
filter:
blur(3px)
brightness(.74);
transform:
translate3d(
46%,
-50%,
-105px
)
rotateY(-20deg)
scale(.80);
}
/* =========================================================
VISUALS
========================================================= */
.development-catalogue .mini-visual {
position: relative;
overflow: hidden;
background: #eee;
}
.development-catalogue .visual-catalogue {
background:
linear-gradient(
145deg,
#202022,
#09090a
);
}
.development-catalogue .visual-watch {
padding: 12%;
background:
linear-gradient(
145deg,
#ececea,
#d8d8d4
);
}
.development-catalogue .visual-code {
padding: 12%;
background:
#18181b;
}
/* =========================================================
CENTRAL VISUAL
========================================================= */
.development-catalogue .visual-grid {
position: absolute;
left: 11%;
right: 11%;
top: 16%;
bottom: 16%;
display: grid;
grid-template-columns:
1fr
1fr;
gap: 7%;
}
.development-catalogue .visual-grid span {
position: relative;
overflow: hidden;
border-radius:
clamp(
4px,
.55vw,
8px
);
background:
rgba(255,255,255,.09);
}
.development-catalogue .visual-grid span::after {
content: "";
position: absolute;
left: 12%;
right: 12%;
bottom: 14%;
height: 8%;
border-radius: 999px;
background:
rgba(255,255,255,.18);
}
.development-catalogue .vg-1 {
background:
linear-gradient(
135deg,
#f0eee8 0 50%,
#151515 50%
) !important;
}
.development-catalogue .vg-2 {
background:
linear-gradient(
145deg,
#b7aea5,
#615b55
) !important;
}
.development-catalogue .vg-3 {
background:
linear-gradient(
145deg,
#25252b,
#4a4a53
) !important;
}
.development-catalogue .vg-4 {
background:
linear-gradient(
145deg,
#e5e5e2,
#adada8
) !important;
}
/* =========================================================
NEW
========================================================= */
.development-catalogue .catalogue-new {
position: absolute;
z-index: 20;
right: 8%;
top: 9%;
padding:
4%
6%;
border-radius: 999px;
background: #fff;
color: #111;
font-size:
clamp(
3px,
.4vw,
6px
);
font-weight: 750;
letter-spacing: .09em;
}
/* =========================================================
WATCH MINI VISUAL
========================================================= */
.development-catalogue .watch-search {
width: 100%;
height: 17%;
border-radius: 999px;
background:
rgba(255,255,255,.86);
box-shadow:
0
3px
10px
rgba(0,0,0,.04);
}
.development-catalogue .watch-grid {
height: 62%;
margin-top: 10%;
display: grid;
grid-template-columns:
1fr
1fr;
gap: 8%;
}
.development-catalogue .watch-grid span {
border-radius:
clamp(
3px,
.4vw,
6px
);
background:
linear-gradient(
145deg,
#9c9186,
#d0c7bd
);
}
/* =========================================================
CODE MINI VISUAL
========================================================= */
.development-catalogue .code-bar {
width: 46%;
height: 6%;
border-radius: 999px;
background:
rgba(255,255,255,.13);
}
.development-catalogue .code-lines {
margin-top: 14%;
display: flex;
flex-direction: column;
gap:
clamp(
3px,
.4vw,
5px
);
}
.development-catalogue .code-lines span {
height:
clamp(
2px,
.28vw,
4px
);
border-radius: 999px;
background:
rgba(255,255,255,.13);
}
.development-catalogue .code-lines span:nth-child(1) {
width: 82%;
}
.development-catalogue .code-lines span:nth-child(2) {
width: 61%;
background:
rgba(125,207,255,.32);
}
.development-catalogue .code-lines span:nth-child(3) {
width: 74%;
background:
rgba(185,231,124,.27);
}
.development-catalogue .code-lines span:nth-child(4) {
width: 43%;
}
/* =========================================================
INFO
========================================================= */
.development-catalogue .mini-info {
position: relative;
padding:
10%
11%;
background: #fff;
color: #111;
}
.development-catalogue .mini-type {
color:
rgba(0,0,0,.30);
font-size:
clamp(
3px,
.38vw,
5.5px
);
letter-spacing: .12em;
}
.development-catalogue .mini-title {
margin-top: 11%;
color: #111;
font-size:
clamp(
7px,
1.1vw,
16px
);
line-height: .95;
font-weight: 700;
letter-spacing: -.05em;
}
.development-catalogue .card-main
.mini-title {
font-size:
clamp(
9px,
1.45vw,
20px
);
}
/* =========================================================
LINES
========================================================= */
.development-catalogue .mini-line {
width: 74%;
height: 4px;
margin-top: 11%;
border-radius: 999px;
background:
rgba(0,0,0,.08);
}
.development-catalogue .mini-line.short {
width: 46%;
margin-top: 5%;
}
/* =========================================================
DESCRIPTION BELOW CARDS
========================================================= */
.development-catalogue .catalogue-description {
position: absolute;
left: 50%;
bottom: 8%;
width: 28%;
transform:
translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap:
clamp(
3px,
.4vw,
6px
);
opacity: .42;
}
.development-catalogue .description-title {
margin-bottom: 3%;
color: #fff;
font-size:
clamp(
4px,
.5vw,
7px
);
letter-spacing: .03em;
}
.development-catalogue .description-line {
height: 3px;
border-radius: 999px;
background:
rgba(255,255,255,.16);
}
.development-catalogue .line-one {
width: 100%;
}
.development-catalogue .line-two {
width: 68%;
}
/* =========================================================
LIST BUTTON
========================================================= */
.development-catalogue .catalogue-list-button {
position: absolute;
left: 50%;
bottom: 2.5%;
transform:
translateX(-50%);
padding:
1.5%
3%;
border:
1px solid
rgba(255,255,255,.12);
border-radius: 999px;
background:
rgba(255,255,255,.06);
color:
rgba(255,255,255,.46);
font-size:
clamp(
3px,
.4vw,
6px
);
white-space: nowrap;
}
/* =========================================================
SUBTLE LIGHT
========================================================= */
.development-catalogue .catalogue-space::after {
content: "";
position: absolute;
z-index: 50;
left: -40%;
top: -50%;
width: 30%;
height: 200%;
transform:
rotate(20deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.035),
transparent
);
transition:
left
1.25s
cubic-bezier(.2,.8,.2,1);
pointer-events: none;
}
.development-catalogue:hover
.catalogue-space::after {
left: 125%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: sufler
Название: Суфлёр
Категория: Сервис
Порядок списка: 1
Главная: нет
NEW: да
Статус: доступен
Ссылка: https://vvrshn.ru/sufler
Кнопка: Открыть суфлёр
Коротко: Бесплатный браузерный суфлёр для записи видео и работы с текстом.
Класс визуала: prompter
DESCRIPTION
Бесплатный браузерный суфлёр, который я сделал для собственных съёмок и записей клиентов. Текст можно быстро вставить, настроить размер, скорость и положение строки, запустить автоматическую прокрутку и читать прямо с экрана без установки отдельной программы. Сделал его потому, что многие существующие решения либо платные, либо неудобные.
ENDDESCRIPTION
VISUAL_HTML
<div class="prompter-stage">
<div class="prompter-screen">
<div class="prompter-text">
<div class="text-line muted">
Сегодня я хочу рассказать
</div>
<div class="text-line muted">
о новой штуке, которую
</div>
<div class="text-line active">
я сделал для своих съёмок.
</div>
<div class="text-line muted">
Она работает прямо
</div>
<div class="text-line muted">
в браузере.
</div>
</div>
<div class="focus-line">
<div class="focus-arrow">
›
</div>
</div>
<div class="prompter-gradient top"></div>
<div class="prompter-gradient bottom"></div>
</div>
<div class="prompter-controls">
<div class="control-row">
<div class="control-label">
СКОРОСТЬ
</div>
<div class="speed-control">
<div class="speed-track">
<div class="speed-fill"></div>
<div class="speed-knob"></div>
</div>
<div class="speed-value">
1.2×
</div>
</div>
</div>
<div class="control-row">
<div class="control-label">
ТЕКСТ
</div>
<div class="size-buttons">
<div class="size-button">
A
</div>
<div class="size-button active">
A
</div>
<div class="size-button large">
A
</div>
</div>
</div>
<div class="control-row">
<div class="control-label">
ОРИЕНТИР
</div>
<div class="position-control">
<div class="position-track">
<div class="position-point"></div>
</div>
</div>
</div>
<div class="prompter-actions">
<div class="secondary-action">
редактировать
</div>
<div class="start-action">
<span class="play-icon"></span>
Start
</div>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.prompter {
background:
linear-gradient(
145deg,
#e9e9e6,
#f6f6f3
);
}
/* =========================================================
STAGE
========================================================= */
.prompter .prompter-stage {
position: absolute;
inset: 7%;
display: grid;
grid-template-columns:
68%
32%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background: #fff;
box-shadow:
0
32px
90px
rgba(0,0,0,.13);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.5deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.prompter:hover .prompter-stage {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
40px
105px
rgba(0,0,0,.18);
}
/* =========================================================
SCREEN
========================================================= */
.prompter .prompter-screen {
position: relative;
overflow: hidden;
background:
radial-gradient(
circle at 50% 48%,
#1d1d20,
#09090a 72%
);
}
.prompter .prompter-text {
position: absolute;
left: 9%;
right: 9%;
top: 50%;
transform:
translateY(-50%);
display: flex;
flex-direction: column;
gap:
clamp(
7px,
1vw,
14px
);
transition:
transform
1.2s
cubic-bezier(.2,.8,.2,1);
}
.prompter:hover .prompter-text {
transform:
translateY(
calc(-50% - 13px)
);
}
/* =========================================================
TEXT
========================================================= */
.prompter .text-line {
text-align: center;
color: #fff;
font-size:
clamp(
9px,
1.45vw,
21px
);
line-height: 1.12;
font-weight: 620;
letter-spacing: -.035em;
white-space: nowrap;
}
.prompter .text-line.muted {
color:
rgba(255,255,255,.17);
filter:
blur(.15px);
}
.prompter .text-line.active {
color:
rgba(255,255,255,.96);
transform:
scale(1.025);
}
/* =========================================================
FOCUS
========================================================= */
.prompter .focus-line {
position: absolute;
z-index: 20;
left: 0;
right: 0;
top: 50%;
height: 1px;
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.13) 12%,
rgba(255,255,255,.13) 88%,
transparent
);
}
.prompter .focus-arrow {
position: absolute;
left:
clamp(
7px,
1vw,
14px
);
top: 50%;
transform:
translateY(-50%);
color:
rgba(255,255,255,.65);
font-size:
clamp(
10px,
1.5vw,
21px
);
font-weight: 300;
animation:
prompterArrow
1.7s
ease-in-out
infinite;
}
@keyframes prompterArrow {
0%,
100% {
opacity: .45;
transform:
translateY(-50%)
translateX(0);
}
50% {
opacity: 1;
transform:
translateY(-50%)
translateX(3px);
}
}
/* =========================================================
FADE
========================================================= */
.prompter .prompter-gradient {
position: absolute;
z-index: 10;
left: 0;
right: 0;
height: 25%;
pointer-events: none;
}
.prompter .prompter-gradient.top {
top: 0;
background:
linear-gradient(
180deg,
#09090a,
transparent
);
}
.prompter .prompter-gradient.bottom {
bottom: 0;
background:
linear-gradient(
0deg,
#09090a,
transparent
);
}
/* =========================================================
CONTROLS
========================================================= */
.prompter .prompter-controls {
position: relative;
padding:
12%
11%;
display: flex;
flex-direction: column;
background:
#f7f7f5;
}
.prompter .prompter-controls::before {
content: "";
position: absolute;
left: 0;
top: 8%;
bottom: 8%;
width: 1px;
background:
rgba(0,0,0,.07);
}
/* =========================================================
ROW
========================================================= */
.prompter .control-row {
padding:
10%
0;
border-bottom:
1px solid
rgba(0,0,0,.065);
}
.prompter .control-row:first-child {
padding-top: 3%;
}
.prompter .control-label {
margin-bottom: 9%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.45vw,
6.5px
);
font-weight: 650;
letter-spacing: .13em;
}
/* =========================================================
SPEED
========================================================= */
.prompter .speed-control {
display: flex;
align-items: center;
gap: 10%;
}
.prompter .speed-track {
position: relative;
width: 72%;
height: 3px;
border-radius: 999px;
background:
rgba(0,0,0,.09);
}
.prompter .speed-fill {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 58%;
border-radius: inherit;
background: #111;
}
.prompter .speed-knob {
position: absolute;
left: 58%;
top: 50%;
width:
clamp(
7px,
.8vw,
11px
);
aspect-ratio: 1;
transform:
translate(
-50%,
-50%
);
border-radius: 50%;
background: #111;
box-shadow:
0
2px
8px
rgba(0,0,0,.18);
transition:
left
.7s
cubic-bezier(.2,.8,.2,1);
}
.prompter:hover .speed-knob {
left: 68%;
}
.prompter:hover .speed-fill {
width: 68%;
}
.prompter .speed-value {
color:
rgba(0,0,0,.48);
font-size:
clamp(
5px,
.58vw,
8px
);
white-space: nowrap;
}
/* =========================================================
FONT SIZE
========================================================= */
.prompter .size-buttons {
display: flex;
align-items: center;
gap: 7%;
}
.prompter .size-button {
width:
clamp(
20px,
2.4vw,
33px
);
aspect-ratio: 1;
display: grid;
place-items: center;
border:
1px solid
rgba(0,0,0,.08);
border-radius:
clamp(
5px,
.65vw,
9px
);
background: #fff;
color:
rgba(0,0,0,.35);
font-size:
clamp(
5px,
.6vw,
8px
);
}
.prompter .size-button.active {
background: #111;
color: #fff;
border-color: #111;
}
.prompter .size-button.large {
font-size:
clamp(
7px,
.85vw,
12px
);
}
/* =========================================================
POSITION
========================================================= */
.prompter .position-control {
padding:
4%
0;
}
.prompter .position-track {
position: relative;
width: 100%;
height: 3px;
border-radius: 999px;
background:
rgba(0,0,0,.09);
}
.prompter .position-point {
position: absolute;
left: 48%;
top: 50%;
width:
clamp(
7px,
.8vw,
11px
);
aspect-ratio: 1;
transform:
translate(
-50%,
-50%
);
border:
2px solid
#111;
border-radius: 50%;
background:
#f7f7f5;
}
/* =========================================================
ACTIONS
========================================================= */
.prompter .prompter-actions {
margin-top: auto;
display: flex;
align-items: center;
justify-content: space-between;
gap: 7%;
}
.prompter .secondary-action {
color:
rgba(0,0,0,.35);
font-size:
clamp(
4px,
.52vw,
7px
);
}
.prompter .start-action {
min-height:
clamp(
26px,
3.2vw,
43px
);
padding:
0
12%;
display: flex;
align-items: center;
justify-content: center;
gap:
clamp(
4px,
.5vw,
7px
);
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.6vw,
8px
);
font-weight: 620;
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1),
box-shadow
.4s
cubic-bezier(.2,.8,.2,1);
}
.prompter:hover .start-action {
transform:
translateY(-2px)
scale(1.025);
box-shadow:
0
8px
20px
rgba(0,0,0,.15);
}
/* =========================================================
PLAY
========================================================= */
.prompter .play-icon {
width: 0;
height: 0;
border-top:
3px solid
transparent;
border-bottom:
3px solid
transparent;
border-left:
5px solid
#fff;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: poster
Название: Постеронная
Категория: Сервис
Порядок списка: 2
Главная: нет
NEW: да
Статус: доступен
Ссылка: https://vvrshn.ru/poster
Кнопка: Открыть сервис
Коротко: Генератор вертикальных постеров и карточек для соцсетей прямо в браузере.
Класс визуала: poster-generator
DESCRIPTION
Браузерный генератор постеров и карточек для соцсетей. Можно собрать вертикальный макет, изменить текст, дату, время, подписи и акцентное слово, а затем сохранить готовую картинку. Я сделал его как быстрый инструмент для ситуаций, когда нужно оформить нормальный постер без отдельного графического редактора.
ENDDESCRIPTION
VISUAL_HTML
<div class="poster-workspace">
<div class="poster-toolbar">
<div class="tool-title">
Постеронная
</div>
<div class="tool-field">
<div class="field-label">
ЗАГОЛОВОК
</div>
<div class="field-box">
НОВАЯ ИСТОРИЯ
</div>
</div>
<div class="tool-field">
<div class="field-label">
АКЦЕНТНОЕ СЛОВО
</div>
<div class="field-box active">
ИСТОРИЯ
</div>
</div>
<div class="tool-row">
<div class="mini-field">
<div class="field-label">
ДАТА
</div>
<div class="field-box">
14.09
</div>
</div>
<div class="mini-field">
<div class="field-label">
ВРЕМЯ
</div>
<div class="field-box">
18:30
</div>
</div>
</div>
<div class="download-button">
Скачать
</div>
</div>
<div class="poster-preview-wrap">
<div class="poster-preview">
<div class="poster-word">
ИСТОРИЯ
</div>
<div class="poster-content">
<div class="poster-topline">
VOVA VERSHININ
</div>
<div class="poster-title">
НОВАЯ<br>
ИСТОРИЯ
</div>
<div class="poster-bottom">
<div class="poster-date">
14.09
</div>
<div class="poster-time">
18:30
</div>
</div>
</div>
</div>
<div class="preview-caption">
1080 × 1920
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.poster-generator {
background:
linear-gradient(
145deg,
#efefec,
#dadad6
);
}
/* =========================================================
WORKSPACE
========================================================= */
.poster-generator .poster-workspace {
position: absolute;
inset: 7%;
display: grid;
grid-template-columns:
38%
62%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background:
#f7f7f4;
box-shadow:
0
32px
90px
rgba(0,0,0,.14);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.5deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.poster-generator:hover
.poster-workspace {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
40px
105px
rgba(0,0,0,.18);
}
/* =========================================================
TOOLBAR
========================================================= */
.poster-generator .poster-toolbar {
position: relative;
padding:
11%
10%;
display: flex;
flex-direction: column;
border-right:
1px solid
rgba(0,0,0,.07);
background:
#f4f4f1;
}
.poster-generator .tool-title {
margin-bottom: 14%;
color: #111;
font-size:
clamp(
9px,
1.25vw,
18px
);
font-weight: 740;
letter-spacing: -.055em;
}
/* =========================================================
FIELDS
========================================================= */
.poster-generator .tool-field {
margin-bottom: 10%;
}
.poster-generator .tool-row {
display: grid;
grid-template-columns:
1fr
1fr;
gap: 7%;
}
.poster-generator .mini-field {
min-width: 0;
}
.poster-generator .field-label {
margin-bottom: 6%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.45vw,
6.5px
);
font-weight: 650;
letter-spacing: .13em;
}
.poster-generator .field-box {
min-height:
clamp(
23px,
3vw,
40px
);
padding:
0
8%;
display: flex;
align-items: center;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.08);
border-radius:
clamp(
5px,
.65vw,
9px
);
background: #fff;
color:
rgba(0,0,0,.48);
font-size:
clamp(
4px,
.53vw,
7.5px
);
white-space: nowrap;
}
.poster-generator .field-box.active {
border-color:
rgba(0,0,0,.18);
color: #111;
box-shadow:
0
4px
14px
rgba(0,0,0,.045);
}
/* =========================================================
DOWNLOAD
========================================================= */
.poster-generator .download-button {
min-height:
clamp(
28px,
3.4vw,
45px
);
margin-top: auto;
display: flex;
align-items: center;
justify-content: center;
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.6vw,
8px
);
font-weight: 620;
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1),
box-shadow
.4s
cubic-bezier(.2,.8,.2,1);
}
.poster-generator:hover
.download-button {
transform:
translateY(-2px);
box-shadow:
0
9px
24px
rgba(0,0,0,.15);
}
/* =========================================================
PREVIEW
========================================================= */
.poster-generator .poster-preview-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
background:
linear-gradient(
145deg,
#e1e1de,
#cfcfcb
);
}
/* =========================================================
POSTER
========================================================= */
.poster-generator .poster-preview {
position: relative;
height: 79%;
aspect-ratio:
9 / 16;
overflow: hidden;
border-radius:
clamp(
8px,
1vw,
14px
);
background:
linear-gradient(
160deg,
#171719,
#070708
);
box-shadow:
0
25px
60px
rgba(0,0,0,.25);
transform:
rotate(1.5deg)
translateY(-1%);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1);
}
.poster-generator:hover
.poster-preview {
transform:
rotate(0deg)
translateY(-2%);
}
/* =========================================================
BACKGROUND WORD
========================================================= */
.poster-generator .poster-word {
position: absolute;
left: 50%;
top: 48%;
transform:
translate(
-50%,
-50%
)
rotate(-90deg);
color:
rgba(255,255,255,.035);
font-size:
clamp(
28px,
5vw,
70px
);
line-height: .8;
font-weight: 800;
letter-spacing: -.07em;
white-space: nowrap;
}
/* =========================================================
POSTER CONTENT
========================================================= */
.poster-generator .poster-content {
position: absolute;
inset:
7%
9%;
display: flex;
flex-direction: column;
color: #fff;
}
.poster-generator .poster-topline {
color:
rgba(255,255,255,.38);
font-size:
clamp(
3px,
.38vw,
5.5px
);
letter-spacing: .17em;
}
/* =========================================================
TITLE
========================================================= */
.poster-generator .poster-title {
margin-top: auto;
margin-bottom: auto;
color: #fff;
font-size:
clamp(
13px,
2.2vw,
31px
);
line-height: .89;
font-weight: 730;
letter-spacing: -.07em;
}
/* =========================================================
BOTTOM
========================================================= */
.poster-generator .poster-bottom {
display: flex;
align-items: flex-end;
justify-content: space-between;
}
.poster-generator .poster-date {
color: #fff;
font-size:
clamp(
7px,
1vw,
14px
);
font-weight: 650;
letter-spacing: -.04em;
}
.poster-generator .poster-time {
color:
rgba(255,255,255,.44);
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
CAPTION
========================================================= */
.poster-generator .preview-caption {
position: absolute;
left: 50%;
bottom: 4%;
transform:
translateX(-50%);
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.43vw,
6px
);
letter-spacing: .07em;
}
/* =========================================================
LIGHT SWEEP
========================================================= */
.poster-generator .poster-preview::after {
content: "";
position: absolute;
top: -40%;
left: -90%;
width: 42%;
height: 180%;
transform:
rotate(18deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.055),
transparent
);
transition:
left
1.1s
cubic-bezier(.2,.8,.2,1);
pointer-events: none;
}
.poster-generator:hover
.poster-preview::after {
left: 130%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: media-converter
Название: Медиаконвертер
Категория: Сервис
Порядок списка: 3
Главная: нет
NEW: да
Статус: готов
Коротко: Конвертация видео и аудио прямо в браузере без загрузки файлов на сервер.
Класс визуала: media-converter
DESCRIPTION
Браузерный конвертер видео и аудио. Файл обрабатывается прямо на устройстве пользователя, без отправки исходника на сторонний сервер. Можно быстро изменить формат медиа и сохранить готовый файл обратно на компьютер или телефон. Сделал его как простой локальный инструмент без регистрации, облака и лишних действий.
ENDDESCRIPTION
VISUAL_HTML
<div class="converter-window">
<div class="converter-top">
<div class="converter-brand">
converter
</div>
<div class="converter-state">
LOCAL
</div>
</div>
<div class="converter-body">
<div class="source-file">
<div class="file-icon">
<div class="file-corner"></div>
<div class="file-play"></div>
</div>
<div class="file-info">
<div class="file-name">
wedding-film.mov
</div>
<div class="file-meta">
4K · 1.84 GB
</div>
</div>
</div>
<div class="conversion-flow">
<div class="flow-line"></div>
<div class="flow-arrow">
→
</div>
</div>
<div class="format-card">
<div class="format-label">
FORMAT
</div>
<div class="format-name">
MP4
</div>
<div class="format-codec">
H.264
</div>
</div>
</div>
<div class="converter-progress">
<div class="progress-head">
<span>
Конвертация
</span>
<span>
72%
</span>
</div>
<div class="progress-track">
<div class="progress-fill"></div>
</div>
</div>
<div class="converter-bottom">
<div class="privacy-note">
<span class="privacy-dot"></span>
файл остаётся на устройстве
</div>
<div class="save-button">
Скачать
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.media-converter {
background:
linear-gradient(
145deg,
#ececea,
#d9d9d5
);
}
/* =========================================================
WINDOW
========================================================= */
.media-converter .converter-window {
position: absolute;
left: 7%;
right: 7%;
top: 9%;
bottom: 9%;
padding:
5%
6%;
display: flex;
flex-direction: column;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background: #fbfbf9;
box-shadow:
0
32px
90px
rgba(0,0,0,.13);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.5deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.media-converter:hover
.converter-window {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
40px
105px
rgba(0,0,0,.17);
}
/* =========================================================
TOP
========================================================= */
.media-converter .converter-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.media-converter .converter-brand {
color: #111;
font-size:
clamp(
10px,
1.4vw,
20px
);
font-weight: 760;
letter-spacing: -.055em;
}
.media-converter .converter-state {
padding:
1.5%
3%;
border:
1px solid
rgba(0,0,0,.08);
border-radius: 999px;
color:
rgba(0,0,0,.35);
font-size:
clamp(
3px,
.43vw,
6px
);
font-weight: 700;
letter-spacing: .14em;
}
/* =========================================================
BODY
========================================================= */
.media-converter .converter-body {
margin-top: auto;
margin-bottom: auto;
display: grid;
grid-template-columns:
1fr
18%
.72fr;
align-items: center;
gap: 3%;
}
/* =========================================================
SOURCE FILE
========================================================= */
.media-converter .source-file {
min-height:
clamp(
75px,
10vw,
135px
);
padding:
8%;
display: flex;
align-items: center;
gap: 9%;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
10px,
1.4vw,
18px
);
background: #fff;
box-shadow:
0
12px
30px
rgba(0,0,0,.05);
}
/* =========================================================
FILE ICON
========================================================= */
.media-converter .file-icon {
position: relative;
width:
clamp(
32px,
4.5vw,
62px
);
aspect-ratio:
.82;
flex: 0 0 auto;
overflow: hidden;
border-radius:
clamp(
6px,
.8vw,
11px
);
background:
linear-gradient(
145deg,
#27272b,
#0c0c0e
);
}
.media-converter .file-corner {
position: absolute;
right: 0;
top: 0;
width: 27%;
height: 23%;
background:
rgba(255,255,255,.11);
clip-path:
polygon(
0 0,
100% 100%,
100% 0
);
}
.media-converter .file-play {
position: absolute;
left: 50%;
top: 52%;
transform:
translate(
-50%,
-50%
);
width: 0;
height: 0;
border-top:
5px solid
transparent;
border-bottom:
5px solid
transparent;
border-left:
8px solid
rgba(255,255,255,.84);
}
/* =========================================================
FILE INFO
========================================================= */
.media-converter .file-info {
min-width: 0;
}
.media-converter .file-name {
overflow: hidden;
color: #111;
font-size:
clamp(
6px,
.82vw,
11px
);
font-weight: 620;
letter-spacing: -.025em;
text-overflow: ellipsis;
white-space: nowrap;
}
.media-converter .file-meta {
margin-top: 12%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
FLOW
========================================================= */
.media-converter .conversion-flow {
position: relative;
height: 50px;
}
.media-converter .flow-line {
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 1px;
background:
linear-gradient(
90deg,
rgba(0,0,0,.05),
rgba(0,0,0,.19),
rgba(0,0,0,.05)
);
}
.media-converter .flow-arrow {
position: absolute;
left: 50%;
top: 50%;
width:
clamp(
22px,
2.8vw,
38px
);
aspect-ratio: 1;
display: grid;
place-items: center;
transform:
translate(
-50%,
-50%
);
border:
1px solid
rgba(0,0,0,.08);
border-radius: 50%;
background: #fbfbf9;
color:
rgba(0,0,0,.55);
font-size:
clamp(
8px,
1vw,
14px
);
transition:
transform
.45s
cubic-bezier(.2,.8,.2,1);
}
.media-converter:hover
.flow-arrow {
transform:
translate(
-43%,
-50%
);
}
/* =========================================================
FORMAT
========================================================= */
.media-converter .format-card {
min-height:
clamp(
75px,
10vw,
135px
);
padding:
10%;
display: flex;
flex-direction: column;
justify-content: center;
border-radius:
clamp(
10px,
1.4vw,
18px
);
background:
#111114;
box-shadow:
0
15px
35px
rgba(0,0,0,.14);
transition:
transform
.45s
cubic-bezier(.2,.8,.2,1);
}
.media-converter:hover
.format-card {
transform:
translateY(-3px);
}
.media-converter .format-label {
color:
rgba(255,255,255,.28);
font-size:
clamp(
3px,
.42vw,
6px
);
font-weight: 650;
letter-spacing: .13em;
}
.media-converter .format-name {
margin-top: 9%;
color: #fff;
font-size:
clamp(
16px,
2.3vw,
32px
);
line-height: .9;
font-weight: 760;
letter-spacing: -.065em;
}
.media-converter .format-codec {
margin-top: 10%;
color:
rgba(255,255,255,.35);
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
PROGRESS
========================================================= */
.media-converter .converter-progress {
margin-bottom: 5%;
}
.media-converter .progress-head {
margin-bottom: 2.5%;
display: flex;
justify-content: space-between;
color:
rgba(0,0,0,.34);
font-size:
clamp(
4px,
.5vw,
7px
);
}
.media-converter .progress-track {
position: relative;
height:
clamp(
3px,
.38vw,
5px
);
overflow: hidden;
border-radius: 999px;
background:
rgba(0,0,0,.07);
}
.media-converter .progress-fill {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 72%;
border-radius: inherit;
background: #111;
transition:
width
1s
cubic-bezier(.2,.8,.2,1);
}
.media-converter:hover
.progress-fill {
width: 88%;
}
/* =========================================================
BOTTOM
========================================================= */
.media-converter .converter-bottom {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10%;
}
.media-converter .privacy-note {
display: flex;
align-items: center;
gap:
clamp(
4px,
.5vw,
7px
);
color:
rgba(0,0,0,.34);
font-size:
clamp(
4px,
.5vw,
7px
);
}
.media-converter .privacy-dot {
width:
clamp(
4px,
.45vw,
6px
);
aspect-ratio: 1;
border-radius: 50%;
background: #4bae6c;
box-shadow:
0
0
0
4px
rgba(75,174,108,.08);
}
/* =========================================================
SAVE
========================================================= */
.media-converter .save-button {
min-height:
clamp(
26px,
3vw,
41px
);
padding:
0
7%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.58vw,
8px
);
font-weight: 620;
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1),
box-shadow
.4s
cubic-bezier(.2,.8,.2,1);
}
.media-converter:hover
.save-button {
transform:
translateY(-2px);
box-shadow:
0
8px
22px
rgba(0,0,0,.16);
}
/* =========================================================
SCAN LIGHT
========================================================= */
.media-converter .converter-window::after {
content: "";
position: absolute;
top: -60%;
left: -60%;
width: 28%;
height: 220%;
transform:
rotate(18deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.36),
transparent
);
opacity: .3;
transition:
left
1.2s
cubic-bezier(.2,.8,.2,1);
pointer-events: none;
}
.media-converter:hover
.converter-window::after {
left: 130%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: internet-check
Название: Проверка интернета
Категория: Сервис
Порядок списка: 4
Главная: нет
NEW: нет
Статус: готов
Коротко: Проверка скорости, задержки и качества интернет-соединения прямо в браузере.
Класс визуала: internet-check
DESCRIPTION
Небольшой браузерный инструмент для быстрой проверки интернет-соединения. Показывает основные параметры сети: скорость загрузки и отдачи, задержку и общее состояние соединения. Сделал его как простой инструмент без лишних экранов, рекламы и перегруженного интерфейса.
ENDDESCRIPTION
VISUAL_HTML
<div class="net-window">
<div class="net-header">
<div class="net-title">
internet
</div>
<div class="net-status">
<span class="status-dot"></span>
подключено
</div>
</div>
<div class="net-main">
<div class="speed-circle">
<div class="speed-ring">
<div class="speed-progress"></div>
</div>
<div class="speed-center">
<div class="speed-number">
487
</div>
<div class="speed-unit">
Мбит/с
</div>
</div>
<div class="needle"></div>
</div>
<div class="net-metrics">
<div class="metric">
<div class="metric-label">
DOWNLOAD
</div>
<div class="metric-value">
487
<span>Mbps</span>
</div>
</div>
<div class="metric">
<div class="metric-label">
UPLOAD
</div>
<div class="metric-value">
128
<span>Mbps</span>
</div>
</div>
<div class="metric">
<div class="metric-label">
PING
</div>
<div class="metric-value">
12
<span>ms</span>
</div>
</div>
</div>
</div>
<div class="connection-chart">
<div class="chart-line">
<span class="p1"></span>
<span class="p2"></span>
<span class="p3"></span>
<span class="p4"></span>
<span class="p5"></span>
<span class="p6"></span>
<span class="p7"></span>
</div>
<div class="chart-caption">
стабильность соединения
</div>
</div>
<div class="net-footer">
<div class="server">
сервер автоматически
</div>
<div class="repeat-button">
Проверить ещё раз
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.internet-check {
background:
radial-gradient(
circle at 50% 44%,
#27292d,
#111214 52%,
#070708 100%
);
}
/* =========================================================
WINDOW
========================================================= */
.internet-check .net-window {
position: absolute;
inset: 7%;
padding:
5%
6%;
display: flex;
flex-direction: column;
overflow: hidden;
border:
1px solid
rgba(255,255,255,.09);
border-radius:
clamp(
16px,
2vw,
28px
);
background:
linear-gradient(
150deg,
rgba(31,32,36,.96),
rgba(12,13,15,.98)
);
box-shadow:
0
35px
100px
rgba(0,0,0,.42);
transform:
perspective(1100px)
rotateX(.8deg)
rotateY(-1.5deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.internet-check:hover
.net-window {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
42px
115px
rgba(0,0,0,.5);
}
/* =========================================================
HEADER
========================================================= */
.internet-check .net-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.internet-check .net-title {
color: #fff;
font-size:
clamp(
10px,
1.4vw,
20px
);
font-weight: 750;
letter-spacing: -.055em;
}
.internet-check .net-status {
display: flex;
align-items: center;
gap:
clamp(
4px,
.5vw,
7px
);
color:
rgba(255,255,255,.34);
font-size:
clamp(
4px,
.48vw,
7px
);
}
.internet-check .status-dot {
width:
clamp(
4px,
.45vw,
6px
);
aspect-ratio: 1;
border-radius: 50%;
background: #5ed47d;
box-shadow:
0
0
0
4px
rgba(94,212,125,.08);
animation:
netStatus
1.6s
ease-in-out
infinite;
}
@keyframes netStatus {
50% {
opacity: .45;
}
}
/* =========================================================
MAIN
========================================================= */
.internet-check .net-main {
margin:
auto
0;
display: grid;
grid-template-columns:
43%
57%;
align-items: center;
}
/* =========================================================
SPEED CIRCLE
========================================================= */
.internet-check .speed-circle {
position: relative;
width: 72%;
aspect-ratio: 1;
margin-left: 7%;
}
.internet-check .speed-ring {
position: absolute;
inset: 0;
border:
clamp(
5px,
.7vw,
10px
)
solid
rgba(255,255,255,.07);
border-radius: 50%;
}
.internet-check .speed-progress {
position: absolute;
inset:
calc(
clamp(
5px,
.7vw,
10px
)
* -1
);
border:
clamp(
5px,
.7vw,
10px
)
solid
transparent;
border-top-color:
rgba(255,255,255,.92);
border-right-color:
rgba(255,255,255,.92);
border-bottom-color:
rgba(255,255,255,.34);
border-radius: 50%;
transform:
rotate(36deg);
transition:
transform
1.1s
cubic-bezier(.2,.8,.2,1);
}
.internet-check:hover
.speed-progress {
transform:
rotate(68deg);
}
/* =========================================================
CENTER
========================================================= */
.internet-check .speed-center {
position: absolute;
left: 50%;
top: 50%;
transform:
translate(
-50%,
-50%
);
text-align: center;
}
.internet-check .speed-number {
color: #fff;
font-size:
clamp(
21px,
3.4vw,
48px
);
line-height: .9;
font-weight: 680;
letter-spacing: -.075em;
}
.internet-check .speed-unit {
margin-top: 10%;
color:
rgba(255,255,255,.28);
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
NEEDLE
========================================================= */
.internet-check .needle {
position: absolute;
left: 50%;
top: 50%;
width: 40%;
height: 1px;
transform:
rotate(-16deg);
transform-origin:
left center;
background:
linear-gradient(
90deg,
rgba(255,255,255,.72),
transparent
);
transition:
transform
1.1s
cubic-bezier(.2,.8,.2,1);
}
.internet-check:hover
.needle {
transform:
rotate(22deg);
}
/* =========================================================
METRICS
========================================================= */
.internet-check .net-metrics {
display: grid;
grid-template-columns:
repeat(
3,
1fr
);
gap: 6%;
}
.internet-check .metric {
min-width: 0;
}
.internet-check .metric-label {
margin-bottom: 16%;
color:
rgba(255,255,255,.24);
font-size:
clamp(
3px,
.42vw,
6px
);
font-weight: 650;
letter-spacing: .11em;
}
.internet-check .metric-value {
color:
rgba(255,255,255,.92);
font-size:
clamp(
9px,
1.4vw,
20px
);
line-height: 1;
font-weight: 640;
letter-spacing: -.045em;
}
.internet-check .metric-value span {
display: block;
margin-top: 10%;
color:
rgba(255,255,255,.26);
font-size:
.38em;
font-weight: 450;
letter-spacing: 0;
}
/* =========================================================
CHART
========================================================= */
.internet-check .connection-chart {
margin-top: auto;
padding-top: 5%;
border-top:
1px solid
rgba(255,255,255,.06);
}
.internet-check .chart-line {
height:
clamp(
25px,
3.8vw,
52px
);
display: flex;
align-items: flex-end;
gap: 1.8%;
}
.internet-check .chart-line span {
flex: 1;
border-radius:
3px
3px
0
0;
background:
rgba(255,255,255,.11);
transition:
height
.7s
cubic-bezier(.2,.8,.2,1),
background
.7s
ease;
}
.internet-check .p1 {
height: 42%;
}
.internet-check .p2 {
height: 67%;
}
.internet-check .p3 {
height: 56%;
}
.internet-check .p4 {
height: 82%;
}
.internet-check .p5 {
height: 74%;
}
.internet-check .p6 {
height: 92%;
}
.internet-check .p7 {
height: 78%;
}
.internet-check:hover
.p1 {
height: 63%;
}
.internet-check:hover
.p2 {
height: 78%;
}
.internet-check:hover
.p3 {
height: 73%;
}
.internet-check:hover
.p4 {
height: 91%;
}
.internet-check:hover
.p5 {
height: 83%;
}
.internet-check:hover
.p6 {
height: 96%;
background:
rgba(255,255,255,.32);
}
.internet-check:hover
.p7 {
height: 89%;
}
.internet-check .chart-caption {
margin-top: 2%;
color:
rgba(255,255,255,.20);
font-size:
clamp(
3px,
.4vw,
6px
);
}
/* =========================================================
FOOTER
========================================================= */
.internet-check .net-footer {
margin-top: 4%;
display: flex;
align-items: center;
justify-content: space-between;
}
.internet-check .server {
color:
rgba(255,255,255,.21);
font-size:
clamp(
3px,
.43vw,
6px
);
}
.internet-check .repeat-button {
min-height:
clamp(
22px,
2.7vw,
36px
);
padding:
0
5%;
display: flex;
align-items: center;
justify-content: center;
border:
1px solid
rgba(255,255,255,.12);
border-radius: 999px;
background:
rgba(255,255,255,.055);
color:
rgba(255,255,255,.7);
font-size:
clamp(
4px,
.5vw,
7px
);
transition:
background .35s ease,
transform .35s ease;
}
.internet-check:hover
.repeat-button {
background:
rgba(255,255,255,.1);
transform:
translateY(-2px);
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: youtube-downloader
Название: YouTube Downloader
Категория: Расширение
Порядок списка: 2
Главная: нет
NEW: да
Статус: личный инструмент
Коротко: Браузерное расширение для сохранения видео и аудио с YouTube.
Класс визуала: youtube-downloader
DESCRIPTION
Моё браузерное расширение для сохранения видео и аудио с YouTube. Добавляет простой интерфейс выбора формата и качества прямо рядом с видео, а обработка выполняется локально через связку браузера и инструментов на компьютере. Сделал его прежде всего для собственного рабочего процесса, чтобы быстрее сохранять нужные материалы для монтажа и работы.
ENDDESCRIPTION
VISUAL_HTML
<div class="yt-window">
<div class="yt-video">
<div class="video-image">
<div class="video-gradient"></div>
<div class="video-play">
<span></span>
</div>
<div class="video-time">
12:48
</div>
</div>
<div class="video-info">
<div class="video-title">
Wedding Film
</div>
<div class="video-meta">
YouTube · 4K
</div>
</div>
</div>
<div class="download-panel">
<div class="panel-top">
<div class="panel-title">
Скачать
</div>
<div class="extension-badge">
VVRSHN
</div>
</div>
<div class="format-label">
ВИДЕО
</div>
<div class="quality-list">
<div class="quality-row">
<div>
<div class="quality-name">
2160p
</div>
<div class="quality-meta">
MP4 · 4K
</div>
</div>
<div class="quality-size">
842 MB
</div>
</div>
<div class="quality-row active">
<div>
<div class="quality-name">
1080p
</div>
<div class="quality-meta">
MP4 · Full HD
</div>
</div>
<div class="quality-check">
✓
</div>
</div>
<div class="quality-row">
<div>
<div class="quality-name">
720p
</div>
<div class="quality-meta">
MP4 · HD
</div>
</div>
<div class="quality-size">
214 MB
</div>
</div>
</div>
<div class="format-divider"></div>
<div class="audio-row">
<div>
<div class="format-label">
АУДИО
</div>
<div class="audio-name">
MP3
</div>
</div>
<div class="audio-wave">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="download-button">
<span class="download-icon">
↓
</span>
Скачать
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.youtube-downloader {
background:
linear-gradient(
145deg,
#e9e9e7,
#f5f5f2
);
}
/* =========================================================
WINDOW
========================================================= */
.youtube-downloader .yt-window {
position: absolute;
inset: 7%;
display: grid;
grid-template-columns:
60%
40%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background: #fff;
box-shadow:
0
32px
90px
rgba(0,0,0,.14);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.4deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.youtube-downloader:hover
.yt-window {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
40px
110px
rgba(0,0,0,.18);
}
/* =========================================================
VIDEO SIDE
========================================================= */
.youtube-downloader .yt-video {
position: relative;
padding:
8%;
display: flex;
flex-direction: column;
background:
#f3f3f1;
}
/* =========================================================
VIDEO IMAGE
========================================================= */
.youtube-downloader .video-image {
position: relative;
flex: 1;
overflow: hidden;
border-radius:
clamp(
10px,
1.3vw,
18px
);
background:
linear-gradient(
135deg,
#323035,
#76695d 35%,
#c3ab94 63%,
#545158
);
box-shadow:
0
15px
40px
rgba(0,0,0,.13);
}
.youtube-downloader .video-image::before {
content: "";
position: absolute;
left: 13%;
bottom: -8%;
width: 28%;
height: 76%;
border-radius:
50%
50%
10%
10%;
background:
rgba(20,20,22,.64);
transform:
rotate(-5deg);
}
.youtube-downloader .video-image::after {
content: "";
position: absolute;
right: 13%;
bottom: -8%;
width: 30%;
height: 80%;
border-radius:
50%
50%
10%
10%;
background:
rgba(245,240,232,.68);
transform:
rotate(5deg);
}
.youtube-downloader .video-gradient {
position: absolute;
z-index: 3;
inset: 0;
background:
linear-gradient(
180deg,
rgba(0,0,0,.03),
rgba(0,0,0,.28)
);
}
/* =========================================================
PLAY
========================================================= */
.youtube-downloader .video-play {
position: absolute;
z-index: 10;
left: 50%;
top: 50%;
width:
clamp(
31px,
4vw,
55px
);
aspect-ratio: 1;
display: grid;
place-items: center;
transform:
translate(
-50%,
-50%
);
border-radius: 50%;
background:
rgba(255,255,255,.91);
box-shadow:
0
8px
28px
rgba(0,0,0,.16);
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1);
}
.youtube-downloader:hover
.video-play {
transform:
translate(
-50%,
-50%
)
scale(1.07);
}
.youtube-downloader .video-play span {
width: 0;
height: 0;
margin-left: 7%;
border-top:
clamp(
4px,
.55vw,
7px
)
solid
transparent;
border-bottom:
clamp(
4px,
.55vw,
7px
)
solid
transparent;
border-left:
clamp(
7px,
.85vw,
11px
)
solid
#111;
}
/* =========================================================
TIME
========================================================= */
.youtube-downloader .video-time {
position: absolute;
z-index: 10;
right: 4%;
bottom: 5%;
padding:
1.4%
2.5%;
border-radius: 4px;
background:
rgba(0,0,0,.68);
color: #fff;
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
VIDEO INFO
========================================================= */
.youtube-downloader .video-info {
padding-top: 7%;
}
.youtube-downloader .video-title {
color: #111;
font-size:
clamp(
8px,
1.15vw,
16px
);
font-weight: 680;
letter-spacing: -.04em;
}
.youtube-downloader .video-meta {
margin-top: 3%;
color:
rgba(0,0,0,.30);
font-size:
clamp(
4px,
.5vw,
7px
);
}
/* =========================================================
DOWNLOAD PANEL
========================================================= */
.youtube-downloader .download-panel {
position: relative;
padding:
11%
10%;
display: flex;
flex-direction: column;
border-left:
1px solid
rgba(0,0,0,.07);
background: #fff;
}
/* =========================================================
PANEL TOP
========================================================= */
.youtube-downloader .panel-top {
display: flex;
align-items: center;
justify-content: space-between;
}
.youtube-downloader .panel-title {
color: #111;
font-size:
clamp(
8px,
1.05vw,
15px
);
font-weight: 680;
letter-spacing: -.04em;
}
.youtube-downloader .extension-badge {
padding:
2%
4%;
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
3px,
.36vw,
5px
);
font-weight: 700;
letter-spacing: .11em;
}
/* =========================================================
FORMAT
========================================================= */
.youtube-downloader .format-label {
margin-top: 15%;
color:
rgba(0,0,0,.25);
font-size:
clamp(
3px,
.4vw,
6px
);
font-weight: 700;
letter-spacing: .14em;
}
/* =========================================================
QUALITY
========================================================= */
.youtube-downloader .quality-list {
margin-top: 6%;
}
.youtube-downloader .quality-row {
min-height:
clamp(
31px,
4vw,
54px
);
padding:
0
6%;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom:
1px solid
rgba(0,0,0,.06);
}
.youtube-downloader .quality-row.active {
margin:
2%
-2%;
padding:
0
8%;
border: 0;
border-radius:
clamp(
7px,
.9vw,
12px
);
background:
#f3f3f1;
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1);
}
.youtube-downloader:hover
.quality-row.active {
transform:
translateX(3px);
}
.youtube-downloader .quality-name {
color:
rgba(0,0,0,.72);
font-size:
clamp(
5px,
.65vw,
9px
);
font-weight: 620;
}
.youtube-downloader .quality-meta {
margin-top: 5%;
color:
rgba(0,0,0,.25);
font-size:
clamp(
3px,
.38vw,
5.5px
);
}
.youtube-downloader .quality-size {
color:
rgba(0,0,0,.23);
font-size:
clamp(
3px,
.4vw,
6px
);
}
.youtube-downloader .quality-check {
width:
clamp(
14px,
1.7vw,
23px
);
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.55vw,
8px
);
}
/* =========================================================
DIVIDER
========================================================= */
.youtube-downloader .format-divider {
height: 1px;
margin-top: 8%;
background:
rgba(0,0,0,.07);
}
/* =========================================================
AUDIO
========================================================= */
.youtube-downloader .audio-row {
display: flex;
align-items: flex-end;
justify-content: space-between;
}
.youtube-downloader .audio-row
.format-label {
margin-top: 14%;
}
.youtube-downloader .audio-name {
margin-top: 16%;
color: #111;
font-size:
clamp(
7px,
.9vw,
13px
);
font-weight: 680;
}
.youtube-downloader .audio-wave {
height:
clamp(
20px,
2.7vw,
36px
);
display: flex;
align-items: center;
gap:
clamp(
2px,
.25vw,
4px
);
}
.youtube-downloader .audio-wave span {
width:
clamp(
2px,
.23vw,
3px
);
border-radius: 999px;
background:
rgba(0,0,0,.20);
animation:
ytWave
1.3s
ease-in-out
infinite;
}
.youtube-downloader .audio-wave span:nth-child(1) {
height: 25%;
}
.youtube-downloader .audio-wave span:nth-child(2) {
height: 55%;
animation-delay: -.2s;
}
.youtube-downloader .audio-wave span:nth-child(3) {
height: 85%;
animation-delay: -.4s;
}
.youtube-downloader .audio-wave span:nth-child(4) {
height: 45%;
animation-delay: -.6s;
}
.youtube-downloader .audio-wave span:nth-child(5) {
height: 72%;
animation-delay: -.8s;
}
.youtube-downloader .audio-wave span:nth-child(6) {
height: 38%;
animation-delay: -1s;
}
.youtube-downloader .audio-wave span:nth-child(7) {
height: 62%;
animation-delay: -1.2s;
}
@keyframes ytWave {
50% {
transform:
scaleY(.45);
}
}
/* =========================================================
DOWNLOAD BUTTON
========================================================= */
.youtube-downloader .download-button {
min-height:
clamp(
28px,
3.5vw,
47px
);
margin-top: auto;
display: flex;
align-items: center;
justify-content: center;
gap:
clamp(
5px,
.6vw,
8px
);
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.58vw,
8px
);
font-weight: 620;
transition:
transform
.4s
cubic-bezier(.2,.8,.2,1),
box-shadow
.4s
cubic-bezier(.2,.8,.2,1);
}
.youtube-downloader:hover
.download-button {
transform:
translateY(-2px);
box-shadow:
0
9px
24px
rgba(0,0,0,.16);
}
.youtube-downloader .download-icon {
font-size:
1.25em;
transform:
translateY(-1px);
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: vvrshn-adblock
Название: VVRSHN AdBlock
Категория: Расширение
Порядок списка: 3
Главная: нет
NEW: да
Статус: beta
Коротко: Моё браузерное расширение, которое автоматически находит рекламу на сайтах и аккуратно скрывает её.
Класс визуала: vvrshn-adblock
DESCRIPTION
Браузерный блокировщик рекламы, который я делаю под собственные задачи. Расширение автоматически определяет рекламные блоки на странице и скрывает их так, чтобы не ломать остальной интерфейс сайта. Проект начинался с очистки рабочего интерфейса почты, а постепенно превращается в более универсальный инструмент для спокойного просмотра сайтов без лишних элементов.
ENDDESCRIPTION
VISUAL_HTML
<div class="adblock-browser">
<div class="browser-top">
<div class="browser-dots">
<span></span>
<span></span>
<span></span>
</div>
<div class="browser-address">
mail.example.ru
</div>
<div class="shield-mini">
✓
</div>
</div>
<div class="browser-body">
<div class="mail-sidebar">
<div class="mail-logo"></div>
<div class="side-line active"></div>
<div class="side-line"></div>
<div class="side-line short"></div>
<div class="side-line"></div>
<div class="side-line short"></div>
</div>
<div class="mail-content">
<div class="mail-toolbar">
<div class="toolbar-line"></div>
<div class="toolbar-icons">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="messages">
<div class="message-row">
<span class="avatar"></span>
<div class="message-copy">
<span></span>
<span></span>
</div>
</div>
<div class="message-row">
<span class="avatar"></span>
<div class="message-copy">
<span></span>
<span></span>
</div>
</div>
<div class="message-row">
<span class="avatar"></span>
<div class="message-copy">
<span></span>
<span></span>
</div>
</div>
<div class="message-row">
<span class="avatar"></span>
<div class="message-copy">
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<div class="ads-column">
<div class="ad-card ad-one">
<div class="ad-label">
РЕКЛАМА
</div>
<div class="ad-picture"></div>
<div class="ad-lines">
<span></span>
<span></span>
</div>
<div class="blocked-cross"></div>
</div>
<div class="ad-card ad-two">
<div class="ad-label">
РЕКЛАМА
</div>
<div class="ad-lines">
<span></span>
<span></span>
<span></span>
</div>
<div class="blocked-cross"></div>
</div>
</div>
<div class="clean-column">
<div class="clean-message">
<div class="clean-icon">
✓
</div>
<div>
реклама<br>
скрыта
</div>
</div>
</div>
</div>
<div class="adblock-panel">
<div class="panel-icon">
V
</div>
<div class="panel-copy">
<div class="panel-title">
VVRSHN AdBlock
</div>
<div class="panel-status">
Защита включена
</div>
</div>
<div class="toggle active">
<div class="toggle-point"></div>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.vvrshn-adblock {
background:
linear-gradient(
145deg,
#e9e9e7,
#f4f4f1
);
}
/* =========================================================
BROWSER
========================================================= */
.vvrshn-adblock .adblock-browser {
position: absolute;
inset: 7%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background: #fff;
box-shadow:
0
32px
90px
rgba(0,0,0,.14);
transform:
perspective(1100px)
rotateX(.8deg)
rotateY(-1.4deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.vvrshn-adblock:hover
.adblock-browser {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
42px
110px
rgba(0,0,0,.18);
}
/* =========================================================
TOP
========================================================= */
.vvrshn-adblock .browser-top {
position: relative;
height: 12%;
min-height: 25px;
padding:
0
3%;
display: flex;
align-items: center;
border-bottom:
1px solid
rgba(0,0,0,.06);
background:
#f3f3f1;
}
.vvrshn-adblock .browser-dots {
display: flex;
gap:
clamp(
3px,
.35vw,
5px
);
}
.vvrshn-adblock .browser-dots span {
width:
clamp(
4px,
.48vw,
6px
);
aspect-ratio: 1;
border-radius: 50%;
background:
rgba(0,0,0,.15);
}
.vvrshn-adblock .browser-address {
position: absolute;
left: 50%;
width: 43%;
min-height:
clamp(
14px,
1.8vw,
24px
);
transform:
translateX(-50%);
display: flex;
align-items: center;
justify-content: center;
border:
1px solid
rgba(0,0,0,.05);
border-radius: 999px;
background:
rgba(255,255,255,.72);
color:
rgba(0,0,0,.28);
font-size:
clamp(
3px,
.42vw,
6px
);
}
.vvrshn-adblock .shield-mini {
margin-left: auto;
width:
clamp(
15px,
1.8vw,
25px
);
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 7px;
background: #111;
color: #fff;
font-size:
clamp(
5px,
.55vw,
8px
);
font-weight: 700;
}
/* =========================================================
BODY
========================================================= */
.vvrshn-adblock .browser-body {
position: absolute;
left: 0;
right: 0;
top: 12%;
bottom: 0;
display: grid;
grid-template-columns:
18%
54%
28%;
}
/* =========================================================
SIDEBAR
========================================================= */
.vvrshn-adblock .mail-sidebar {
padding:
12%
14%;
border-right:
1px solid
rgba(0,0,0,.055);
background:
#f7f7f5;
}
.vvrshn-adblock .mail-logo {
width: 36%;
aspect-ratio: 1;
margin-bottom: 24%;
border-radius:
35%;
background: #111;
}
.vvrshn-adblock .side-line {
width: 82%;
height:
clamp(
3px,
.38vw,
5px
);
margin-bottom: 14%;
border-radius: 999px;
background:
rgba(0,0,0,.08);
}
.vvrshn-adblock .side-line.short {
width: 58%;
}
.vvrshn-adblock .side-line.active {
width: 92%;
background:
rgba(0,0,0,.32);
}
/* =========================================================
MAIL CONTENT
========================================================= */
.vvrshn-adblock .mail-content {
background: #fff;
}
.vvrshn-adblock .mail-toolbar {
height: 16%;
padding:
0
6%;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom:
1px solid
rgba(0,0,0,.055);
}
.vvrshn-adblock .toolbar-line {
width: 27%;
height: 5px;
border-radius: 999px;
background:
rgba(0,0,0,.08);
}
.vvrshn-adblock .toolbar-icons {
display: flex;
gap:
clamp(
5px,
.65vw,
9px
);
}
.vvrshn-adblock .toolbar-icons span {
width:
clamp(
9px,
1.1vw,
15px
);
aspect-ratio: 1;
border:
1px solid
rgba(0,0,0,.08);
border-radius: 50%;
}
/* =========================================================
MESSAGES
========================================================= */
.vvrshn-adblock .messages {
padding:
3%
5%;
}
.vvrshn-adblock .message-row {
height:
clamp(
30px,
4vw,
54px
);
display: flex;
align-items: center;
gap: 5%;
border-bottom:
1px solid
rgba(0,0,0,.045);
}
.vvrshn-adblock .avatar {
width:
clamp(
14px,
1.8vw,
24px
);
aspect-ratio: 1;
flex: 0 0 auto;
border-radius: 50%;
background:
#ededeb;
}
.vvrshn-adblock .message-copy {
width: 70%;
display: flex;
flex-direction: column;
gap:
clamp(
3px,
.35vw,
5px
);
}
.vvrshn-adblock .message-copy span {
width: 100%;
height: 4px;
border-radius: 999px;
background:
rgba(0,0,0,.09);
}
.vvrshn-adblock .message-copy span:last-child {
width: 63%;
opacity: .6;
}
/* =========================================================
ADS
========================================================= */
.vvrshn-adblock .ads-column {
position: relative;
padding:
8%;
overflow: hidden;
border-left:
1px solid
rgba(0,0,0,.055);
background:
#f7f7f5;
transition:
opacity
.6s
ease,
transform
.6s
cubic-bezier(.2,.8,.2,1),
filter
.6s
ease;
}
.vvrshn-adblock:hover
.ads-column {
opacity: 0;
filter:
blur(8px);
transform:
scale(.92)
translateX(20%);
}
.vvrshn-adblock .ad-card {
position: relative;
margin-bottom: 9%;
padding:
9%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
8px,
1vw,
13px
);
background: #fff;
}
.vvrshn-adblock .ad-one {
height: 52%;
}
.vvrshn-adblock .ad-two {
height: 31%;
}
.vvrshn-adblock .ad-label {
color:
rgba(0,0,0,.28);
font-size:
clamp(
3px,
.35vw,
5px
);
letter-spacing: .13em;
}
.vvrshn-adblock .ad-picture {
height: 43%;
margin-top: 9%;
border-radius:
6px;
background:
linear-gradient(
135deg,
#e2c19f,
#ba8d68
);
}
.vvrshn-adblock .ad-lines {
margin-top: 10%;
display: flex;
flex-direction: column;
gap: 5px;
}
.vvrshn-adblock .ad-lines span {
width: 100%;
height: 4px;
border-radius: 999px;
background:
rgba(0,0,0,.08);
}
.vvrshn-adblock .ad-lines span:nth-child(2) {
width: 66%;
}
.vvrshn-adblock .ad-lines span:nth-child(3) {
width: 43%;
}
/* =========================================================
BLOCK CROSS
========================================================= */
.vvrshn-adblock .blocked-cross {
position: absolute;
z-index: 10;
left: 50%;
top: 50%;
width:
clamp(
29px,
4vw,
53px
);
aspect-ratio: 1;
transform:
translate(
-50%,
-50%
);
border-radius: 50%;
background:
rgba(15,15,17,.90);
box-shadow:
0
9px
25px
rgba(0,0,0,.20);
}
.vvrshn-adblock .blocked-cross::before,
.vvrshn-adblock .blocked-cross::after {
content: "";
position: absolute;
left: 24%;
right: 24%;
top: 50%;
height: 2px;
border-radius: 999px;
background: #fff;
}
.vvrshn-adblock .blocked-cross::before {
transform:
rotate(45deg);
}
.vvrshn-adblock .blocked-cross::after {
transform:
rotate(-45deg);
}
/* =========================================================
CLEAN STATE
========================================================= */
.vvrshn-adblock .clean-column {
position: absolute;
z-index: 15;
right: 0;
top: 0;
bottom: 0;
width: 28%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform:
translateX(25%);
background:
#f7f7f5;
transition:
opacity
.65s
ease
.08s,
transform
.65s
cubic-bezier(.2,.8,.2,1)
.08s;
}
.vvrshn-adblock:hover
.clean-column {
opacity: 1;
transform:
translateX(0);
}
.vvrshn-adblock .clean-message {
display: flex;
flex-direction: column;
align-items: center;
gap:
clamp(
7px,
.9vw,
12px
);
color:
rgba(0,0,0,.38);
font-size:
clamp(
5px,
.58vw,
8px
);
line-height: 1.3;
text-align: center;
}
.vvrshn-adblock .clean-icon {
width:
clamp(
30px,
4vw,
54px
);
aspect-ratio: 1;
display: grid;
place-items: center;
border-radius: 50%;
background: #111;
color: #fff;
font-size:
clamp(
9px,
1.2vw,
16px
);
box-shadow:
0
10px
30px
rgba(0,0,0,.14);
}
/* =========================================================
FLOATING EXTENSION PANEL
========================================================= */
.vvrshn-adblock .adblock-panel {
position: absolute;
z-index: 30;
right: 4%;
bottom: 6%;
width: 32%;
min-height:
clamp(
40px,
5.5vw,
73px
);
padding:
3%;
display: flex;
align-items: center;
gap: 7%;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
9px,
1.1vw,
15px
);
background:
rgba(255,255,255,.94);
box-shadow:
0
17px
45px
rgba(0,0,0,.14);
backdrop-filter:
blur(15px);
-webkit-backdrop-filter:
blur(15px);
transform:
translateY(8%)
scale(.98);
transition:
transform
.5s
cubic-bezier(.2,.8,.2,1);
}
.vvrshn-adblock:hover
.adblock-panel {
transform:
translateY(0)
scale(1);
}
.vvrshn-adblock .panel-icon {
width:
clamp(
24px,
3.2vw,
43px
);
aspect-ratio: 1;
flex: 0 0 auto;
display: grid;
place-items: center;
border-radius:
30%;
background: #111;
color: #fff;
font-size:
clamp(
7px,
.9vw,
12px
);
font-weight: 760;
}
.vvrshn-adblock .panel-copy {
min-width: 0;
flex: 1;
}
.vvrshn-adblock .panel-title {
overflow: hidden;
color: #111;
font-size:
clamp(
5px,
.62vw,
8.5px
);
font-weight: 650;
white-space: nowrap;
text-overflow: ellipsis;
}
.vvrshn-adblock .panel-status {
margin-top: 7%;
color:
rgba(0,0,0,.30);
font-size:
clamp(
3px,
.4vw,
5.5px
);
}
/* =========================================================
TOGGLE
========================================================= */
.vvrshn-adblock .toggle {
position: relative;
width:
clamp(
25px,
3vw,
41px
);
height:
clamp(
14px,
1.7vw,
23px
);
flex: 0 0 auto;
border-radius: 999px;
background:
rgba(0,0,0,.10);
}
.vvrshn-adblock .toggle.active {
background: #111;
}
.vvrshn-adblock .toggle-point {
position: absolute;
top: 50%;
right: 7%;
height: 76%;
aspect-ratio: 1;
transform:
translateY(-50%);
border-radius: 50%;
background: #fff;
box-shadow:
0
2px
7px
rgba(0,0,0,.16);
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: editors-catalog
Название: Каталог монтажёров
Категория: Сайт
Порядок списка: 5
Главная: нет
NEW: да
Статус: в разработке
Коротко: Каталог монтажёров с ценами, специализацией, примерами работ и контактами.
Класс визуала: editors-catalog
DESCRIPTION
Каталог монтажёров для видеографов и других специалистов, которым нужно быстро найти человека под конкретную задачу. В карточках собраны специализация, стоимость разных форматов монтажа, примеры работ и контакты. Без рейтингов и попыток определить, кто «лучше»: каталог просто помогает посмотреть варианты, сравнить условия и самостоятельно выбрать подходящего исполнителя.
ENDDESCRIPTION
VISUAL_HTML
<div class="editors-interface">
<div class="editors-header">
<div class="editors-brand">
монтажёры
</div>
<div class="editors-counter">
КАТАЛОГ
</div>
</div>
<div class="editors-grid">
<div class="editor-card editor-card-a">
<div class="editor-top">
<div class="editor-avatar">
М
</div>
<div class="editor-person">
<div class="editor-name">
muvistudio
</div>
<div class="editor-type">
студия монтажа
</div>
</div>
</div>
<div class="editor-speciality">
свадебные фильмы
</div>
<div class="editor-price">
<span>
фильм
</span>
<strong>
40 000 ₽
</strong>
</div>
<div class="editor-work">
<span class="work-play"></span>
<div class="work-lines">
<span></span>
<span></span>
</div>
</div>
</div>
<div class="editor-card editor-card-main">
<div class="editor-top">
<div class="editor-avatar dark">
A
</div>
<div class="editor-person">
<div class="editor-name">
монтажёр
</div>
<div class="editor-type">
авторский монтаж
</div>
</div>
<div class="available-dot"></div>
</div>
<div class="editor-tags">
<span>
фильмы
</span>
<span>
клипы
</span>
<span>
reels
</span>
</div>
<div class="editor-prices">
<div class="price-row">
<span>Фильм</span>
<strong>25 000 ₽</strong>
</div>
<div class="price-row">
<span>Клип</span>
<strong>8 000 ₽</strong>
</div>
<div class="price-row">
<span>Reels</span>
<strong>3 000 ₽</strong>
</div>
</div>
<div class="editor-contact">
посмотреть работы
<span>↗</span>
</div>
</div>
<div class="editor-card editor-card-b">
<div class="editor-top">
<div class="editor-avatar">
V
</div>
<div class="editor-person">
<div class="editor-name">
video editor
</div>
<div class="editor-type">
клипы / reels
</div>
</div>
</div>
<div class="editor-speciality">
динамичный монтаж
</div>
<div class="editor-price">
<span>
клип
</span>
<strong>
12 000 ₽
</strong>
</div>
<div class="editor-work second">
<span class="work-play"></span>
<div class="work-lines">
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<div class="editors-footer">
<div class="random-note">
без рейтинга · порядок случайный
</div>
<div class="catalogue-line"></div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.editors-catalog {
background:
linear-gradient(
145deg,
#ececea,
#d8d8d4
);
}
/* =========================================================
INTERFACE
========================================================= */
.editors-catalog .editors-interface {
position: absolute;
inset: 7%;
padding:
5%
5%
4%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background:
#f8f8f5;
box-shadow:
0
32px
90px
rgba(0,0,0,.14);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.3deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.editors-catalog:hover
.editors-interface {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
42px
110px
rgba(0,0,0,.18);
}
/* =========================================================
HEADER
========================================================= */
.editors-catalog .editors-header {
display: flex;
align-items: center;
justify-content:
space-between;
}
.editors-catalog .editors-brand {
color: #111;
font-size:
clamp(
10px,
1.4vw,
20px
);
font-weight: 750;
letter-spacing:
-.055em;
}
.editors-catalog .editors-counter {
color:
rgba(0,0,0,.27);
font-size:
clamp(
3px,
.4vw,
6px
);
font-weight: 700;
letter-spacing:
.14em;
}
/* =========================================================
GRID
========================================================= */
.editors-catalog .editors-grid {
position: absolute;
left: 5%;
right: 5%;
top: 20%;
bottom: 13%;
perspective:
900px;
transform-style:
preserve-3d;
}
/* =========================================================
CARDS
========================================================= */
.editors-catalog .editor-card {
position: absolute;
top: 50%;
width: 31%;
height: 81%;
padding: 5%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
10px,
1.3vw,
18px
);
background: #fff;
box-shadow:
0
18px
45px
rgba(0,0,0,.10);
transition:
transform
.65s
cubic-bezier(.2,.8,.2,1),
opacity
.5s
ease,
filter
.5s
ease;
}
.editors-catalog .editor-card-main {
z-index: 10;
left: 50%;
width: 34%;
height: 92%;
transform:
translate(
-50%,
-50%
);
}
.editors-catalog .editor-card-a {
z-index: 4;
left: 1%;
opacity: .62;
filter:
brightness(.92);
transform:
translateY(-50%)
rotateY(8deg)
scale(.92);
}
.editors-catalog .editor-card-b {
z-index: 4;
right: 1%;
opacity: .62;
filter:
brightness(.92);
transform:
translateY(-50%)
rotateY(-8deg)
scale(.92);
}
.editors-catalog:hover
.editor-card-main {
transform:
translate(
-50%,
-52%
)
scale(1.025);
}
.editors-catalog:hover
.editor-card-a {
transform:
translateY(-50%)
translateX(-3%)
rotateY(5deg)
scale(.93);
}
.editors-catalog:hover
.editor-card-b {
transform:
translateY(-50%)
translateX(3%)
rotateY(-5deg)
scale(.93);
}
/* =========================================================
PERSON
========================================================= */
.editors-catalog .editor-top {
position: relative;
display: flex;
align-items: center;
gap: 8%;
}
.editors-catalog .editor-avatar {
width:
clamp(
22px,
3vw,
40px
);
aspect-ratio: 1;
flex:
0
0
auto;
display: grid;
place-items: center;
border-radius: 50%;
background:
#e7e7e3;
color:
rgba(0,0,0,.47);
font-size:
clamp(
6px,
.8vw,
11px
);
font-weight: 680;
}
.editors-catalog .editor-avatar.dark {
background: #111;
color: #fff;
}
.editors-catalog .editor-person {
min-width: 0;
}
.editors-catalog .editor-name {
overflow: hidden;
color: #111;
font-size:
clamp(
5px,
.68vw,
9.5px
);
font-weight: 660;
white-space: nowrap;
text-overflow: ellipsis;
}
.editors-catalog .editor-type {
margin-top: 7%;
color:
rgba(0,0,0,.28);
font-size:
clamp(
3px,
.4vw,
6px
);
white-space: nowrap;
}
.editors-catalog .available-dot {
position: absolute;
right: 0;
top: 10%;
width:
clamp(
5px,
.55vw,
7px
);
aspect-ratio: 1;
border-radius: 50%;
background:
#55a86c;
box-shadow:
0
0
0
4px
rgba(85,168,108,.09);
}
/* =========================================================
SPECIALITY
========================================================= */
.editors-catalog .editor-speciality {
margin-top: 15%;
color:
rgba(0,0,0,.32);
font-size:
clamp(
4px,
.48vw,
7px
);
}
/* =========================================================
TAGS
========================================================= */
.editors-catalog .editor-tags {
margin-top: 14%;
display: flex;
flex-wrap: wrap;
gap: 5%;
}
.editors-catalog .editor-tags span {
padding:
4%
6%;
border:
1px solid
rgba(0,0,0,.07);
border-radius: 999px;
background:
#f5f5f2;
color:
rgba(0,0,0,.46);
font-size:
clamp(
3px,
.38vw,
5.5px
);
}
/* =========================================================
SIMPLE PRICE
========================================================= */
.editors-catalog .editor-price {
margin-top: 13%;
padding-top: 11%;
display: flex;
align-items: flex-end;
justify-content:
space-between;
border-top:
1px solid
rgba(0,0,0,.06);
}
.editors-catalog .editor-price span {
color:
rgba(0,0,0,.30);
font-size:
clamp(
3px,
.4vw,
6px
);
}
.editors-catalog .editor-price strong {
color: #111;
font-size:
clamp(
5px,
.68vw,
9.5px
);
font-weight: 650;
white-space: nowrap;
}
/* =========================================================
PRICE LIST
========================================================= */
.editors-catalog .editor-prices {
margin-top: 13%;
}
.editors-catalog .price-row {
min-height:
clamp(
25px,
3.3vw,
44px
);
display: flex;
align-items: center;
justify-content:
space-between;
border-bottom:
1px solid
rgba(0,0,0,.055);
}
.editors-catalog .price-row span {
color:
rgba(0,0,0,.38);
font-size:
clamp(
4px,
.48vw,
7px
);
}
.editors-catalog .price-row strong {
color: #111;
font-size:
clamp(
4px,
.52vw,
7.5px
);
font-weight: 650;
}
/* =========================================================
EXAMPLE WORK
========================================================= */
.editors-catalog .editor-work {
position: absolute;
left: 5%;
right: 5%;
bottom: 6%;
height: 26%;
overflow: hidden;
border-radius:
clamp(
6px,
.8vw,
11px
);
background:
linear-gradient(
145deg,
#82776c,
#c4b5a6
);
}
.editors-catalog .editor-work.second {
background:
linear-gradient(
145deg,
#656a72,
#aab0b8
);
}
.editors-catalog .work-play {
position: absolute;
left: 12%;
top: 50%;
width:
clamp(
18px,
2.3vw,
31px
);
aspect-ratio: 1;
transform:
translateY(-50%);
border-radius: 50%;
background:
rgba(255,255,255,.88);
}
.editors-catalog .work-play::after {
content: "";
position: absolute;
left: 53%;
top: 50%;
transform:
translate(
-50%,
-50%
);
width: 0;
height: 0;
border-top:
3px solid
transparent;
border-bottom:
3px solid
transparent;
border-left:
5px solid
#111;
}
.editors-catalog .work-lines {
position: absolute;
left: 37%;
right: 10%;
top: 50%;
transform:
translateY(-50%);
display: flex;
flex-direction: column;
gap:
clamp(
3px,
.35vw,
5px
);
}
.editors-catalog .work-lines span {
height:
clamp(
2px,
.27vw,
4px
);
border-radius: 999px;
background:
rgba(255,255,255,.55);
}
.editors-catalog .work-lines span:last-child {
width: 58%;
opacity: .6;
}
/* =========================================================
CONTACT
========================================================= */
.editors-catalog .editor-contact {
min-height:
clamp(
25px,
3.2vw,
43px
);
margin-top: auto;
position: absolute;
left: 5%;
right: 5%;
bottom: 6%;
padding:
0
7%;
display: flex;
align-items: center;
justify-content:
space-between;
border-radius: 999px;
background: #111;
color: #fff;
font-size:
clamp(
4px,
.48vw,
7px
);
transition:
transform
.35s
cubic-bezier(.2,.8,.2,1),
box-shadow
.35s
ease;
}
.editors-catalog:hover
.editor-contact {
transform:
translateY(-2px);
box-shadow:
0
8px
20px
rgba(0,0,0,.14);
}
/* =========================================================
FOOTER
========================================================= */
.editors-catalog .editors-footer {
position: absolute;
left: 5%;
right: 5%;
bottom: 4%;
display: flex;
align-items: center;
gap: 5%;
}
.editors-catalog .random-note {
flex:
0
0
auto;
color:
rgba(0,0,0,.24);
font-size:
clamp(
3px,
.38vw,
5.5px
);
}
.editors-catalog .catalogue-line {
flex: 1;
height: 1px;
background:
rgba(0,0,0,.07);
}
/* =========================================================
LIGHT SWEEP
========================================================= */
.editors-catalog
.editors-interface::after {
content: "";
position: absolute;
z-index: 30;
top: -70%;
left: -55%;
width: 23%;
height: 240%;
transform:
rotate(18deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.24),
transparent
);
opacity: .26;
pointer-events: none;
transition:
left
1.15s
cubic-bezier(.2,.8,.2,1);
}
.editors-catalog:hover
.editors-interface::after {
left: 130%;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: gennady-mishakov
Название: Геннадий Мишаков
Категория: Сайт
Порядок списка: 7
Главная: нет
NEW: да
Статус: готов
Коротко: Интерактивный сайт-презентация ведущего, где каждый экран превращён в небольшую сцену.
Класс визуала: gennady-mishakov
DESCRIPTION
Интерактивный сайт-презентация ведущего Геннадия Мишакова. Вместо обычных фотографий и длинного текста сайт построен как последовательность небольших сцен: церемония, банкет, интерактивы, букет, микрофон и другие моменты мероприятия. На экранах можно нажимать на персонажей и предметы, запускать анимации и постепенно знакомиться с Геной через его работу.
ENDDESCRIPTION
VISUAL_HTML
<div class="gennady-stage">
<div class="stage-top">
<div class="gennady-name">
Геннадий<br>
Мишаков
</div>
<div class="slide-counter">
04 / 10
</div>
</div>
<div class="ceremony-scene">
<div class="scene-caption">
ЦЕРЕМОНИЯ
</div>
<div class="confetti confetti-one"></div>
<div class="confetti confetti-two"></div>
<div class="confetti confetti-three"></div>
<div class="gennady-character">
<div class="gennady-head">
<div class="gennady-hair"></div>
</div>
<div class="gennady-body">
<div class="red-necklace">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="gennady-mic">
<span class="mic-head"></span>
<span class="mic-body"></span>
</div>
</div>
<div class="couple">
<div class="partner groom">
<span class="partner-head"></span>
<span class="partner-body"></span>
</div>
<div class="hearts">
<span>♥</span>
<span>♥</span>
<span>♥</span>
</div>
<div class="partner bride">
<span class="partner-head"></span>
<span class="partner-body"></span>
</div>
</div>
<div class="speech-bubble">
объявляю вас<br>
мужем и женой
</div>
</div>
<div class="interactive-row">
<div class="interaction active">
<div class="interaction-icon">
✦
</div>
<div>
церемония
</div>
</div>
<div class="interaction">
<div class="interaction-icon">
♫
</div>
<div>
банкет
</div>
</div>
<div class="interaction">
<div class="interaction-icon">
♡
</div>
<div>
букет
</div>
</div>
<div class="interaction">
<div class="interaction-icon">
●
</div>
<div>
микрофон
</div>
</div>
</div>
<div class="stage-hint">
нажми на Гену
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.gennady-mishakov {
background:
linear-gradient(
145deg,
#f0ede8,
#d8d2ca
);
}
/* =========================================================
STAGE
========================================================= */
.gennady-mishakov .gennady-stage {
position: absolute;
inset: 6%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background:
#f7f4ef;
box-shadow:
0
32px
90px
rgba(0,0,0,.15);
transform:
perspective(1100px)
rotateX(.6deg)
rotateY(-1.2deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov:hover
.gennady-stage {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
42px
110px
rgba(0,0,0,.19);
}
/* =========================================================
TOP
========================================================= */
.gennady-mishakov .stage-top {
position: absolute;
z-index: 30;
left: 5%;
right: 5%;
top: 5%;
display: flex;
align-items: flex-start;
justify-content:
space-between;
}
.gennady-mishakov .gennady-name {
color: #111;
font-size:
clamp(
10px,
1.35vw,
19px
);
line-height: .9;
font-weight: 760;
letter-spacing:
-.055em;
}
.gennady-mishakov .slide-counter {
color:
rgba(0,0,0,.28);
font-size:
clamp(
3px,
.42vw,
6px
);
font-weight: 650;
letter-spacing:
.10em;
}
/* =========================================================
SCENE
========================================================= */
.gennady-mishakov .ceremony-scene {
position: absolute;
left: 5%;
right: 5%;
top: 18%;
bottom: 20%;
overflow: hidden;
border-radius:
clamp(
10px,
1.4vw,
19px
);
background:
linear-gradient(
180deg,
#dad6d0 0%,
#ebe7e1 63%,
#c7b7a7 64%,
#b9a898 100%
);
box-shadow:
inset
0
0
0
1px
rgba(0,0,0,.045);
}
.gennady-mishakov .ceremony-scene::before {
content: "";
position: absolute;
left: 8%;
right: 8%;
bottom: 35%;
height: 1px;
background:
rgba(0,0,0,.06);
}
.gennady-mishakov .ceremony-scene::after {
content: "";
position: absolute;
left: 50%;
top: 0;
width: 35%;
height: 100%;
transform:
translateX(-50%);
background:
radial-gradient(
ellipse at center,
rgba(255,255,255,.65),
transparent 67%
);
}
/* =========================================================
CAPTION
========================================================= */
.gennady-mishakov .scene-caption {
position: absolute;
z-index: 10;
left: 3.5%;
top: 5%;
color:
rgba(0,0,0,.26);
font-size:
clamp(
3px,
.40vw,
6px
);
font-weight: 700;
letter-spacing:
.15em;
}
/* =========================================================
GENNADY
========================================================= */
.gennady-mishakov .gennady-character {
position: absolute;
z-index: 12;
left: 28%;
bottom: 8%;
width: 17%;
height: 69%;
transform-origin:
50%
100%;
transition:
transform
.55s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov:hover
.gennady-character {
transform:
translateX(-9%)
rotate(-2deg);
}
/* =========================================================
HEAD
========================================================= */
.gennady-mishakov .gennady-head {
position: absolute;
z-index: 5;
left: 50%;
top: 0;
width: 44%;
aspect-ratio: .86;
transform:
translateX(-50%);
border-radius:
47%
47%
44%
44%;
background:
#d7b299;
}
.gennady-mishakov .gennady-hair {
position: absolute;
left: -28%;
right: -27%;
top: -24%;
height: 88%;
border-radius:
55%
55%
42%
42%;
background:
linear-gradient(
160deg,
#c8c2ba,
#8d8984
);
z-index: -1;
transform:
rotate(-3deg);
}
/* =========================================================
BODY
========================================================= */
.gennady-mishakov .gennady-body {
position: absolute;
left: 50%;
bottom: 0;
width: 78%;
height: 70%;
transform:
translateX(-50%);
border-radius:
40%
40%
12%
12%;
background:
linear-gradient(
180deg,
#f7f4ee,
#e4dfd8
);
box-shadow:
inset
0
0
0
1px
rgba(0,0,0,.06);
}
/* =========================================================
NECKLACE
========================================================= */
.gennady-mishakov .red-necklace {
position: absolute;
left: 50%;
top: 9%;
width: 52%;
height: 22%;
transform:
translateX(-50%);
display: flex;
justify-content:
space-between;
align-items: flex-end;
}
.gennady-mishakov .red-necklace span {
width:
clamp(
3px,
.35vw,
5px
);
aspect-ratio: 1;
border-radius: 50%;
background:
#a9342d;
}
.gennady-mishakov .red-necklace span:nth-child(1),
.gennady-mishakov .red-necklace span:nth-child(5) {
transform:
translateY(-45%);
}
.gennady-mishakov .red-necklace span:nth-child(2),
.gennady-mishakov .red-necklace span:nth-child(4) {
transform:
translateY(-10%);
}
/* =========================================================
MICROPHONE
========================================================= */
.gennady-mishakov .gennady-mic {
position: absolute;
z-index: 20;
right: -19%;
top: 43%;
width: 50%;
height: 18%;
transform:
rotate(-12deg);
transition:
transform
.55s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov:hover
.gennady-mic {
transform:
rotate(-3deg)
translateX(16%);
}
.gennady-mishakov .mic-body {
position: absolute;
left: 4%;
top: 47%;
width: 82%;
height:
clamp(
3px,
.35vw,
5px
);
border-radius: 999px;
background:
#222;
}
.gennady-mishakov .mic-head {
position: absolute;
right: 0;
top: 31%;
width: 27%;
aspect-ratio: 1.15;
border-radius: 50%;
background:
#111;
}
/* =========================================================
COUPLE
========================================================= */
.gennady-mishakov .couple {
position: absolute;
z-index: 14;
right: 20%;
bottom: 9%;
width: 30%;
height: 61%;
display: flex;
justify-content:
center;
align-items:
flex-end;
transition:
gap
.65s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov:hover
.couple {
gap: 0;
}
.gennady-mishakov .partner {
position: relative;
width: 45%;
height: 100%;
transition:
transform
.65s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov .groom {
transform:
translateX(-8%);
}
.gennady-mishakov .bride {
transform:
translateX(8%);
}
.gennady-mishakov:hover
.groom {
transform:
translateX(13%)
rotate(2deg);
}
.gennady-mishakov:hover
.bride {
transform:
translateX(-13%)
rotate(-2deg);
}
.gennady-mishakov .partner-head {
position: absolute;
left: 50%;
top: 7%;
width: 37%;
aspect-ratio: 1;
transform:
translateX(-50%);
border-radius: 50%;
background:
#cfab92;
}
.gennady-mishakov .partner-body {
position: absolute;
left: 50%;
bottom: 0;
width: 72%;
height: 68%;
transform:
translateX(-50%);
border-radius:
42%
42%
8%
8%;
}
.gennady-mishakov .groom
.partner-body {
background:
#2b2a2b;
}
.gennady-mishakov .bride
.partner-body {
background:
#f4f0e8;
box-shadow:
inset
0
0
0
1px
rgba(0,0,0,.05);
}
/* =========================================================
HEARTS
========================================================= */
.gennady-mishakov .hearts {
position: absolute;
z-index: 30;
left: 50%;
top: 10%;
transform:
translateX(-50%);
pointer-events: none;
}
.gennady-mishakov .hearts span {
position: absolute;
color:
rgba(159,55,52,.0);
font-size:
clamp(
7px,
.9vw,
13px
);
transform:
translateY(12px)
scale(.4);
transition:
color .4s ease,
transform
.8s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov .hearts span:nth-child(1) {
left: -18px;
transition-delay:
.05s;
}
.gennady-mishakov .hearts span:nth-child(2) {
left: 0;
top: -8px;
transition-delay:
.13s;
}
.gennady-mishakov .hearts span:nth-child(3) {
left: 17px;
top: 5px;
transition-delay:
.22s;
}
.gennady-mishakov:hover
.hearts span {
color:
rgba(159,55,52,.74);
transform:
translateY(-10px)
scale(1);
}
/* =========================================================
SPEECH
========================================================= */
.gennady-mishakov .speech-bubble {
position: absolute;
z-index: 25;
left: 10%;
top: 26%;
padding:
3%
4%;
border-radius:
clamp(
7px,
.9vw,
12px
);
background:
rgba(255,255,255,.88);
color:
rgba(0,0,0,.60);
font-size:
clamp(
4px,
.5vw,
7px
);
line-height: 1.35;
box-shadow:
0
10px
28px
rgba(0,0,0,.08);
opacity: .25;
transform:
translateY(7px)
scale(.96);
transition:
opacity .5s ease,
transform
.5s
cubic-bezier(.2,.8,.2,1);
}
.gennady-mishakov:hover
.speech-bubble {
opacity: 1;
transform:
translateY(0)
scale(1);
}
/* =========================================================
CONFETTI
========================================================= */
.gennady-mishakov .confetti {
position: absolute;
z-index: 40;
inset: 0;
opacity: 0;
pointer-events: none;
background-image:
radial-gradient(
circle,
rgba(153,70,62,.72) 0 2px,
transparent 2.5px
),
radial-gradient(
circle,
rgba(180,145,72,.72) 0 2px,
transparent 2.5px
),
radial-gradient(
circle,
rgba(80,104,114,.66) 0 2px,
transparent 2.5px
);
background-size:
43px 47px,
61px 53px,
71px 65px;
transition:
opacity
.25s
ease;
}
.gennady-mishakov .confetti-one {
background-position:
4px 1px,
17px 11px,
29px 21px;
}
.gennady-mishakov .confetti-two {
background-position:
17px 14px,
6px 24px,
38px 5px;
}
.gennady-mishakov .confetti-three {
background-position:
28px 31px,
37px 9px,
12px 36px;
}
.gennady-mishakov:hover
.confetti-one {
animation:
confettiFlash
.55s
ease
.30s
1;
}
.gennady-mishakov:hover
.confetti-two {
animation:
confettiFlash
.55s
ease
.80s
1;
}
.gennady-mishakov:hover
.confetti-three {
animation:
confettiFlash
.55s
ease
1.30s
1;
}
@keyframes confettiFlash {
0% {
opacity: 0;
transform:
translateY(-8%);
}
30% {
opacity: .9;
}
100% {
opacity: 0;
transform:
translateY(12%);
}
}
/* =========================================================
INTERACTIONS
========================================================= */
.gennady-mishakov .interactive-row {
position: absolute;
left: 5%;
right: 5%;
bottom: 7%;
display: grid;
grid-template-columns:
repeat(4,1fr);
gap: 1.5%;
}
.gennady-mishakov .interaction {
min-height:
clamp(
30px,
4.2vw,
56px
);
padding:
0
8%;
display: flex;
align-items: center;
gap: 10%;
border:
1px solid
rgba(0,0,0,.06);
border-radius:
clamp(
7px,
.9vw,
12px
);
background:
rgba(255,255,255,.50);
color:
rgba(0,0,0,.35);
font-size:
clamp(
3px,
.42vw,
6px
);
transition:
background .3s ease,
transform
.3s
cubic-bezier(.2,.8,.2,1),
color .3s ease;
}
.gennady-mishakov .interaction.active {
background: #111;
color: #fff;
}
.gennady-mishakov:hover
.interaction.active {
transform:
translateY(-2px);
}
.gennady-mishakov .interaction-icon {
width:
clamp(
15px,
1.8vw,
24px
);
aspect-ratio: 1;
display: grid;
place-items: center;
flex:
0
0
auto;
border-radius: 50%;
background:
rgba(0,0,0,.055);
font-size:
clamp(
5px,
.58vw,
8px
);
}
.gennady-mishakov .interaction.active
.interaction-icon {
background:
rgba(255,255,255,.12);
}
/* =========================================================
HINT
========================================================= */
.gennady-mishakov .stage-hint {
position: absolute;
z-index: 35;
left: 7%;
bottom: 22%;
color:
rgba(0,0,0,.24);
font-size:
clamp(
3px,
.37vw,
5px
);
transition:
opacity
.35s
ease;
}
.gennady-mishakov:hover
.stage-hint {
opacity: 0;
}
END_VISUAL_CSS
ENDPRODUCT
PRODUCT
id: course-lesson-template
Название: Шаблон уроков курса
Категория: Сервис
Порядок списка: 5
Главная: нет
NEW: да
Статус: в разработке
Коротко: Шаблон для оформления уроков курса на сайте из обычного конспекта или транскрибации.
Класс визуала: course-lessons
DESCRIPTION
Шаблон для учебных материалов на сайте. Я загружаю конспект или транскрибацию урока, а система превращает её в аккуратно оформленную страницу с заголовками, основными тезисами, примерами и переходом к следующему уроку. Идея в том, чтобы не верстать каждый урок вручную, а собирать весь курс в единой визуальной системе.
ENDDESCRIPTION
VISUAL_HTML
<div class="course-interface">
<div class="course-sidebar">
<div class="course-logo">
снимать<br>
красиво
</div>
<div class="course-progress">
<div class="progress-label">
КУРС
</div>
<div class="progress-count">
03 / 12
</div>
</div>
<div class="lesson-menu">
<div class="lesson-menu-item done">
<span class="lesson-number">
01
</span>
<span class="lesson-name">
введение
</span>
</div>
<div class="lesson-menu-item done">
<span class="lesson-number">
02
</span>
<span class="lesson-name">
крупности
</span>
</div>
<div class="lesson-menu-item active">
<span class="lesson-number">
03
</span>
<span class="lesson-name">
история
</span>
</div>
<div class="lesson-menu-item">
<span class="lesson-number">
04
</span>
<span class="lesson-name">
движение
</span>
</div>
</div>
</div>
<div class="lesson-page">
<div class="lesson-top">
<div class="lesson-kicker">
УРОК 03
</div>
<div class="lesson-time">
17:02
</div>
</div>
<div class="lesson-title">
Как видеть<br>
историю на съёмке
</div>
<div class="lesson-lead">
Большая история складывается из маленьких событий.
</div>
<div class="lesson-block">
<div class="block-number">
01
</div>
<div class="block-content">
<div class="block-title">
Где происходит событие?
</div>
<div class="block-lines">
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>
<div class="lesson-block">
<div class="block-number">
02
</div>
<div class="block-content">
<div class="block-title">
Кто участвует?
</div>
<div class="block-lines">
<span></span>
<span></span>
</div>
</div>
</div>
<div class="lesson-example">
<div class="example-label">
ПРИМЕР
</div>
<div class="example-title">
ЗАГС
</div>
<div class="example-items">
<span>
общий план
</span>
<span>
пара
</span>
<span>
гости
</span>
<span>
кольца
</span>
</div>
</div>
<div class="next-lesson">
<span>
следующий урок
</span>
<strong>
движение камеры
</strong>
<span class="next-arrow">
→
</span>
</div>
</div>
</div>
END_VISUAL_HTML
VISUAL_CSS
.course-lessons {
background:
linear-gradient(
145deg,
#ecece8,
#d7d7d1
);
}
/* =========================================================
INTERFACE
========================================================= */
.course-lessons .course-interface {
position: absolute;
inset: 7%;
display: grid;
grid-template-columns:
28%
72%;
overflow: hidden;
border:
1px solid
rgba(0,0,0,.07);
border-radius:
clamp(
16px,
2vw,
28px
);
background:
#fff;
box-shadow:
0
32px
90px
rgba(0,0,0,.14);
transform:
perspective(1100px)
rotateX(.7deg)
rotateY(-1.3deg);
transition:
transform
.6s
cubic-bezier(.2,.8,.2,1),
box-shadow
.6s
cubic-bezier(.2,.8,.2,1);
}
.course-lessons:hover
.course-interface {
transform:
perspective(1100px)
rotateX(0deg)
rotateY(0deg);
box-shadow:
0
42px
110px
rgba(0,0,0,.18);
}
/* =========================================================
SIDEBAR
========================================================= */
.course-lessons .course-sidebar {
position: relative;
padding:
12%
11%;
overflow: hidden;
border-right:
1px solid
rgba(0,0,0,.065);
background:
#111;
}
.course-lessons .course-logo {
color: #fff;
font-size:
clamp(
12px,
1.7vw,
24px
);
line-height: .88;
font-weight: 720;
letter-spacing:
-.06em;
}
/* =========================================================
PROGRESS
========================================================= */
.course-lessons .course-progress {
margin-top: 24%;
padding-top: 14%;
display: flex;
align-items: center;
justify-content:
space-between;
border-top:
1px solid
rgba(255,255,255,.10);
}
.course-lessons .progress-label {
color:
rgba(255,255,255,.35);
font-size:
clamp(
3px,
.4vw,
6px
);
letter-spacing:
.14em;
}
.course-lessons .progress-count {
color:
rgba(255,255,255,.65);
font-size:
clamp(
4px,
.48vw,
7px
);
font-variant-numeric:
tabular-nums;
}
/* =========================================================
MENU
========================================================= */
.course-lessons .lesson-menu {
margin-top: 21%;
}
.course-lessons .lesson-menu-item {
min-height:
clamp(
31px,
4vw,
54px
);
padding:
0
6%;
display: grid;
grid-template-columns:
25px
1fr;
align-items: center;
gap: 8%;
border-bottom:
1px solid
rgba(255,255,255,.07);
color:
rgba(255,255,255,.31);
transition:
color
.3s
ease,
transform
.35s
cubic-bezier(.2,.8,.2,1);
}
.course-lessons .lesson-menu-item.done {
color:
rgba(255,255,255,.44);
}
.course-lessons .lesson-menu-item.active {
color: #fff;
}
.course-lessons:hover
.lesson-menu-item.active {
transform:
translateX(4px);
}
.course-lessons .lesson-number {
font-size:
clamp(
3px,
.4vw,
6px
);
font-variant-numeric:
tabular-nums;
}
.course-lessons .lesson-name {
font-size:
clamp(
4px,
.52vw,
7.5px
);
}
/* =========================================================
LESSON
========================================================= */
.course-lessons .lesson-page {
position: relative;
padding:
7%
8%;
overflow: hidden;
background:
#fafaf7;
}
/* =========================================================
TOP
========================================================= */
.course-lessons .lesson-top {
display: flex;
align-items: center;
justify-content:
space-between;
}
.course-lessons .lesson-kicker {
color:
rgba(0,0,0,.28);
font-size:
clamp(
3px,
.4vw,
6px
);
font-weight: 700;
letter-spacing:
.14em;
}
.course-lessons .lesson-time {
color:
rgba(0,0,0,.26);
font-size:
clamp(
3px,
.4vw,
6px
);
font-variant-numeric:
tabular-nums;
}
/* =========================================================
TITLE
========================================================= */
.course-lessons .lesson-title {
margin-top: 8%;
max-width: 70%;
color: #111;
font-size:
clamp(
17px,
2.5vw,
35px
);
line-height: .91;
font-weight: 690;
letter-spacing:
-.062em;
}
.course-lessons .lesson-lead {
max-width: 57%;
margin-top: 5%;
color:
rgba(0,0,0,.42);
font-size:
clamp(
4px,
.55vw,
8px
);
line-height: 1.45;
}
/* =========================================================
LESSON BLOCKS
========================================================= */
.course-lessons .lesson-block {
width: 58%;
margin-top: 7%;
padding:
5%
0;
display: grid;
grid-template-columns:
34px
1fr;
gap: 5%;
border-top:
1px solid
rgba(0,0,0,.07);
}
.course-lessons .block-number {
color:
rgba(0,0,0,.20);
font-size:
clamp(
4px,
.48vw,
7px
);
}
.course-lessons .block-title {
color:
rgba(0,0,0,.70);
font-size:
clamp(
5px,
.64vw,
9px
);
font-weight: 640;
}
.course-lessons .block-lines {
margin-top: 7%;
display: flex;
flex-direction: column;
gap:
clamp(
3px,
.35vw,
5px
);
}
.course-lessons .block-lines span {
width: 100%;
height:
clamp(
2px,
.28vw,
4px
);
border-radius: 999px;
background:
rgba(0,0,0,.07);
}
.course-lessons .block-lines span:nth-child(2) {
width: 82%;
}
.course-lessons .block-lines span:nth-child(3) {
width: 61%;
}
/* =========================================================
EXAMPLE
========================================================= */
.course-lessons .lesson-example {
position: absolute;
right: 7%;
top: 33%;
width: 28%;
min-height: 44%;
padding:
6%;
overflow: hidden;
border-radius:
clamp(
9px,
1.2vw,
16px
);
background:
#111;
box-shadow:
0
18px
45px
rgba(0,0,0,.14);
transition:
transform
.5s
cubic-bezier(.2,.8,.2,1),
box-shadow
.5s
ease;
}
.course-lessons:hover
.lesson-example {
transform:
translateY(-4px)
rotate(-1deg);
box-shadow:
0
24px
55px
rgba(0,0,0,.18);
}
.course-lessons .example-label {
color:
rgba(255,255,255,.35);
font-size:
clamp(
3px,
.36vw,
5px
);
font-weight: 700;
letter-spacing:
.14em;
}
.course-lessons .example-title {
margin-top: 17%;
color: #fff;
font-size:
clamp(
13px,
1.9vw,
27px
);
line-height: 1;
font-weight: 720;
letter-spacing:
-.055em;
}
.course-lessons .example-items {
margin-top: 19%;
display: flex;
flex-direction: column;
gap:
clamp(
7px,
.9vw,
12px
);
}
.course-lessons .example-items span {
min-height:
clamp(
20px,
2.6vw,
35px
);
padding:
0
9%;
display: flex;
align-items: center;
border:
1px solid
rgba(255,255,255,.10);
border-radius: 999px;
color:
rgba(255,255,255,.58);
font-size:
clamp(
3px,
.4vw,
6px
);
transition:
color
.3s
ease,
background
.3s
ease,
transform
.3s
cubic-bezier(.2,.8,.2,1);
}
.course-lessons:hover
.example-items span:nth-child(2) {
color: #fff;
background:
rgba(255,255,255,.08);
transform:
translateX(3px);
}
/* =========================================================
NEXT
========================================================= */
.course-lessons .next-lesson {
position: absolute;
left: 8%;
right: 8%;
bottom: 7%;
min-height:
clamp(
31px,
4vw,
54px
);
padding:
0
3%;
display: grid;
grid-template-columns:
auto
1fr
auto;
gap: 5%;
align-items: center;
border-top:
1px solid
rgba(0,0,0,.07);
border-bottom:
1px solid
rgba(0,0,0,.07);
color:
rgba(0,0,0,.30);
font-size:
clamp(
3px,
.4vw,
6px
);
}
.course-lessons .next-lesson strong {
color: #111;
font-size:
clamp(
4px,
.54vw,
8px
);
font-weight: 630;
text-align: right;
}
.course-lessons .next-arrow {
color: #111;
font-size:
clamp(
8px,
1vw,
14px
);
transition:
transform
.35s
cubic-bezier(.2,.8,.2,1);
}
.course-lessons:hover
.next-arrow {
transform:
translateX(4px);
}
/* =========================================================
LIGHT
========================================================= */
.course-lessons
.course-interface::after {
content: "";
position: absolute;
z-index: 50;
top: -80%;
left: -60%;
width: 22%;
height: 260%;
transform:
rotate(18deg);
background:
linear-gradient(
90deg,
transparent,
rgba(255,255,255,.24),
transparent
);
opacity: .28;
pointer-events: none;
transition:
left
1.2s
cubic-bezier(.2,.8,.2,1);
}
.course-lessons:hover
.course-interface::after {
left: 135%;
}
END_VISUAL_CSS
ENDPRODUCT