diff --git a/home.txt b/home.txt index d385757..61fcad0 100644 --- a/home.txt +++ b/home.txt @@ -23,7 +23,8 @@ box-sizing: border-box; } - .header-video { + .header-video, + .header-image { position: absolute; inset: 0; width: 100%; @@ -32,6 +33,9 @@ background-size: cover; background-repeat: no-repeat; z-index: 0; + margin-top: 130px !important; + border-top-left-radius: 50px !important; + border-top-right-radius: 50px !important; will-change: transform, opacity; backface-visibility: hidden; transform-origin: center top; @@ -87,70 +91,31 @@ gap: 10px; } - .btn-primary, - .btn-secondary { - position: relative; + .btn-primary { display: inline-flex; align-items: center; - justify-content: center; - overflow: hidden; + gap: 6px; + padding: 10px 22px; border-radius: 100px; + background: var(--btn-primary-bg); + color: var(--btn-primary-text) !important; + font-size: 13.5px; + font-weight: 600; text-decoration: none !important; - transition: transform 0.2s ease, opacity 0.26s ease-out; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important; - } - - .btn-primary { - color: light-dark(#000000, #ffffff) !important; + transition: transform 0.15s ease; } .btn-secondary { - color: var(--text) !important; - } - - .glass-surface__filter { - width: 100%; - height: 100%; - pointer-events: none; - position: absolute; - inset: 0; - opacity: 0; - z-index: -1; - } - - .glass-surface__content { - width: 100%; - height: 100%; - display: flex; + display: inline-flex; align-items: center; - justify-content: center; - gap: 6px; - padding: 10px 22px; - border-radius: inherit; - position: relative; - z-index: 1; + padding: 10px 20px; + border-radius: 100px; font-size: 13.5px; font-weight: 600; - } - - .btn-secondary .glass-surface__content { - padding: 10px 20px; - } - - .glass-surface--svg { - background: transparent !important; - border: none !important; - box-shadow: none; - backdrop-filter: var(--filter-id, url(#glass-filter)) saturate(var(--glass-saturation, 1)) !important; - -webkit-backdrop-filter: var(--filter-id, url(#glass-filter)) saturate(var(--glass-saturation, 1)) !important; - } - - .glass-surface--fallback { - background: transparent!important; - -webkit-backdrop-filter: blur(12px); - backdrop-filter: blur(12px); - border: transparent !important; - box-shadow: none; + text-decoration: none !important; + backdrop-filter: blur(25px) saturate(2); + -webkit-backdrop-filter: blur(25px) saturate(2); + transition: transform 0.15s ease; } @keyframes fadeVideoBg { @@ -173,11 +138,24 @@ will-change: opacity; } - .body-blurred-video { + .body-blurred-video, + .body-blurred-image { width: 100%; height: 100%; object-fit: cover; filter: blur(25px); + display: block; + } + + .body-blurred-video:not([src]), + .body-blurred-video[src=""], + .body-blurred-image:not([src]), + .body-blurred-image[src=""], + .header-video:not([src]), + .header-video[src=""], + .header-image:not([src]), + .header-image[src=""] { + display: none; } .content-section { @@ -236,20 +214,6 @@ transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; } - .feature-box .glass-surface__content { - flex-direction: column; - align-items: stretch; - justify-content: flex-start; - gap: 0; - padding: 24px; - } - - .feature-box.glass-surface--svg, - .feature-box.glass-surface--fallback { - background: transparent !important; - border: none !important; - } - .feature-box::after { content: ""; position: absolute; @@ -328,20 +292,13 @@ letter-spacing: 0.01em; } - .hero-greeting .glass-surface__content { - padding: 6px 16px; - font-size: 13px; - font-weight: 600; - letter-spacing: 0.01em; - } - .hero-resume { - width: min(100vw, 200px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--text); margin-top: 30px; + text-align: center; } @media (max-width: 900px) { @@ -350,6 +307,16 @@ top: max(6px, env(safe-area-inset-top)); width: 90%; } + + .header-video, + .header-image { + margin-top: 80px !important; + border-top-left-radius: 55px !important; + border-top-right-radius: 55px !important; + width: 97% !important; + margin-left: auto !important; + margin-right: auto !important; + } } @media (orientation: landscape) and (max-height: 550px) { @@ -385,11 +352,6 @@ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; } - - .feature-box, - .feature-box .glass-surface__content { - padding: 18px; - } } @@ -397,6 +359,7 @@
+
+
@@ -416,9 +380,9 @@

A community-built media project focused on freedom, privacy, and giving people control over their own experience.

-
+
- diff --git a/src/assets/images/wallpaper-media/tree.png b/src/assets/images/wallpaper-media/tree.png new file mode 100644 index 0000000..bafc6e5 Binary files /dev/null and b/src/assets/images/wallpaper-media/tree.png differ diff --git a/src/css/components.css b/src/css/components.css index 75a4861..870d1e2 100644 --- a/src/css/components.css +++ b/src/css/components.css @@ -220,6 +220,56 @@ main.prose blockquote p { width: 75%; } +.theme-ambient { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 520px; + z-index: -1; + pointer-events: none; + overflow: hidden; + opacity: 0; +} + +.theme-ambient.is-in { + animation: themeAmbientIn 1s cubic-bezier(0.22, 1, 0.36, 1) both; +} + +.theme-ambient-media { + position: absolute; + inset: -12% 0; + width: 100%; + height: 124%; + object-fit: cover; + filter: blur(70px) saturate(1.4) brightness(0.8); + transform: scale(1.15); + -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 85%); + mask-image: linear-gradient(to bottom, #000 0%, transparent 85%); +} + +@keyframes themeAmbientIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@media (prefers-reduced-motion: reduce) { + .theme-ambient.is-in { + animation: none; + opacity: 1; + } +} + +body.is-home .theme-ambient, +body.is-404 .theme-ambient { + display: none; +} + .content-animate>* { animation: smoothBlurReveal 0.44s cubic-bezier(0.22, 1, 0.36, 1) both; will-change: filter, opacity, transform; diff --git a/src/css/overlay.css b/src/css/overlay.css index bb614f2..c1ff461 100644 --- a/src/css/overlay.css +++ b/src/css/overlay.css @@ -375,12 +375,10 @@ align-items: center; gap: 3px; z-index: 2003; - background: var(--bg-menu); border-radius: 100px; padding: 3px 6px; - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); + backdrop-filter: blur(16px) saturate(5); + -webkit-backdrop-filter: blur(16px) saturate(5); opacity: 0; transform: translateY(-8px) scale(0.96); transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1) 0.08s, diff --git a/src/js/glass.js b/src/js/glass.js deleted file mode 100644 index 1844211..0000000 --- a/src/js/glass.js +++ /dev/null @@ -1,133 +0,0 @@ -var GLASS_TARGETS = [ - { - selector: ".btn-primary", - options: { - distortionScale: -300, - displace: 0, - backgroundOpacity: 0.1 - } - }, - { - selector: ".btn-secondary", - options: { - distortionScale: -300, - displace: 0, - backgroundOpacity: 0.1 - } - }, - { - selector: ".hero-greeting", - options: { - distortionScale: -200, - displace: 0, - backgroundOpacity: 0.08 - } - }, - { - selector: ".feature-box", - options: { - distortionScale: -220, - displace: 0, - backgroundOpacity: 0.12, - saturation: 1.3, - cornerRadius: 30 - } - } -]; - -function initGlassSurface(el, opts) { - if (!el || el.getAttribute("data-glass")) return; - el.setAttribute("data-glass", "true"); - opts = opts || {}; - var distortionScale = opts.distortionScale !== undefined ? opts.distortionScale : -180; - var displace = opts.displace !== undefined ? opts.displace : 0; - var backgroundOpacity = opts.backgroundOpacity !== undefined ? opts.backgroundOpacity : 0; - var saturation = opts.saturation !== undefined ? opts.saturation : 1; - var redOffset = opts.redOffset !== undefined ? opts.redOffset : 0; - var greenOffset = opts.greenOffset !== undefined ? opts.greenOffset : 10; - var blueOffset = opts.blueOffset !== undefined ? opts.blueOffset : 20; - var borderWidth = opts.borderWidth !== undefined ? opts.borderWidth : 0.07; - var brightness = opts.brightness !== undefined ? opts.brightness : 50; - var opacity = opts.opacity !== undefined ? opts.opacity : 0.93; - var blur = opts.blur !== undefined ? opts.blur : 11; - var mixBlendMode = opts.mixBlendMode || "difference"; - - var uid = Math.random().toString(36).slice(2, 9); - var filterId = "glass-filter-" + uid; - var redGradId = "red-grad-" + uid; - var blueGradId = "blue-grad-" + uid; - var softId = "soft-" + uid; - - var isWebkit = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); - var isFirefox = /Firefox/.test(navigator.userAgent); - var div = document.createElement("div"); - div.style.backdropFilter = "url(#" + filterId + ")"; - var svgSupported = !isWebkit && !isFirefox && div.style.backdropFilter !== ""; - - var rect = el.getBoundingClientRect(); - var w = Math.round(rect.width) || 160; - var h = Math.round(rect.height) || 40; - var r = opts.cornerRadius !== undefined ? opts.cornerRadius : Math.round(h / 2); - var edge = Math.min(w, h) * (borderWidth * 0.5); - - var mapSvg = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - ''; - var mapUrl = "data:image/svg+xml," + encodeURIComponent(mapSvg); - - el.style.setProperty("--glass-frost", backgroundOpacity); - el.style.setProperty("--glass-saturation", saturation); - el.style.setProperty("--filter-id", "url(#" + filterId + ")"); - el.classList.add(svgSupported ? "glass-surface--svg" : "glass-surface--fallback"); - - var filterSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - filterSvg.setAttribute("class", "glass-surface__filter"); - filterSvg.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - ''; - - var childNodes = Array.prototype.slice.call(el.childNodes); - var wrap = document.createElement("div"); - wrap.className = "glass-surface__content"; - childNodes.forEach(function (n) { wrap.appendChild(n); }); - - el.appendChild(filterSvg); - if (!svgSupported) { - var sheen = document.createElement("span"); - sheen.className = "glass-surface__sheen"; - sheen.setAttribute("aria-hidden", "true"); - var rim = document.createElement("span"); - rim.className = "glass-surface__rim"; - rim.setAttribute("aria-hidden", "true"); - el.appendChild(sheen); - el.appendChild(rim); - } - el.appendChild(wrap); -} - -function applyGlassSurfaces(root) { - var base = root || document; - GLASS_TARGETS.forEach(function (target) { - base.querySelectorAll(target.selector).forEach(function (el) { - initGlassSurface(el, target.options); - }); - }); -} \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index add5b34..2e97541 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -39,15 +39,15 @@ var THEMES_GENERAL = [ { id: "cyberpunk", label: "Cyberpunk" } ]; -var THEME_VIDEOS = { - dark: "https://www.pexels.com/download/video/39880903/", - light: "https://www.pexels.com/download/video/36600568/", - midnight: "https://www.pexels.com/download/video/15860507/", - nord: "https://www.pexels.com/download/video/31468607/", - dracula: "https://www.pexels.com/download/video/8116002/", - forest: "https://www.pexels.com/download/video/11265968/", - sunset: "https://www.pexels.com/download/video/855437/", - cyberpunk: "https://www.pexels.com/download/video/32336464/" +var THEME_MEDIA = { + dark: "/src/assets/images/wallpaper-media/tree.png", + light: "https://www.pexels.com/download/video//", + midnight: "https://www.pexels.com/download/video//", + nord: "https://www.pexels.com/download/video//", + dracula: "https://www.pexels.com/download/video//", + forest: "https://www.pexels.com/download/video//", + sunset: "https://www.pexels.com/download/video//", + cyberpunk: "https://www.pexels.com/download/video//" }; var SITE_TREE = [ @@ -59,16 +59,16 @@ var SITE_TREE = [ { title: "Start here", items: [ - { title: "Introduction", file: "/start-here/introduction.md", path: "/start-here/introduction" }, + { title: "Introduction", file: "/start-here/introduction.md", path: "/start-here/introduction", hasMedia: true }, { title: "Architecture", file: "/start-here/architecture.md", path: "/start-here/architecture" } ] }, { title: "Products", items: [ - { title: "Home", file: "/products/home.md", path: "/products/home" }, - { title: "Go", file: "/products/go.md", path: "/products/go" }, - { title: "TV", file: "/products/tv.md", path: "/products/tv" }, + { title: "Home", file: "/products/home.md", path: "/products/home", hasMedia: true }, + { title: "Go", file: "/products/go.md", path: "/products/go", hasMedia: true }, + { title: "TV", file: "/products/tv.md", path: "/products/tv", hasMedia: true }, { title: "Player", file: "/products/player.md", path: "/products/player" } ] }, @@ -88,10 +88,10 @@ var SITE_TREE = [ { title: "Vyla SDK", items: [ - { title: "SDK", file: "/sdk/vyla-sdk/index.md", path: "/sdk" }, + { title: "SDK", file: "/sdk/vyla-sdk/index.md", path: "/sdk", hasMedia: true }, { title: "SDK Quickstart", file: "/sdk/vyla-sdk/quickstart.md", path: "/sdk/vyla-sdk/quickstart" }, - { title: "Manga", file: "/sdk/vyla-sdk/manga.md", path: "/sdk/vyla-sdk/manga" }, - { title: "Contributing", file: "/sdk/vyla-sdk/contributing.md", path: "/sdk/vyla-sdk/contributing" } + { title: "Manga", file: "/sdk/vyla-sdk/manga.md", path: "/sdk/vyla-sdk/manga", hasMedia: true }, + { title: "Contributing", file: "/sdk/vyla-sdk/contributing.md", path: "/sdk/vyla-sdk/contributing", hasMedia: true } ] } ] @@ -111,7 +111,7 @@ var SITE_TREE = [ title: "Reference", items: [ { title: "Paths", file: "/stream-api/reference/paths.md", path: "/stream-api/reference/paths" }, - { title: "Media Data", file: "/stream-api/reference/media-data.md", path: "/stream-api/reference/media-data" }, + { title: "Media Data", file: "/stream-api/reference/media-data.md", path: "/stream-api/reference/media-data", hasMedia: true }, { title: "Operations", file: "/stream-api/reference/operations.md", path: "/stream-api/reference/operations" } ] }, @@ -160,33 +160,100 @@ function getThemeMode() { return localStorage.getItem(THEME_KEY) || "auto"; } + function applyTheme() { var mode = getThemeMode(); var theme = resolveTheme(mode); document.documentElement.setAttribute("data-theme", theme); + var logo = document.getElementById("brand-logo"); if (logo) logo.src = theme === "light" ? "/src/assets/images/dark_logo.png" : "/src/assets/images/logo.png"; + applyPreferences(); - var targetSrc = THEME_VIDEOS[theme] || THEME_VIDEOS.halloween; + + + var targetSrc = THEME_MEDIA[theme] || THEME_MEDIA.dark; var videosOff = getPref("video", "on") === "off"; - document.querySelectorAll(".body-blurred-video, .header-video").forEach(function (v) { - if (videosOff) { - v.pause(); - if (v.getAttribute("src")) { - v.removeAttribute("src"); - v.load(); + var isImageSource = /\.(jpe?g|png|gif|webp|avif|svg)(\?.*)?$/i.test(targetSrc || ""); + + document.querySelectorAll(".body-blurred-video, .header-video, .body-blurred-image, .header-image").forEach(function (element) { + var isVideo = element.tagName === "VIDEO"; + var isImage = element.tagName === "IMG"; + + if ((isVideo && (videosOff || isImageSource)) || (isImage && !isImageSource)) { + if (isVideo) { + element.pause(); + element.load(); } + element.removeAttribute("src"); return; } - if (v.getAttribute("src") !== targetSrc) { - v.src = targetSrc; - v.load(); - v.play().catch(function () { }); + + if (element.getAttribute("src") !== targetSrc) { + element.src = targetSrc; + + if (isVideo) { + element.load(); + element.play().catch(function () { }); + } } }); + + updateThemeAmbient(targetSrc, isImageSource, videosOff); + applyThemeCopy(theme); } +function updateThemeAmbient(src, isImage, videosOff) { + var el = document.getElementById("theme-ambient"); + if (!el) { + el = document.createElement("div"); + el.id = "theme-ambient"; + el.className = "theme-ambient"; + el.setAttribute("aria-hidden", "true"); + document.body.appendChild(el); + } + + var blocked = !src || (!isImage && videosOff); + el.hidden = blocked; + if (blocked) return; + + var want = isImage ? "img" : "video"; + var media = el.querySelector(".theme-ambient-media"); + if (!media || media.tagName.toLowerCase() !== want) { + el.innerHTML = ""; + media = document.createElement(want); + media.className = "theme-ambient-media"; + if (isImage) { + media.alt = ""; + } else { + media.muted = true; + media.loop = true; + media.autoplay = true; + media.playsInline = true; + media.setAttribute("muted", ""); + media.setAttribute("playsinline", ""); + } + el.appendChild(media); + } + + if (media.getAttribute("src") !== src) { + media.src = src; + if (!isImage) { + media.load(); + media.play().catch(function () { }); + } + } +} + +function revealThemeAmbient() { + var el = document.getElementById("theme-ambient"); + if (!el || el.hidden) return; + el.classList.remove("is-in"); + void el.offsetWidth; + el.classList.add("is-in"); +} + function setTheme(mode) { localStorage.setItem(THEME_KEY, mode); applyTheme(); @@ -466,6 +533,7 @@ function detectPlatform() { var ua = navigator.userAgent || ""; if (/Android.*(TV|AFT|BRAVIA|SHIELD)|AndroidTV|GoogleTV|SmartTV/i.test(ua)) return "tv"; if (/Android/i.test(ua)) return "android"; + if (/iPhone|iPad|iPod/i.test(ua)) return "ios"; if (/Windows/i.test(ua)) return "windows"; if (/Mac OS X|Macintosh/i.test(ua)) return "mac"; if (/Linux|X11/i.test(ua)) return "linux"; @@ -1207,94 +1275,6 @@ function navigateTo(path) { loadPage(); } -function initGlassSurface(el, opts) { - if (!el || el.getAttribute("data-glass")) return; - el.setAttribute("data-glass", "true"); - opts = opts || {}; - var distortionScale = opts.distortionScale !== undefined ? opts.distortionScale : -300; - var displace = opts.displace !== undefined ? opts.displace : 0; - var backgroundOpacity = opts.backgroundOpacity !== undefined ? opts.backgroundOpacity : 0.1; - var saturation = opts.saturation !== undefined ? opts.saturation : 1; - var redOffset = opts.redOffset !== undefined ? opts.redOffset : 0; - var greenOffset = opts.greenOffset !== undefined ? opts.greenOffset : 10; - var blueOffset = opts.blueOffset !== undefined ? opts.blueOffset : 20; - var borderWidth = opts.borderWidth !== undefined ? opts.borderWidth : 0.07; - var brightness = opts.brightness !== undefined ? opts.brightness : 50; - var opacity = opts.opacity !== undefined ? opts.opacity : 0.93; - var blur = opts.blur !== undefined ? opts.blur : 11; - var mixBlendMode = opts.mixBlendMode || "difference"; - - var uid = Math.random().toString(36).slice(2, 9); - var filterId = "glass-filter-" + uid; - var redGradId = "red-grad-" + uid; - var blueGradId = "blue-grad-" + uid; - var softId = "soft-" + uid; - - var isWebkit = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); - var isFirefox = /Firefox/.test(navigator.userAgent); - var div = document.createElement("div"); - div.style.backdropFilter = "url(#" + filterId + ")"; - var svgSupported = !isWebkit && !isFirefox && div.style.backdropFilter !== ""; - - var rect = el.getBoundingClientRect(); - var w = Math.round(rect.width) || 160; - var h = Math.round(rect.height) || 44; - var r = opts.cornerRadius !== undefined ? opts.cornerRadius : Math.round(h / 2); - var edge = Math.min(w, h) * (borderWidth * 0.5); - - var mapSvg = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - ''; - var mapUrl = "data:image/svg+xml," + encodeURIComponent(mapSvg); - - el.style.setProperty("--glass-frost", backgroundOpacity); - el.style.setProperty("--glass-saturation", saturation); - el.style.setProperty("--filter-id", "url(#" + filterId + ")"); - el.classList.add(svgSupported ? "glass-surface--svg" : "glass-surface--fallback"); - - var filterSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - filterSvg.setAttribute("class", "glass-surface__filter"); - filterSvg.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - ''; - - var childNodes = Array.prototype.slice.call(el.childNodes); - var wrap = document.createElement("div"); - wrap.className = "glass-surface__content"; - childNodes.forEach(function (n) { wrap.appendChild(n); }); - - el.appendChild(filterSvg); - if (!svgSupported) { - var sheen = document.createElement("span"); - sheen.className = "glass-surface__sheen"; - sheen.setAttribute("aria-hidden", "true"); - var rim = document.createElement("span"); - rim.className = "glass-surface__rim"; - rim.setAttribute("aria-hidden", "true"); - el.appendChild(sheen); - el.appendChild(rim); - } - el.appendChild(wrap); -} - function mountGreeting(root) { var content = root.querySelector(".header-content"); var title = root.querySelector(".header-title"); @@ -1315,9 +1295,6 @@ function mountGreeting(root) { resume.textContent = "Continue: " + (last.title || last.path); actions.appendChild(resume); } - if (typeof applyGlassSurfaces === "function") { - applyGlassSurfaces(root); - } } function loadPage() { @@ -1421,7 +1398,7 @@ function loadPage() { '
' + '
' + '
' + - '
' + + (route.item.hasMedia ? '
' : '') + '
' + '
' + '
' + @@ -1455,6 +1432,7 @@ function loadPage() { contentEl.classList.remove("caught-up"); contentEl.classList.add("content-animate"); + revealThemeAmbient(); var catchUpOnScroll = function () { if (contentEl.classList.contains("content-animate")) {