/
egorscale
/
EgorScale
Обзор
Документация
Войти
/
egorscale
/
EgorScale
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
index.html
986 строк
32 KB
egorscale
Create: index.html
01 июл 2026, 16:55
Верифицирован
01 июл 2026, 16:55
4faf465
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>егор скейл - портфолио</title> <style> :root{ --bg-0:#0a0b0d; --bg-1:#0d1420; --surface:rgba(255,255,255,0.055); --surface-strong:rgba(255,255,255,0.09); --border-glass:rgba(255,255,255,0.14); --text-0:#f5f5f7; --text-1:rgba(245,245,247,0.62); --text-2:rgba(245,245,247,0.38); --accent:#0a84ff; --accent-soft:rgba(10,132,255,0.5); --accent-glow:rgba(10,132,255,0.22); --radius-lg:28px; --radius-md:18px; --radius-sm:12px; --ease:cubic-bezier(.16,1,.3,1); } *{margin:0;padding:0;box-sizing:border-box;} html{scroll-behavior:smooth;} /* macOS arrow cursor — SVG data URI of the classic black pointer */ html, body, a, button, .glass-btn, .nav a { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='22' viewBox='0 0 18 22'%3E%3Cpath d='M0 0 L0 18 L4.5 13.5 L7.5 20 L10 19 L7 12.5 L13 12.5 Z' fill='%23000' stroke='%23fff' stroke-width='1.2'/%3E%3C/svg%3E") 0 0, auto; } .work-card, .play-glass, [onclick] { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='22' viewBox='0 0 18 22'%3E%3Cpath d='M0 0 L0 18 L4.5 13.5 L7.5 20 L10 19 L7 12.5 L13 12.5 Z' fill='%23000' stroke='%23fff' stroke-width='1.2'/%3E%3C/svg%3E") 0 0, pointer; } body{ background:var(--bg-0); color:var(--text-0); font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text","Helvetica Neue",Arial,sans-serif; overflow-x:hidden; -webkit-font-smoothing:antialiased; } /* ---------- preloader ---------- */ #preloader{ position:fixed; inset:0; z-index:9999; background:#000; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:18px; transition:opacity 0.7s cubic-bezier(.4,0,.2,1), visibility 0.7s; } #preloader.hidden{ opacity:0; visibility:hidden; pointer-events:none; } #preloader .pre-name{ font-size:clamp(22px, 5vw, 42px); font-weight:600; letter-spacing:0.28em; text-transform:uppercase; color:#fff; opacity:0; transform:translateY(12px); animation:preName 0.7s 0.2s var(--ease) forwards; } @keyframes preName{ to{ opacity:1; transform:translateY(0); } } #preloader .pre-line{ width:0; height:2px; background:linear-gradient(90deg, #0a84ff, #5e5ce6); border-radius:2px; animation:preLine 0.65s 0.65s cubic-bezier(.16,1,.3,1) forwards; } @keyframes preLine{ to{ width:clamp(80px, 14vw, 160px); } } /* nav entrance — .visible added by JS after preloader */ .nav.visible{ opacity:1 !important; transform:translateY(0) translateX(-50%) !important; } @media (prefers-reduced-motion: reduce){ html{scroll-behavior:auto;} *{animation-duration:0.01ms !important; animation-iteration-count:1 !important; transition-duration:0.01ms !important;} } a{color:inherit;text-decoration:none;} ::selection{background:var(--accent-soft);color:#fff;} :focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:8px; } /* ---------- ambient backdrop ---------- */ .ambient{ position:fixed; inset:0; z-index:0; pointer-events:none; background: radial-gradient(ellipse 70% 50% at 50% -5%, var(--bg-1) 0%, transparent 60%), radial-gradient(ellipse 50% 40% at 85% 20%, rgba(10,132,255,0.07) 0%, transparent 60%), radial-gradient(ellipse 50% 40% at 10% 60%, rgba(10,132,255,0.05) 0%, transparent 60%); } .noise{ position:fixed; inset:0; z-index:1; pointer-events:none; opacity:0.025; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); } .stars{ position:fixed; inset:0; z-index:0; pointer-events:none; } .star{ position:absolute; width:2px;height:2px; border-radius:24px; background:rgba(255,255,255,0.55); animation:twinkle 4s ease-in-out infinite; } @keyframes twinkle{ 0%,100%{opacity:0.15;} 50%{opacity:0.7;} } main, header, footer{position:relative; z-index:2;} /* ---------- nav ---------- */ .nav{ position:fixed; top:20px; left:50%; transform:translateY(-20px) translateX(-50%); z-index:100; display:flex; align-items:center; gap:4px; padding:8px; border-radius:100px; background:var(--surface); border:1px solid var(--border-glass); backdrop-filter:blur(24px) saturate(160%); -webkit-backdrop-filter:blur(24px) saturate(160%); box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 20px 40px -20px rgba(0,0,0,0.6); opacity:0; transition:opacity 0.8s var(--ease), transform 0.8s var(--ease); } .nav a{ font-size:13px; font-weight:500; letter-spacing:0.01em; color:var(--text-1); padding:9px 18px; border-radius:100px; transition:color 0.3s var(--ease), background 0.3s var(--ease); } .nav a:hover{ color:var(--text-0); background:rgba(255,255,255,0.06); } .nav .dot{ width:6px;height:6px; border-radius:24px; background:var(--accent); box-shadow:0 0 10px var(--accent); margin:0 6px; } @media (max-width:680px){ .nav{display:none;} } /* ---------- glass surfaces ---------- */ .glass{ position:relative; background:var(--surface); border:1px solid var(--border-glass); border-radius:var(--radius-lg); backdrop-filter:blur(28px) saturate(160%); -webkit-backdrop-filter:blur(28px) saturate(160%); box-shadow: 0 1px 0 rgba(255,255,255,0.09) inset, 0 0 0 1px rgba(255,255,255,0.02) inset, 0 30px 60px -30px rgba(0,0,0,0.55); } .glass::before{ content:""; position:absolute; top:0; left:8%; right:8%; height:1px; background:linear-gradient(90deg, transparent, rgba(255,255,255,0.55), transparent); border-radius:100px; } .glass-btn{ display:inline-flex; align-items:center; justify-content:center; gap:8px; padding:15px 30px; font-size:15px; font-weight:500; border-radius:100px; background:var(--surface-strong); border:1px solid var(--border-glass); backdrop-filter:blur(20px) saturate(160%); -webkit-backdrop-filter:blur(20px) saturate(160%); box-shadow: 0 1px 0 rgba(255,255,255,0.16) inset, 0 12px 30px -14px rgba(0,0,0,0.5); cursor:pointer; transition:transform 0.45s var(--ease), box-shadow 0.45s var(--ease), background 0.3s var(--ease); } .glass-btn:hover{ transform:translateY(-2px); background:rgba(255,255,255,0.13); box-shadow: 0 1px 0 rgba(255,255,255,0.22) inset, 0 18px 40px -16px rgba(0,0,0,0.6); } .glass-btn:active{ transform:translateY(0px) scale(0.98); } .glass-btn.primary{ background:linear-gradient(180deg, rgba(10,132,255,0.95), rgba(10,90,255,0.95)); border-color:rgba(120,180,255,0.5); color:#fff; box-shadow: 0 1px 0 rgba(255,255,255,0.35) inset, 0 16px 40px -12px rgba(10,132,255,0.55); } .glass-btn.primary:hover{ box-shadow: 0 1px 0 rgba(255,255,255,0.4) inset, 0 20px 50px -14px rgba(10,132,255,0.7); } /* ---------- layout helpers ---------- */ .wrap{ max-width:1180px; margin:0 auto; padding:0 32px; } @media (max-width:680px){ .wrap{padding:0 20px;} } section{ padding:160px 0; } @media (max-width:680px){ section{ padding:100px 0; } } .eyebrow{ display:inline-flex; align-items:center; gap:8px; font-family:"SF Mono",ui-monospace,Menlo,monospace; font-size:11px; letter-spacing:0.18em; text-transform:uppercase; color:var(--accent); margin-bottom:20px; } .eyebrow::before{ content:""; width:6px;height:6px; border-radius:24px; background:var(--accent); box-shadow:0 0 12px var(--accent); } .reveal{ opacity:0; transform:translateY(28px); transition:opacity 0.9s var(--ease), transform 0.9s var(--ease); } .reveal.in{ opacity:1; transform:translateY(0); } /* ---------- hero ---------- */ .hero{ min-height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; padding:140px 32px 100px; position:relative; } .hero-badge{ width:104px; height:104px; border-radius:24px; display:flex; align-items:center; justify-content:center; margin-bottom:36px; background:linear-gradient(160deg, rgba(255,255,255,0.12), rgba(255,255,255,0.02)); border:1px solid var(--border-glass); backdrop-filter:blur(20px) saturate(160%); box-shadow: 0 1px 0 rgba(255,255,255,0.25) inset, 0 25px 50px -20px rgba(10,132,255,0.35); font-size:34px; font-weight:600; letter-spacing:-0.02em; animation:floatBadge 5s ease-in-out infinite; overflow:hidden; position:relative; } #hero-photo{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:inherit; display:block; } /* инициалы: показываем только если фото не загрузилось (onerror скрывает img, показывает span) */ .badge-initials{ display:none; align-items:center; justify-content:center; width:100%; height:100%; font-size:26px; font-weight:600; letter-spacing:-0.02em; color:var(--text-0); } /* когда src пустой — img отрабатывает onerror, показываем инициалы */ #hero-photo[src=""]{ display:none; } #hero-photo[src=""] ~ .badge-initials{ display:flex; } @keyframes floatBadge{ 0%,100%{ transform:translateY(0px); box-shadow:0 1px 0 rgba(255,255,255,0.25) inset, 0 25px 50px -20px rgba(10,132,255,0.35); } 50%{ transform:translateY(-8px); box-shadow:0 1px 0 rgba(255,255,255,0.25) inset, 0 35px 60px -16px rgba(10,132,255,0.5); } } .hero h1{ font-size:clamp(56px, 10vw, 118px); font-weight:650; letter-spacing:-0.035em; line-height:0.98; background:linear-gradient(180deg, #ffffff 0%, rgba(255,255,255,0.78) 100%); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; } .hero p.sub{ margin-top:26px; font-size:clamp(17px, 2.2vw, 22px); font-weight:400; color:var(--text-1); max-width:560px; line-height:1.5; } .hero-actions{ display:flex; gap:14px; margin-top:48px; flex-wrap:wrap; justify-content:center; } .scroll-cue{ margin-top:88px; display:flex; flex-direction:column; align-items:center; gap:10px; color:var(--text-2); font-size:11px; letter-spacing:0.12em; text-transform:uppercase; } @media (max-width:680px){ .scroll-cue{ margin-top:56px; } } .scroll-cue .line{ width:1px; height:34px; background:linear-gradient(180deg, var(--text-2), transparent); animation:scrollpulse 2.2s ease-in-out infinite; } @keyframes scrollpulse{ 0%{ transform:scaleY(0.4); opacity:0.3; } 50%{ transform:scaleY(1); opacity:1; } 100%{ transform:scaleY(0.4); opacity:0.3; } } /* ---------- section headers ---------- */ .section-head{ text-align:center; max-width:640px; margin:0 auto 64px; } .section-head h2{ font-size:clamp(34px, 5vw, 52px); font-weight:650; letter-spacing:-0.025em; line-height:1.08; } .section-head p{ margin-top:16px; font-size:17px; color:var(--text-1); line-height:1.55; } /* ---------- work grid ---------- */ .work-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:20px; } @media (max-width:900px){ .work-grid{ grid-template-columns:1fr; } } .work-card{ position:relative; aspect-ratio:3/4; border-radius:var(--radius-lg); overflow:hidden; cursor:pointer; transition:transform 0.6s var(--ease); } .work-card:hover{ transform:translateY(-6px); } .work-card .frame{ position:absolute; inset:0; background:linear-gradient(165deg, var(--card-a, #1c2733), var(--card-b, #0a0d12)); } .work-card .frame::after{ content:""; position:absolute; inset:0; background:radial-gradient(circle at 30% 20%, rgba(255,255,255,0.14), transparent 55%); } .work-card .scrim{ position:absolute; left:0; right:0; bottom:0; height:62%; background:linear-gradient(180deg, transparent, rgba(0,0,0,0.78) 100%); } .work-card .meta{ position:absolute; left:24px; right:24px; bottom:24px; display:flex; align-items:flex-end; justify-content:space-between; } .work-card video{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; background:transparent; } .work-card .meta h3{ font-size:21px; font-weight:600; letter-spacing:-0.01em; } .work-card .meta span{ display:block; margin-top:4px; font-size:13px; color:var(--text-1); } .play-glass{ width:46px; height:46px; border-radius:24px; display:flex; align-items:center; justify-content:center; background:rgba(255,255,255,0.12); border:1px solid rgba(255,255,255,0.22); backdrop-filter:blur(14px) saturate(160%); box-shadow:0 1px 0 rgba(255,255,255,0.3) inset; flex-shrink:0; cursor:pointer; transition:transform 0.4s var(--ease), background 0.4s var(--ease); } .work-card:hover .play-glass{ transform:scale(1.08); background:var(--accent); border-color:rgba(150,200,255,0.6); } .play-glass svg{ width:14px; height:14px; transition:opacity 0.2s; } .play-glass .icon-pause{ display:none; } .play-glass.is-playing .icon-play{ display:none; } .play-glass.is-playing .icon-pause{ display:block; } .work-card .tag{ position:absolute; top:24px; left:24px; font-family:"SF Mono",ui-monospace,Menlo,monospace; font-size:10px; letter-spacing:0.1em; text-transform:uppercase; padding:6px 12px; border-radius:100px; background:rgba(0,0,0,0.35); border:1px solid rgba(255,255,255,0.14); backdrop-filter:blur(10px); color:var(--text-1); } /* horizontal variant — sits full-width below the vertical grid */ .work-card.horizontal{ aspect-ratio:21/6; margin-top:20px; max-height:360px; } @media (max-width:900px){ .work-card.horizontal{ aspect-ratio:16/9; max-height:none; } } /* ---------- testimonials ---------- */ .testi-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:20px; } @media (max-width:900px){ .testi-grid{ grid-template-columns:1fr; } } .testi-card{ padding:32px; display:flex; flex-direction:column; gap:20px; transition:transform 0.5s var(--ease), border-color 0.5s var(--ease); } .testi-card:hover{ transform:translateY(-4px); border-color:rgba(10,132,255,0.35); } .testi-card .quote{ font-size:16px; line-height:1.6; color:var(--text-0); opacity:0.92; } .testi-person{ display:flex; align-items:center; gap:12px; margin-top:auto; } .avatar{ width:40px; height:40px; border-radius:50%; flex-shrink:0; display:flex; align-items:center; justify-content:center; font-size:14px; font-weight:600; background:linear-gradient(160deg, var(--av-a, #2a3a4a), var(--av-b, #0f1620)); border:1px solid rgba(255,255,255,0.14); } .testi-person .who{ display:flex; flex-direction:column; } .testi-person .who strong{ font-size:14px; font-weight:600; } .testi-person .who span{ font-size:12px; color:var(--text-2); margin-top:2px; } /* ---------- process / capabilities strip ---------- */ .strip{ display:grid; grid-template-columns:repeat(4, 1fr); gap:1px; border-radius:var(--radius-lg); overflow:hidden; background:var(--border-glass); } @media (max-width:900px){ .strip{ grid-template-columns:repeat(2,1fr); } } .strip-item{ background:rgba(8,9,11,0.92); padding:36px 28px; backdrop-filter:blur(20px); } .strip-item .num{ font-family:"SF Mono",ui-monospace,Menlo,monospace; font-size:12px; color:var(--accent); letter-spacing:0.05em; } .strip-item h4{ margin-top:14px; font-size:18px; font-weight:600; letter-spacing:-0.01em; } .strip-item p{ margin-top:8px; font-size:14px; line-height:1.5; color:var(--text-1); } /* ---------- contact ---------- */ .contact-panel{ position:relative; padding:90px 60px; text-align:center; overflow:hidden; } @media (max-width:680px){ .contact-panel{ padding:64px 28px; } } .contact-panel .glow{ position:absolute; width:480px; height:480px; border-radius:50%; background:radial-gradient(circle, var(--accent-glow), transparent 70%); top:50%; left:50%; transform:translate(-50%,-50%); pointer-events:none; } .contact-panel h2{ position:relative; font-size:clamp(32px, 5vw, 50px); font-weight:650; letter-spacing:-0.025em; line-height:1.1; } .contact-panel p{ position:relative; margin:18px auto 0; max-width:460px; color:var(--text-1); font-size:16px; line-height:1.55; } .contact-actions{ position:relative; display:flex; gap:14px; justify-content:center; margin-top:40px; flex-wrap:wrap; } </style> </head> <body> <!-- Preloader --> <div id="preloader"> <span class="pre-name">егор скейл</span> <div class="pre-line"></div> </div> <div class="ambient"></div> <div class="noise"></div> <div class="stars" id="stars"></div> <nav class="nav"> <a href="#work">Работы</a> <span class="dot"></span> <a href="#testimonials">Отзывы</a> <span class="dot"></span> <a href="#contact">Контакты</a> </nav> <main> <!-- HERO --> <section class="hero"> <!-- Плейсхолдер фото: замените src на путь к своей фотографии, например src="photo.jpg" --> <div class="hero-badge reveal in"> <img id="hero-photo" src="photos/photo.jpeg" alt="Egor Scale" onerror="this.style.display='none'; this.parentElement.querySelector('.badge-initials').style.display='flex'"> <span class="badge-initials">ЕС</span> </div> <h1 class="reveal in">Егор Скейл</h1> <p class="sub reveal in" style="transition-delay:0.1s"> Создаю ролики, которые хочется досмотреть. От базовой охватной динамики до сложной инфографики и полноценного моушн-дизайна </p> <div class="hero-actions reveal in" style="transition-delay:0.2s"> <a href="#work" class="glass-btn primary">Смотреть работы</a> <a href="#contact" class="glass-btn">Связаться</a> </div> <div class="scroll-cue"> <span>Скролл</span> <span class="line"></span> </div> </section> <!-- WORK --> <section id="work"> <div class="wrap"> <div class="section-head reveal"> <div class="eyebrow" style="justify-content:center">Избранные работы</div> <h2>Больше, чем просто нарезка кадров.</h2> <p>Подборка работ: от динамичных Reels для охватов до премиального моушн-дизайна.</p> </div> <div class="work-grid"> <div class="work-card reveal" onclick="toggleWorkVideo(this.querySelector('.play-glass'))" style="--card-a:#23303d; --card-b:#0a0d12;"> <div class="frame"></div> <!-- Вставьте свой видеофайл в src ниже (например src="videos/kak.mp4") --> <video playsinline muted loop preload="metadata"> <source src="videos/с интервью.mp4" type="video/mp4"> </video> <div class="scrim"></div> <span class="tag">Reels</span> <div class="meta"> <div> <h3>Монтаж – «Базовый»</h3> <span>0:36</span> </div> <div class="play-glass" onclick="toggleWorkVideo(this)"> <svg class="icon-play" viewBox="0 0 24 24" fill="none"><path d="M5 3v18l15-9L5 3z" fill="#fff"/></svg> <svg class="icon-pause" viewBox="0 0 24 24" fill="none"><rect x="5" y="3" width="5" height="18" fill="#fff"/><rect x="14" y="3" width="5" height="18" fill="#fff"/></svg> </div> </div> </div> <div class="work-card reveal" onclick="toggleWorkVideo(this.querySelector('.play-glass'))" style="transition-delay:0.08s; --card-a:#2a2630; --card-b:#0a0d12;"> <div class="frame"></div> <!-- Вставьте свой видеофайл в src ниже --> <video playsinline muted loop preload="metadata"> <source src="videos/2из5.mp4" type="video/mp4"> </video> <div class="scrim"></div> <span class="tag">Reels</span> <div class="meta"> <div> <h3>Монтаж – «Стандарт»</h3> <span>0:49</span> </div> <div class="play-glass" onclick="toggleWorkVideo(this)"> <svg class="icon-play" viewBox="0 0 24 24" fill="none"><path d="M5 3v18l15-9L5 3z" fill="#fff"/></svg> <svg class="icon-pause" viewBox="0 0 24 24" fill="none"><rect x="5" y="3" width="5" height="18" fill="#fff"/><rect x="14" y="3" width="5" height="18" fill="#fff"/></svg> </div> </div> </div> <div class="work-card reveal" onclick="toggleWorkVideo(this.querySelector('.play-glass'))" style="transition-delay:0.16s; --card-a:#1d2a22; --card-b:#0a0d12;"> <div class="frame"></div> <!-- Вставьте свой видеофайл в src ниже --> <video playsinline muted loop preload="metadata"> <source src="videos/Final.mp4" type="video/mp4"> </video> <div class="scrim"></div> <span class="tag">Motion</span> <div class="meta"> <div> <h3>Монтаж – «Премиум»</h3> <span>0:14</span> </div> <div class="play-glass" onclick="toggleWorkVideo(this)"> <svg class="icon-play" viewBox="0 0 24 24" fill="none"><path d="M5 3v18l15-9L5 3z" fill="#fff"/></svg> <svg class="icon-pause" viewBox="0 0 24 24" fill="none"><rect x="5" y="3" width="5" height="18" fill="#fff"/><rect x="14" y="3" width="5" height="18" fill="#fff"/></svg> </div> </div> </div> </div> <!-- Горизонтальная работа, во всю ширину, под основной сеткой --> <div class="work-card horizontal reveal" onclick="toggleWorkVideo(this.querySelector('.play-glass'))" style="--card-a:#2a2440; --card-b:#0a0d12;"> <div class="frame"></div> <!-- Вставьте свой видеофайл в src ниже --> <video playsinline muted loop preload="metadata"> <source src="videos/MotionDesign.mp4" type="video/mp4"> </video> <div class="scrim"></div> <span class="tag">Motion Design</span> <div class="meta"> <div> <h3>Промо ролик</h3> <span>0:09</span> </div> <div class="play-glass" onclick="toggleWorkVideo(this)"> <svg class="icon-play" viewBox="0 0 24 24" fill="none"><path d="M5 3v18l15-9L5 3z" fill="#fff"/></svg> <svg class="icon-pause" viewBox="0 0 24 24" fill="none"><rect x="5" y="3" width="5" height="18" fill="#fff"/><rect x="14" y="3" width="5" height="18" fill="#fff"/></svg> </div> </div> </div> </div> </section> <!-- CAPABILITIES STRIP --> <section style="padding-top:0;"> <div class="wrap"> <div class="strip reveal"> <div class="strip-item"> <div class="num">Монтаж</div> <h4>Сторителлинг</h4> <p>Структура и темп, который удерживает внимание до последней секунды.</p> </div> <div class="strip-item"> <div class="num">Моушн</div> <h4>Анимация</h4> <p>Графика, текст и переходы на высшем уровне.</p> </div> <div class="strip-item"> <div class="num">Цвет</div> <h4>Цветокоррекция</h4> <p>Полная работа с цветом – вручную, без фильтров.</p> </div> <div class="strip-item"> <div class="num">Звук</div> <h4>Саунд-дизайн</h4> <p>Звук, который чувствуется ещё до того, как его замечают.</p> </div> </div> </div> </section> <!-- TESTIMONIALS --> <section id="testimonials"> <div class="wrap"> <div class="section-head reveal"> <div class="eyebrow" style="justify-content:center">Отзывы клиентов</div> <h2>Что говорят о работе</h2> </div> <div class="testi-grid"> <div class="testi-card glass reveal"> <p class="quote">«Работали с Егором плотно с января по апрель. До этого просмотры стояли на месте, а тут ролики начали реально цеплять людей. Клиенты стали записываться прямо с инсты. Мощный спец, рекомендую!»</p> <div class="testi-person"> <div class="avatar" style="--av-a:#3a2a4a; --av-b:#100b16;">А</div> <div class="who"> <strong>Александр</strong> <span>Клиент</span> </div> </div> </div> <div class="testi-card glass reveal" style="transition-delay:0.08s"> <p class="quote">«Сдал вовремя, ни одной правки. Просто пушка 🔥»</p> <div class="testi-person"> <div class="avatar" style="--av-a:#2a3a3a; --av-b:#0b1616;">Д</div> <div class="who"> <strong>Дмитрий</strong> <span>Клиент</span> </div> </div> </div> <div class="testi-card glass reveal" style="transition-delay:0.16s"> <p class="quote">«Выглядит дорого, охваты сразу пошли вверх. Берем следующий пакет!»</p> <div class="testi-person"> <div class="avatar" style="--av-a:#2a3a4a; --av-b:#0b1420;">А</div> <div class="who"> <strong>Алиса</strong> <span>Клиент</span> </div> </div> </div> </div> </div> </section> <!-- CONTACT --> <section id="contact"> <div class="wrap"> <div class="contact-panel glass reveal"> <div class="glow"></div> <h2>Готов обсудить проект</h2> <p>Расскажи, что нужно снять или собрать — отвечу в течение дня.</p> <div class="contact-actions"> <a href="http://t.me/egor_scale" class="glass-btn primary">Написать в Telegram</a> </div> </div> </div> </section> </main> <div id="videoModal" onclick="if(event.target===this)closeVideoModal()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.75);backdrop-filter:blur(12px);z-index:9999;align-items:center;justify-content:center;opacity:0;transition:opacity .3s;"> <div style="position:relative;max-width:90vw;max-height:90vh;display:flex;align-items:center;justify-content:center;transform:scale(.94);transition:transform .3s;"><button onclick="closeVideoModal()" style="position:absolute;right:0;top:-50px;font-size:28px;background:none;border:none;color:white;cursor:pointer">✕</button><video id="modalVideo" controls autoplay style="max-width:min(90vw,1400px);max-height:90vh;width:auto;height:auto;object-fit:contain;border-radius:20px;display:block"></video></div></div> <script> /* ── preloader ── */ const preloader = document.getElementById('preloader'); // hide preloader after animations complete (~1.6s) then show nav window.addEventListener('load', () => { setTimeout(() => { preloader.classList.add('hidden'); document.querySelector('.nav').classList.add('visible'); }, 1800); }); // fallback if load fires late setTimeout(() => { preloader.classList.add('hidden'); document.querySelector('.nav').classList.add('visible'); }, 3000); /* ── ambient stars ── */ const starsEl = document.getElementById('stars'); const starCount = window.innerWidth < 680 ? 40 : 90; for(let i = 0; i < starCount; i++){ const s = document.createElement('div'); s.className = 'star'; s.style.left = Math.random() * 100 + '%'; s.style.top = Math.random() * 100 + '%'; s.style.animationDelay = (Math.random() * 4) + 's'; starsEl.appendChild(s); } /* ── scroll reveal ── */ const revealEls = document.querySelectorAll('.reveal'); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if(e.isIntersecting) e.target.classList.add('in'); }); }, { threshold: 0.13 }); revealEls.forEach(el => io.observe(el)); /* ── nav magnet hover ── */ document.querySelectorAll('.nav a').forEach(link => { link.addEventListener('mousemove', e => { const r = link.getBoundingClientRect(); const x = e.clientX - r.left - r.width / 2; const y = e.clientY - r.top - r.height / 2; link.style.transform = `translate(${x * 0.18}px, ${y * 0.22}px)`; }); link.addEventListener('mouseleave', () => { link.style.transform = ''; }); }); /* ── hero parallax on scroll ── */ const heroH1 = document.querySelector('.hero h1'); const heroSub = document.querySelector('.hero .sub'); window.addEventListener('scroll', () => { const y = window.scrollY; if(heroH1) heroH1.style.transform = `translateY(${y * 0.04}px)`; if(heroSub) heroSub.style.transform = `translateY(${y * 0.025}px)`; }, { passive: true }); /* ── work-card video play/pause ── Когда вставите реальный <source src="..."> в video-теги выше, функция начнёт проигрывать / ставить на паузу нужное видео. */ function toggleWorkVideo(btn){ const v=btn.closest(".work-card").querySelector("video"); const s=v.querySelector("source"); if(s&&s.src){document.getElementById("modalVideo").src=s.src;let md=document.getElementById("videoModal");md.style.display="flex";requestAnimationFrame(()=>{md.style.opacity="1";md.firstElementChild.style.transform="scale(1)";});document.body.style.overflow="hidden";document.getElementById("modalVideo").play();} return; } function closeVideoModal(){const md=document.getElementById("videoModal");const m=document.getElementById("modalVideo");m.pause();m.src="";md.style.opacity="0";md.firstElementChild.style.transform="scale(.94)";document.body.style.overflow="";setTimeout(()=>md.style.display="none",300);}document.addEventListener("keydown",e=>{if(e.key==="Escape")closeVideoModal();}); document.querySelectorAll('.work-card video').forEach(v=>{ v.addEventListener('loadedmetadata',()=>{try{v.currentTime=3;}catch(e){}}); v.addEventListener('seeked',()=>{v.pause();}); }); </script> </body> </html>