Spaces:
Running
Running
Hermes Agent commited on
Commit ·
bfa9bd9
1
Parent(s): 8300a1e
feat: sync full-screen ambient blurred backdrop with spotlight hero theme colors
Browse files- apex/ui/abyss.css +72 -0
- apex/ui/spotlight-loader.js +43 -26
- apex/ui/spotlight.css +3 -3
- apex/ui/spotlight.html +3 -4
apex/ui/abyss.css
CHANGED
|
@@ -5647,3 +5647,75 @@ div[data-category="cast"] .cardScalable,
|
|
| 5647 |
box-sizing: border-box !important;
|
| 5648 |
}
|
| 5649 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5647 |
box-sizing: border-box !important;
|
| 5648 |
}
|
| 5649 |
}
|
| 5650 |
+
|
| 5651 |
+
/* ========================================================
|
| 5652 |
+
APEX DYNAMIC AMBIENT BACKDROP SYNCHRONIZATION
|
| 5653 |
+
Full-screen dynamic blur synced with active Spotlight item
|
| 5654 |
+
======================================================== */
|
| 5655 |
+
#abyss-spotlight-backdrop {
|
| 5656 |
+
position: fixed;
|
| 5657 |
+
inset: 0;
|
| 5658 |
+
width: 100vw;
|
| 5659 |
+
height: 100vh;
|
| 5660 |
+
pointer-events: none;
|
| 5661 |
+
z-index: 0;
|
| 5662 |
+
overflow: hidden;
|
| 5663 |
+
opacity: 0;
|
| 5664 |
+
transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
| 5665 |
+
background-color: #050508;
|
| 5666 |
+
}
|
| 5667 |
+
|
| 5668 |
+
html.abyss-spotlight-visible #abyss-spotlight-backdrop {
|
| 5669 |
+
opacity: 1;
|
| 5670 |
+
}
|
| 5671 |
+
|
| 5672 |
+
.abyss-spotlight-backdrop-layer {
|
| 5673 |
+
position: absolute;
|
| 5674 |
+
inset: -50px;
|
| 5675 |
+
background-size: cover;
|
| 5676 |
+
background-position: center top;
|
| 5677 |
+
opacity: 0;
|
| 5678 |
+
filter: blur(58px) saturate(165%) contrast(115%) brightness(40%);
|
| 5679 |
+
transform: scale(1.15);
|
| 5680 |
+
transition: opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1), transform 1.5s cubic-bezier(0.16, 1, 0.3, 1);
|
| 5681 |
+
will-change: opacity, transform;
|
| 5682 |
+
}
|
| 5683 |
+
|
| 5684 |
+
.abyss-spotlight-backdrop-layer.is-active {
|
| 5685 |
+
opacity: 1;
|
| 5686 |
+
transform: scale(1.03);
|
| 5687 |
+
}
|
| 5688 |
+
|
| 5689 |
+
/* Atmospheric contrast gradient: transparent at top, soft vignette downwards, anchoring into true black */
|
| 5690 |
+
#abyss-spotlight-backdrop::after {
|
| 5691 |
+
content: "";
|
| 5692 |
+
position: absolute;
|
| 5693 |
+
inset: 0;
|
| 5694 |
+
background: linear-gradient(
|
| 5695 |
+
to bottom,
|
| 5696 |
+
rgba(5, 5, 8, 0.15) 0%,
|
| 5697 |
+
rgba(5, 5, 8, 0.35) 25%,
|
| 5698 |
+
rgba(5, 5, 8, 0.65) 55%,
|
| 5699 |
+
rgba(5, 5, 8, 0.88) 80%,
|
| 5700 |
+
#050508 100%
|
| 5701 |
+
);
|
| 5702 |
+
pointer-events: none;
|
| 5703 |
+
}
|
| 5704 |
+
|
| 5705 |
+
/* Ensure background transparency pass-through on the home screen when spotlight is active */
|
| 5706 |
+
html.abyss-spotlight-visible body,
|
| 5707 |
+
html.abyss-spotlight-visible .backgroundContainer,
|
| 5708 |
+
html.abyss-spotlight-visible #indexPage,
|
| 5709 |
+
html.abyss-spotlight-visible .pageTabContent,
|
| 5710 |
+
html.abyss-spotlight-visible .homeSectionsContainer,
|
| 5711 |
+
html.abyss-spotlight-visible .mainAnimatedPages,
|
| 5712 |
+
html.abyss-spotlight-visible .pageContainer {
|
| 5713 |
+
background-color: transparent !important;
|
| 5714 |
+
background: transparent !important;
|
| 5715 |
+
}
|
| 5716 |
+
|
| 5717 |
+
html.abyss-spotlight-visible #indexPage,
|
| 5718 |
+
html.abyss-spotlight-visible .homeSectionsContainer {
|
| 5719 |
+
position: relative;
|
| 5720 |
+
z-index: 1;
|
| 5721 |
+
}
|
apex/ui/spotlight-loader.js
CHANGED
|
@@ -24,6 +24,7 @@
|
|
| 24 |
var backdropLayerA = null;
|
| 25 |
var backdropLayerB = null;
|
| 26 |
var activeBackdropLayer = null;
|
|
|
|
| 27 |
|
| 28 |
function safe(fn) {
|
| 29 |
// Runs fn and swallows/reports any error so one failure never kills the loader.
|
|
@@ -55,6 +56,16 @@
|
|
| 55 |
|
| 56 |
function clearSpotlightBackdrop() {
|
| 57 |
safe(function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
var els = document.querySelectorAll(BACKDROP_SELECTOR + "[" + BACKDROP_MARK_ATTR + "]");
|
| 59 |
for (var i = 0; i < els.length; i++) {
|
| 60 |
els[i].style.backgroundImage = "";
|
|
@@ -95,34 +106,37 @@
|
|
| 95 |
}
|
| 96 |
|
| 97 |
function installBackdropOverlay() {
|
| 98 |
-
if (backdropOverlay) return;
|
| 99 |
-
var container = document.querySelector(".backdropContainer");
|
| 100 |
-
if (!container
|
| 101 |
-
|
| 102 |
-
backdropOverlay = document.createElement("div");
|
| 103 |
-
backdropOverlay.id = "abyss-spotlight-backdrop";
|
| 104 |
-
backdropLayerA = document.createElement("div");
|
| 105 |
-
backdropLayerB = document.createElement("div");
|
| 106 |
-
backdropLayerA.className = "abyss-spotlight-backdrop-layer";
|
| 107 |
-
backdropLayerB.className = "abyss-spotlight-backdrop-layer";
|
| 108 |
-
backdropOverlay.appendChild(backdropLayerA);
|
| 109 |
-
backdropOverlay.appendChild(backdropLayerB);
|
| 110 |
|
| 111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
}
|
| 123 |
|
| 124 |
function setSpotlightBackdrop(url) {
|
| 125 |
-
if (!url
|
|
|
|
|
|
|
|
|
|
| 126 |
safe(function () {
|
| 127 |
var incoming = activeBackdropLayer === backdropLayerA ? backdropLayerB : backdropLayerA;
|
| 128 |
var outgoing = activeBackdropLayer;
|
|
@@ -136,7 +150,7 @@
|
|
| 136 |
if (outgoing && outgoing !== incoming) {
|
| 137 |
setTimeout(function () {
|
| 138 |
outgoing.classList.remove("is-active");
|
| 139 |
-
},
|
| 140 |
}
|
| 141 |
});
|
| 142 |
activeBackdropLayer = incoming;
|
|
@@ -244,7 +258,6 @@
|
|
| 244 |
}
|
| 245 |
|
| 246 |
window.addEventListener("message", function (event) {
|
| 247 |
-
if (!currentIframe || event.source !== currentIframe.contentWindow) return;
|
| 248 |
if (!event.data || event.data.type !== "abyss-spotlight") return;
|
| 249 |
if (event.data.action === "leave") {
|
| 250 |
spotlightFocused = false;
|
|
@@ -292,7 +305,11 @@
|
|
| 292 |
if (action !== lastAction) {
|
| 293 |
postToFrame(iframe, action);
|
| 294 |
lastAction = action;
|
| 295 |
-
if (action === "pause")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
}
|
| 297 |
});
|
| 298 |
};
|
|
|
|
| 24 |
var backdropLayerA = null;
|
| 25 |
var backdropLayerB = null;
|
| 26 |
var activeBackdropLayer = null;
|
| 27 |
+
var currentBackdropUrl = null;
|
| 28 |
|
| 29 |
function safe(fn) {
|
| 30 |
// Runs fn and swallows/reports any error so one failure never kills the loader.
|
|
|
|
| 56 |
|
| 57 |
function clearSpotlightBackdrop() {
|
| 58 |
safe(function () {
|
| 59 |
+
currentBackdropUrl = null;
|
| 60 |
+
if (backdropLayerA) {
|
| 61 |
+
backdropLayerA.classList.remove("is-active");
|
| 62 |
+
backdropLayerA.style.backgroundImage = "";
|
| 63 |
+
}
|
| 64 |
+
if (backdropLayerB) {
|
| 65 |
+
backdropLayerB.classList.remove("is-active");
|
| 66 |
+
backdropLayerB.style.backgroundImage = "";
|
| 67 |
+
}
|
| 68 |
+
activeBackdropLayer = null;
|
| 69 |
var els = document.querySelectorAll(BACKDROP_SELECTOR + "[" + BACKDROP_MARK_ATTR + "]");
|
| 70 |
for (var i = 0; i < els.length; i++) {
|
| 71 |
els[i].style.backgroundImage = "";
|
|
|
|
| 106 |
}
|
| 107 |
|
| 108 |
function installBackdropOverlay() {
|
| 109 |
+
if (backdropOverlay && backdropOverlay.isConnected) return;
|
| 110 |
+
var container = document.querySelector(".backgroundContainer") || document.querySelector(".backdropContainer") || document.body;
|
| 111 |
+
if (!container) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
+
if (!backdropOverlay) {
|
| 114 |
+
backdropOverlay = document.createElement("div");
|
| 115 |
+
backdropOverlay.id = "abyss-spotlight-backdrop";
|
| 116 |
+
backdropLayerA = document.createElement("div");
|
| 117 |
+
backdropLayerB = document.createElement("div");
|
| 118 |
+
backdropLayerA.className = "abyss-spotlight-backdrop-layer";
|
| 119 |
+
backdropLayerB.className = "abyss-spotlight-backdrop-layer";
|
| 120 |
+
backdropOverlay.appendChild(backdropLayerA);
|
| 121 |
+
backdropOverlay.appendChild(backdropLayerB);
|
| 122 |
+
}
|
| 123 |
|
| 124 |
+
if (!backdropOverlay.isConnected) {
|
| 125 |
+
if (container === document.body) {
|
| 126 |
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
| 127 |
+
} else if (container.parentNode) {
|
| 128 |
+
container.parentNode.insertBefore(backdropOverlay, container.nextSibling);
|
| 129 |
+
} else {
|
| 130 |
+
document.body.appendChild(backdropOverlay);
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
}
|
| 134 |
|
| 135 |
function setSpotlightBackdrop(url) {
|
| 136 |
+
if (!url) return;
|
| 137 |
+
currentBackdropUrl = url;
|
| 138 |
+
installBackdropOverlay();
|
| 139 |
+
if (!backdropOverlay) return;
|
| 140 |
safe(function () {
|
| 141 |
var incoming = activeBackdropLayer === backdropLayerA ? backdropLayerB : backdropLayerA;
|
| 142 |
var outgoing = activeBackdropLayer;
|
|
|
|
| 150 |
if (outgoing && outgoing !== incoming) {
|
| 151 |
setTimeout(function () {
|
| 152 |
outgoing.classList.remove("is-active");
|
| 153 |
+
}, 450);
|
| 154 |
}
|
| 155 |
});
|
| 156 |
activeBackdropLayer = incoming;
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
window.addEventListener("message", function (event) {
|
|
|
|
| 261 |
if (!event.data || event.data.type !== "abyss-spotlight") return;
|
| 262 |
if (event.data.action === "leave") {
|
| 263 |
spotlightFocused = false;
|
|
|
|
| 305 |
if (action !== lastAction) {
|
| 306 |
postToFrame(iframe, action);
|
| 307 |
lastAction = action;
|
| 308 |
+
if (action === "pause") {
|
| 309 |
+
clearSpotlightBackdrop();
|
| 310 |
+
} else if (action === "resume" && currentBackdropUrl) {
|
| 311 |
+
setSpotlightBackdrop(currentBackdropUrl);
|
| 312 |
+
}
|
| 313 |
}
|
| 314 |
});
|
| 315 |
};
|
apex/ui/spotlight.css
CHANGED
|
@@ -52,10 +52,10 @@ body {
|
|
| 52 |
position: absolute;
|
| 53 |
inset: 0;
|
| 54 |
background:
|
| 55 |
-
/* Seamless bottom fade
|
| 56 |
-
linear-gradient(to top,
|
| 57 |
/* Left side reading gradient ensuring text/metadata has 100% contrast */
|
| 58 |
-
linear-gradient(to right,
|
| 59 |
pointer-events: none;
|
| 60 |
}
|
| 61 |
|
|
|
|
| 52 |
position: absolute;
|
| 53 |
inset: 0;
|
| 54 |
background:
|
| 55 |
+
/* Seamless bottom fade that allows ambient colors to radiate down through content rails */
|
| 56 |
+
linear-gradient(to top, rgba(5, 5, 8, 0.82) 0%, rgba(5, 5, 8, 0.55) 25%, rgba(0, 0, 0, 0.22) 55%, transparent 82%),
|
| 57 |
/* Left side reading gradient ensuring text/metadata has 100% contrast */
|
| 58 |
+
linear-gradient(to right, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.78) 32%, rgba(0, 0, 0, 0.35) 58%, transparent 85%);
|
| 59 |
pointer-events: none;
|
| 60 |
}
|
| 61 |
|
apex/ui/spotlight.html
CHANGED
|
@@ -810,11 +810,10 @@
|
|
| 810 |
}
|
| 811 |
|
| 812 |
try {
|
| 813 |
-
const syncUrl = artwork.backdrop
|
| 814 |
-
? (artwork.primaryBackdrop ? itemImageUrls(item).primary : (artwork.usedThumb ? itemImageUrls(item).thumb : itemImageUrls(item).backdrop))
|
| 815 |
-
: null;
|
| 816 |
if (syncUrl) {
|
| 817 |
-
window.
|
|
|
|
| 818 |
}
|
| 819 |
} catch { /* parent sync is optional */ }
|
| 820 |
let episodePrefix = '';
|
|
|
|
| 810 |
}
|
| 811 |
|
| 812 |
try {
|
| 813 |
+
const syncUrl = artwork.backdrop || (artwork.primaryBackdrop ? itemImageUrls(item).primary : (artwork.usedThumb ? itemImageUrls(item).thumb : itemImageUrls(item).backdrop));
|
|
|
|
|
|
|
| 814 |
if (syncUrl) {
|
| 815 |
+
const origin = (window.location && window.location.origin && window.location.origin !== 'null') ? window.location.origin : '*';
|
| 816 |
+
window.parent.postMessage({ type: 'abyss-spotlight', action: 'backdrop-sync', url: syncUrl }, origin);
|
| 817 |
}
|
| 818 |
} catch { /* parent sync is optional */ }
|
| 819 |
let episodePrefix = '';
|