411 lines
10 KiB
Vue
411 lines
10 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, onUnmounted, ref } from "vue";
|
|
import { mdiPlay } from "@mdi/js";
|
|
|
|
const { t, locale } = useI18n();
|
|
const config = useRuntimeConfig();
|
|
const muxAccentColor = "#00f0ff";
|
|
const muxPrimaryColor = "#e6fbff";
|
|
const muxSecondaryColor = "#020617";
|
|
|
|
const muxPlaybackId = computed(() => String(config.public.muxPlaybackId || "").trim());
|
|
const videoTitle = computed(() => (
|
|
locale.value === "ru" ? "Демо-видео Agent Teams" : "Agent Teams demo video"
|
|
));
|
|
const muxVideoTitle = computed(() => (
|
|
locale.value === "ru" ? "Демо Agent Teams" : "Agent Teams demo"
|
|
));
|
|
const muxPlayerUrl = computed(() => {
|
|
if (!muxPlaybackId.value) return "";
|
|
|
|
const url = new URL(`https://player.mux.com/${encodeURIComponent(muxPlaybackId.value)}`);
|
|
url.searchParams.set("accent-color", muxAccentColor);
|
|
url.searchParams.set("primary-color", muxPrimaryColor);
|
|
url.searchParams.set("secondary-color", muxSecondaryColor);
|
|
url.searchParams.set("metadata-video-id", "agent-teams-demo");
|
|
url.searchParams.set("metadata-video-title", muxVideoTitle.value);
|
|
url.searchParams.set("metadata-player-name", "Landing hero");
|
|
url.searchParams.set("title", muxVideoTitle.value);
|
|
url.searchParams.set("video-title", muxVideoTitle.value);
|
|
return url.toString();
|
|
});
|
|
const isLoaded = ref(false);
|
|
const hasError = ref(false);
|
|
|
|
let loadFallbackTimer: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
function clearLoadFallback() {
|
|
if (!loadFallbackTimer) return;
|
|
clearTimeout(loadFallbackTimer);
|
|
loadFallbackTimer = null;
|
|
}
|
|
|
|
function markLoaded() {
|
|
if (hasError.value) return;
|
|
isLoaded.value = true;
|
|
clearLoadFallback();
|
|
}
|
|
|
|
function markError() {
|
|
hasError.value = true;
|
|
clearLoadFallback();
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadFallbackTimer = setTimeout(markLoaded, 2500);
|
|
});
|
|
|
|
onUnmounted(clearLoadFallback);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="hero-video">
|
|
<div class="hero-video__ambient" aria-hidden="true" />
|
|
<div class="hero-video__edge hero-video__edge--top" aria-hidden="true" />
|
|
<div class="hero-video__edge hero-video__edge--bottom" aria-hidden="true" />
|
|
<div class="hero-video__corner hero-video__corner--tl" aria-hidden="true" />
|
|
<div class="hero-video__corner hero-video__corner--tr" aria-hidden="true" />
|
|
<div class="hero-video__corner hero-video__corner--bl" aria-hidden="true" />
|
|
<div class="hero-video__corner hero-video__corner--br" aria-hidden="true" />
|
|
|
|
<ClientOnly>
|
|
<iframe
|
|
v-if="muxPlayerUrl && !hasError"
|
|
class="hero-video__player"
|
|
:class="{ 'hero-video__player--loaded': isLoaded }"
|
|
:src="muxPlayerUrl"
|
|
:title="videoTitle"
|
|
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture"
|
|
allowfullscreen
|
|
loading="lazy"
|
|
referrerpolicy="strict-origin-when-cross-origin"
|
|
@load="markLoaded"
|
|
@error="markError"
|
|
/>
|
|
|
|
<template #fallback>
|
|
<div class="hero-video__skeleton">
|
|
<div class="hero-video__skeleton-pulse" />
|
|
<div class="hero-video__skeleton-content">
|
|
<div class="hero-video__skeleton-spinner" />
|
|
<span class="hero-video__skeleton-label">{{ t("hero.watchDemo") }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</ClientOnly>
|
|
|
|
<div v-if="!isLoaded && !hasError && muxPlayerUrl" class="hero-video__skeleton">
|
|
<div class="hero-video__skeleton-pulse" />
|
|
<div class="hero-video__skeleton-content">
|
|
<div class="hero-video__skeleton-spinner" />
|
|
<span class="hero-video__skeleton-label">{{ t("hero.watchDemo") }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="hasError || !muxPlayerUrl" class="hero-video__error">
|
|
<v-icon :icon="mdiPlay" size="36" class="hero-video__error-icon" />
|
|
<span class="hero-video__error-text">{{ t("hero.videoUnavailable") }}</span>
|
|
</div>
|
|
|
|
<div class="hero-video__scan" aria-hidden="true" />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.hero-video {
|
|
--hero-video-cyan: #00f0ff;
|
|
--hero-video-cyan-soft: rgba(0, 240, 255, 0.22);
|
|
--hero-video-magenta: #ff2bff;
|
|
--hero-video-magenta-soft: rgba(255, 43, 255, 0.18);
|
|
--hero-video-dark: rgba(2, 6, 23, 0.96);
|
|
|
|
position: relative;
|
|
z-index: 1;
|
|
aspect-ratio: 16 / 9;
|
|
border-radius: 16px;
|
|
background:
|
|
radial-gradient(circle at 18% 0%, var(--hero-video-cyan-soft), transparent 42%),
|
|
radial-gradient(circle at 88% 100%, var(--hero-video-magenta-soft), transparent 38%),
|
|
var(--hero-video-dark);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border: 1px solid rgba(0, 240, 255, 0.34);
|
|
overflow: hidden;
|
|
box-shadow:
|
|
0 20px 60px rgba(0, 0, 0, 0.6),
|
|
0 0 34px rgba(0, 240, 255, 0.18),
|
|
0 0 52px rgba(255, 43, 255, 0.1),
|
|
inset 0 1px 0 rgba(230, 251, 255, 0.18);
|
|
}
|
|
|
|
.hero-video::before,
|
|
.hero-video::after {
|
|
content: "";
|
|
position: absolute;
|
|
pointer-events: none;
|
|
z-index: 4;
|
|
}
|
|
|
|
.hero-video::before {
|
|
inset: 0;
|
|
border: 1px solid rgba(230, 251, 255, 0.16);
|
|
border-radius: inherit;
|
|
box-shadow:
|
|
inset 0 0 28px rgba(0, 240, 255, 0.08),
|
|
inset 0 -26px 42px rgba(2, 6, 23, 0.44);
|
|
}
|
|
|
|
.hero-video::after {
|
|
inset: 0;
|
|
background:
|
|
linear-gradient(90deg, transparent 0 7%, rgba(0, 240, 255, 0.1) 7.2% 7.55%, transparent 7.8%),
|
|
linear-gradient(180deg, rgba(255, 255, 255, 0.1), transparent 18%, transparent 78%, rgba(0, 240, 255, 0.1));
|
|
mix-blend-mode: screen;
|
|
opacity: 0.32;
|
|
}
|
|
|
|
.hero-video__ambient,
|
|
.hero-video__scan,
|
|
.hero-video__edge,
|
|
.hero-video__corner {
|
|
position: absolute;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.hero-video__ambient {
|
|
inset: 0;
|
|
z-index: 1;
|
|
background:
|
|
linear-gradient(135deg, rgba(0, 240, 255, 0.14), transparent 28%, transparent 68%, rgba(255, 43, 255, 0.16)),
|
|
radial-gradient(circle at 50% 50%, transparent 58%, rgba(0, 0, 0, 0.34));
|
|
mix-blend-mode: screen;
|
|
opacity: 0.74;
|
|
}
|
|
|
|
.hero-video__scan {
|
|
inset: 0;
|
|
z-index: 5;
|
|
background:
|
|
repeating-linear-gradient(to bottom, rgba(230, 251, 255, 0.1) 0 1px, transparent 1px 5px),
|
|
linear-gradient(90deg, transparent, rgba(0, 240, 255, 0.12), transparent);
|
|
mix-blend-mode: soft-light;
|
|
opacity: 0.22;
|
|
}
|
|
|
|
.hero-video__edge {
|
|
left: 18px;
|
|
right: 18px;
|
|
z-index: 6;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, transparent, var(--hero-video-cyan), var(--hero-video-magenta), transparent);
|
|
box-shadow: 0 0 16px rgba(0, 240, 255, 0.45);
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.hero-video__edge--top {
|
|
top: 9px;
|
|
}
|
|
|
|
.hero-video__edge--bottom {
|
|
bottom: 9px;
|
|
opacity: 0.58;
|
|
}
|
|
|
|
.hero-video__corner {
|
|
z-index: 6;
|
|
width: 28px;
|
|
height: 28px;
|
|
border-color: var(--hero-video-cyan);
|
|
filter: drop-shadow(0 0 10px rgba(0, 240, 255, 0.54));
|
|
}
|
|
|
|
.hero-video__corner--tl {
|
|
top: 8px;
|
|
left: 8px;
|
|
border-top: 2px solid;
|
|
border-left: 2px solid;
|
|
}
|
|
|
|
.hero-video__corner--tr {
|
|
top: 8px;
|
|
right: 8px;
|
|
border-top: 2px solid;
|
|
border-right: 2px solid;
|
|
}
|
|
|
|
.hero-video__corner--bl {
|
|
bottom: 8px;
|
|
left: 8px;
|
|
border-bottom: 2px solid;
|
|
border-left: 2px solid;
|
|
}
|
|
|
|
.hero-video__corner--br {
|
|
right: 8px;
|
|
bottom: 8px;
|
|
border-right: 2px solid;
|
|
border-bottom: 2px solid;
|
|
}
|
|
|
|
.hero-video__player {
|
|
position: relative;
|
|
z-index: 2;
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
aspect-ratio: 16 / 9;
|
|
border-radius: 14px;
|
|
opacity: 0;
|
|
transition: opacity 0.5s ease;
|
|
border: none;
|
|
background: #020617;
|
|
}
|
|
|
|
.hero-video__player--loaded {
|
|
opacity: 1;
|
|
}
|
|
|
|
.hero-video__skeleton {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 16px;
|
|
background: rgba(6, 10, 18, 0.96);
|
|
z-index: 7;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.hero-video__skeleton::before,
|
|
.hero-video__skeleton::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.hero-video__skeleton::before {
|
|
background:
|
|
linear-gradient(90deg, rgba(2, 6, 16, 0.18), rgba(2, 6, 16, 0.36)),
|
|
linear-gradient(180deg, rgba(0, 234, 255, 0.08), rgba(255, 43, 255, 0.08)),
|
|
url("/screenshots/2.jpg") center / cover;
|
|
opacity: 0.82;
|
|
filter: saturate(0.98) contrast(1.14) brightness(0.72);
|
|
transform: scale(1.035);
|
|
}
|
|
|
|
.hero-video__skeleton::after {
|
|
background:
|
|
linear-gradient(90deg, transparent 0 48%, rgba(0, 234, 255, 0.14) 48.2% 48.6%, transparent 48.8%),
|
|
repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.08) 0 1px, transparent 1px 4px);
|
|
mix-blend-mode: screen;
|
|
opacity: 0.34;
|
|
}
|
|
|
|
.hero-video__skeleton-pulse {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
135deg,
|
|
rgba(0, 240, 255, 0.12) 0%,
|
|
rgba(255, 0, 255, 0.08) 50%,
|
|
rgba(0, 240, 255, 0.1) 100%
|
|
);
|
|
mix-blend-mode: screen;
|
|
animation: skeletonPulse 2s ease-in-out infinite;
|
|
}
|
|
|
|
.hero-video__skeleton-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 12px;
|
|
z-index: 1;
|
|
}
|
|
|
|
.hero-video__skeleton-spinner {
|
|
width: 58px;
|
|
height: 58px;
|
|
border-radius: 50%;
|
|
border: 2px solid rgba(0, 240, 255, 0.28);
|
|
border-top-color: rgba(0, 240, 255, 0.92);
|
|
background: rgba(2, 8, 18, 0.56);
|
|
box-shadow:
|
|
0 0 0 1px rgba(0, 240, 255, 0.14) inset,
|
|
0 0 28px rgba(0, 240, 255, 0.34);
|
|
animation: spinnerRotate 0.8s linear infinite;
|
|
}
|
|
|
|
.hero-video__skeleton-label {
|
|
font-size: 13px;
|
|
font-weight: 800;
|
|
color: rgba(0, 240, 255, 0.88);
|
|
font-family: "JetBrains Mono", monospace;
|
|
letter-spacing: 0.05em;
|
|
text-transform: uppercase;
|
|
text-shadow: 0 0 16px rgba(0, 240, 255, 0.42);
|
|
}
|
|
|
|
@keyframes skeletonPulse {
|
|
0%,
|
|
100% { opacity: 0.3; }
|
|
50% { opacity: 0.8; }
|
|
}
|
|
|
|
@keyframes spinnerRotate {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
.hero-video__error {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 7;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 12px;
|
|
padding: 32px;
|
|
background:
|
|
linear-gradient(135deg, rgba(0, 234, 255, 0.08), rgba(255, 43, 255, 0.05)),
|
|
rgba(2, 6, 16, 0.94);
|
|
}
|
|
|
|
.hero-video__error-icon {
|
|
color: rgba(0, 240, 255, 0.3);
|
|
}
|
|
|
|
.hero-video__error-text {
|
|
font-size: 13px;
|
|
color: #8892b0;
|
|
font-family: "JetBrains Mono", monospace;
|
|
text-align: center;
|
|
}
|
|
|
|
@media (max-width: 960px) {
|
|
.hero-video {
|
|
max-width: 100%;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.hero-video {
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.hero-video__player {
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.hero-video__edge {
|
|
left: 12px;
|
|
right: 12px;
|
|
}
|
|
|
|
.hero-video__corner {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
}
|
|
</style>
|