Reinit marzipano
All checks were successful
Marzipano Prod / Produktivumgebung (push) Successful in 2m11s

This commit is contained in:
2024-10-02 20:01:42 +02:00
commit 4de399a7cf
28615 changed files with 89172 additions and 0 deletions

1440
assets/data.js Normal file

File diff suppressed because it is too large Load Diff

584
assets/index.js Normal file
View File

@ -0,0 +1,584 @@
//@ts-check
/*
* Copyright 2016 Google Inc, 2020 Georg-Cantor-Gymnasium Halle (Saale), All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
import APP_DATA from "./data";
(($) => {
$(window).on("load", () => {
$(".preloader").fadeOut(100);
});
// @ts-ignore
var Marzipano = window.Marzipano;
// mdi icons
var svgs = {
"chevron-up-circle-outline":
'<svg xmlns="http://www.w3.org/2000/svg" id="mdi-chevron-up-circle-outline" viewBox="0 0 24 24" height="1em" width="1em" fill="#fff"><path d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12M7.4,15.4L12,10.8L16.6,15.4L18,14L12,8L6,14L7.4,15.4Z" /></svg>',
"play-circle-outline":
'<svg xmlns="http://www.w3.org/2000/svg" id="mdi-play-circle-outline" viewBox="0 0 24 24" height="1em" width="1em" fill="#fff"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z" /></svg>',
"information-outline":
'<svg xmlns="http://www.w3.org/2000/svg" id="mdi-information-outline" viewBox="0 0 24 24" height="1em" width="1em" fill="#fff"><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" /></svg>',
"pause-circle-outline":
'<svg xmlns="http://www.w3.org/2000/svg" id="mdi-pause-circle-outline" viewBox="0 0 24 24" height="1em" width="1em" fill="#fff"><path d="M13,16V8H15V16H13M9,16V8H11V16H9M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" /></svg>',
};
// Grab elements from DOM.
var panoElement = document.querySelector("#pano");
var sceneNameElement = document.querySelector("#titleBar .sceneName");
var sceneListElement = document.querySelector("#sceneList");
var sceneElements = document.querySelectorAll("#sceneList .scene");
var sceneListToggleElement = document.querySelector("#sceneListToggle");
var autorotateToggleElement = document.querySelector("#autorotateToggle");
var fullscreenToggleElement = document.querySelector("#fullscreenToggle");
// Detect desktop or mobile mode.
const setMode = () => {
if (mql.matches) {
document.body.classList.remove("desktop");
document.body.classList.add("mobile");
} else {
document.body.classList.remove("mobile");
document.body.classList.add("desktop");
}
};
var mql = matchMedia("(max-width: 768px), (max-height: 500px)");
setMode();
mql.onchange = setMode;
// Viewer options.
var viewerOpts = {
controls: {
mouseViewMode: APP_DATA.settings.mouseViewMode,
},
};
// Initialize viewer.
var viewer = new Marzipano.Viewer(panoElement, viewerOpts);
// create list for audio elements
var audioList = [];
// Create scenes.
var scenes = APP_DATA.scenes.map((data) => {
var urlPrefix = "tiles";
var source = Marzipano.ImageUrlSource.fromString(urlPrefix + "/" + data.id + "/{z}/{f}/{y}/{x}.jpg", {
cubeMapPreviewUrl: urlPrefix + "/" + data.id + "/preview.jpg",
});
var geometry = new Marzipano.CubeGeometry(data.levels);
var limiter = Marzipano.RectilinearView.limit.traditional(
data.faceSize,
(100 * Math.PI) / 180,
(120 * Math.PI) / 180
);
var view = new Marzipano.RectilinearView(data.initialViewParameters, limiter);
var scene = viewer.createScene({
source: source,
geometry: geometry,
view: view,
pinFirstLevel: true,
});
// Create link hotspots.
data.linkHotspots.forEach(function (hotspot) {
var element = createLinkHotspotElement(hotspot);
scene.hotspotContainer().createHotspot(element, { yaw: hotspot.yaw, pitch: hotspot.pitch });
});
// Create info hotspots.
data.infoHotspots.forEach(function (hotspot) {
var element = createInfoHotspotElement(hotspot, data.id);
scene.hotspotContainer().createHotspot(element, { yaw: hotspot.yaw, pitch: hotspot.pitch });
});
return {
data: data,
scene: scene,
view: view,
};
});
// Set up autorotate, if enabled.
var autorotate = Marzipano.autorotate({
yawSpeed: 0.03,
targetPitch: 0,
targetFov: Math.PI / 2,
});
if (APP_DATA.settings.autorotateEnabled) {
autorotateToggleElement?.classList.add("enabled");
}
// Start with the scene list open on desktop.
if (!document.body.classList.contains("mobile")) {
showSceneList();
}
// Set handler for autorotate toggle.
autorotateToggleElement?.addEventListener("click", toggleAutorotate);
// Set up fullscreen mode
if (APP_DATA.settings.fullscreenButton) {
document.body.classList.add("fullscreen-enabled");
fullscreenToggleElement?.addEventListener("click", function () {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else if (document.exitFullscreen) {
document.exitFullscreen();
}
});
document.addEventListener("fullscreenchange", () => {
if (document.fullscreenElement) {
fullscreenToggleElement?.classList.add("enabled");
} else {
fullscreenToggleElement?.classList.remove("enabled");
}
});
} else {
document.body.classList.add("fullscreen-disabled");
}
// Set handler for scene list toggle.
sceneListToggleElement?.addEventListener("click", toggleSceneList);
// Set handler for scene switch.
scenes.forEach(function (scene) {
var el = document.querySelector('#sceneList .scene[data-id="' + scene.data.id + '"]');
el?.addEventListener("click", function () {
switchScene(scene);
showSceneList();
// On mobile, hide scene list after selecting a scene.
if (document.body.classList.contains("mobile")) {
hideSceneList();
}
});
});
// DOM elements for view controls.
var viewUpElement = document.querySelector("#viewUp");
var viewDownElement = document.querySelector("#viewDown");
var viewLeftElement = document.querySelector("#viewLeft");
var viewRightElement = document.querySelector("#viewRight");
var viewInElement = document.querySelector("#viewIn");
var viewOutElement = document.querySelector("#viewOut");
// Dynamic parameters for controls.
var velocity = 0.7;
var friction = 3;
// Associate view controls with elements.
var controls = viewer.controls();
controls.registerMethod(
"upElement",
new Marzipano.ElementPressControlMethod(viewUpElement, "y", -velocity, friction),
true
);
controls.registerMethod(
"downElement",
new Marzipano.ElementPressControlMethod(viewDownElement, "y", velocity, friction),
true
);
controls.registerMethod(
"leftElement",
new Marzipano.ElementPressControlMethod(viewLeftElement, "x", -velocity, friction),
true
);
controls.registerMethod(
"rightElement",
new Marzipano.ElementPressControlMethod(viewRightElement, "x", velocity, friction),
true
);
controls.registerMethod(
"inElement",
new Marzipano.ElementPressControlMethod(viewInElement, "zoom", -velocity, friction),
true
);
controls.registerMethod(
"outElement",
new Marzipano.ElementPressControlMethod(viewOutElement, "zoom", velocity, friction),
true
);
function sanitize(s) {
return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
}
function switchScene(scene) {
stopPlayback();
stopAutorotate();
scene.view.setParameters(scene.data.initialViewParameters);
scene.scene.switchTo();
startAutorotate();
updateSceneName(scene);
updateSceneList(scene);
}
function updateSceneName(scene) {
if (sceneNameElement) {
sceneNameElement.innerHTML = sanitize(scene.data.name);
}
}
function updateSceneList(scene) {
for (var i = 0; i < sceneElements.length; i++) {
var el = sceneElements[i];
if (el.getAttribute("data-id") === scene.data.id) {
el.classList.add("current");
} else {
el.classList.remove("current");
}
}
}
function showSceneList() {
sceneListElement?.classList.add("enabled");
sceneListToggleElement?.classList.add("enabled");
}
function hideSceneList() {
sceneListElement?.classList.remove("enabled");
sceneListToggleElement?.classList.remove("enabled");
}
function toggleSceneList() {
sceneListElement?.classList.toggle("enabled");
sceneListToggleElement?.classList.toggle("enabled");
}
function startAutorotate() {
if (!autorotateToggleElement?.classList.contains("enabled")) {
return;
}
viewer.startMovement(autorotate);
viewer.setIdleMovement(3000, autorotate);
}
function stopAutorotate() {
viewer.stopMovement();
viewer.setIdleMovement(Infinity);
}
function stopPlayback() {
audioList.forEach((a) => {
a.pause();
a.currentTime = 0;
});
const x = document.querySelectorAll("video");
for (let i = 0; i < x.length; i++) {
if (!x[i].paused) {
x[i].pause();
}
}
}
function toggleAutorotate() {
if (autorotateToggleElement?.classList.contains("enabled")) {
autorotateToggleElement?.classList.remove("enabled");
stopAutorotate();
} else {
autorotateToggleElement?.classList.add("enabled");
startAutorotate();
}
}
function createLinkHotspotElement(hotspot) {
// Create wrapper element to hold icon and tooltip.
var wrapper = document.createElement("div");
wrapper.classList.add("hotspot");
wrapper.classList.add("link-hotspot");
// Create image element.
const icon = document.createElement("span");
icon.innerHTML = svgs["chevron-up-circle-outline"];
// Set rotation transform.
var transformProperties = ["-webkit-transform", "transform"];
for (var i = 0; i < transformProperties.length; i++) {
var property = transformProperties[i];
icon.style[property] = "rotate(" + hotspot.rotation + "rad)";
}
// Add click event handler.
wrapper.addEventListener("click", function () {
switchScene(findSceneById(hotspot.target));
});
// Prevent touch and scroll events from reaching the parent element.
// This prevents the view control logic from interfering with the hotspot.
stopTouchAndScrollEventPropagation(wrapper);
// Create tooltip element.
var tooltip = document.createElement("div");
tooltip.classList.add("hotspot-tooltip");
tooltip.classList.add("link-hotspot-tooltip");
tooltip.innerHTML = findSceneDataById(hotspot.target)?.name ?? "";
wrapper.appendChild(icon);
wrapper.appendChild(tooltip);
return wrapper;
}
/**
*
* @param {*} hotspot
* @param {string} sceneId
* @returns {HTMLDivElement}
*/
function createInfoHotspotElement(hotspot, sceneId) {
// Create wrapper element to hold icon and tooltip.
var wrapper = document.createElement("div");
wrapper.classList.add("hotspot");
wrapper.classList.add("info-hotspot");
// Create hotspot/tooltip header.
var header = document.createElement("div");
header.classList.add("info-hotspot-header");
// Create image element.
var iconWrapper = document.createElement("div");
iconWrapper.classList.add("info-hotspot-icon-wrapper");
// Create title element.
var title = document.createElement("div");
title.classList.add("info-hotspot-title");
title.innerHTML = hotspot.title;
// Create close element.
var closeWrapper = document.createElement("div");
closeWrapper.classList.add("info-hotspot-close-wrapper");
var closeIcon = document.createElement("i");
closeIcon.classList.add("info-hotspot-close-icon", "fa-solid", "fa-circle-xmark");
closeWrapper.appendChild(closeIcon);
// Construct header element.
header.appendChild(iconWrapper);
header.appendChild(title);
// Place header and text into wrapper element.
wrapper.appendChild(header);
var toggle;
switch (hotspot.type) {
case "audio":
case "audio-room": {
iconWrapper.innerHTML = svgs["play-circle-outline"];
if (hotspot.type == "audio-room") {
wrapper.classList.add("audio-room");
}
const player = new Audio();
player.preload = "none";
player.src = hotspot.src;
player.addEventListener("play", () => {
iconWrapper.innerHTML = svgs["pause-circle-outline"];
});
player.addEventListener("pause", () => {
iconWrapper.innerHTML = svgs["play-circle-outline"];
});
player.addEventListener("ended", () => {
iconWrapper.innerHTML = svgs["play-circle-outline"];
});
audioList.push(player);
toggle = () => {
if (player.paused) {
player.play();
} else {
player.pause();
}
};
break;
}
case "title":
iconWrapper.innerHTML = svgs["information-outline"];
toggle = () => {};
break;
default:
iconWrapper.innerHTML = svgs["information-outline"];
const modal = document.createElement("div");
modal.classList.add("modal");
const modalDialog = document.createElement("div");
modalDialog.classList.add("modal-dialog", "modal-dialog-centered", "modal-lg");
const modalContent = document.createElement("div");
modalContent.classList.add("modal-content");
const modalHeader = document.createElement("div");
modalHeader.classList.add("modal-header");
const modalTitle = document.createElement("h5");
modalTitle.classList.add("modal-title");
modalTitle.innerHTML = hotspot.title;
modalHeader.appendChild(modalTitle);
const buttonClose = document.createElement("button");
buttonClose.type = "button";
buttonClose.classList.add("btn-close");
buttonClose.setAttribute("data-bs-dismiss", "modal");
modalHeader.appendChild(buttonClose);
modalContent.appendChild(modalHeader);
switch (hotspot.type) {
case "iframe":
var iframe = document.createElement("iframe");
modalContent.appendChild(iframe);
break;
case "video":
var video = document.createElement("video");
video.controls = true;
video.classList.add("video-js", "vjs-fluid", "w-100");
modalContent.appendChild(video);
break;
case "image":
var image = document.createElement("img");
modalContent.appendChild(image);
break;
default:
var modalBody = document.createElement("div");
modalBody.classList.add("modal-body");
modalContent.appendChild(modalBody);
}
modalDialog.appendChild(modalContent);
modal.appendChild(modalDialog);
document.body.appendChild(modal);
// @ts-ignore
const bsModal = new bootstrap.Modal(modal);
var videoJS = () =>
modalContent.querySelectorAll("video.video-js").forEach((video) => {
// @ts-ignore
videojs(video, {});
});
toggle = () => {
switch (hotspot.type) {
case "iframe":
if (iframe.src == "") iframe.src = hotspot.src;
break;
case "video":
if (video.src == "") video.src = hotspot.src;
// @ts-ignore
videojs(video, {});
break;
case "image":
if (image.src == "") image.src = hotspot.src;
break;
case "embed":
if (modalBody.innerHTML == "") {
fetch(`/tour/content/${sceneId}/${hotspot.name}/index.html`)
.then((response) => response.text())
.then((text) => {
modalBody.innerHTML = text;
// @ts-ignore
new VenoBox({
selector: ".vb-gallery",
numeration: true,
infinigall: true,
share: true,
shareStyle: "block",
spinner: "grid",
fitView: true,
navTouch: true,
});
videoJS();
});
}
break;
default:
if (modalBody.innerHTML == "") modalBody.innerHTML = hotspot.text;
videoJS();
break;
}
stopPlayback();
bsModal.show();
};
}
// Show content when hotspot is clicked.
wrapper.querySelector(".info-hotspot-header")?.addEventListener("click", toggle);
// Prevent touch and scroll events from reaching the parent element.
// This prevents the view control logic from interfering with the hotspot.
stopTouchAndScrollEventPropagation(wrapper);
return wrapper;
}
// Prevent touch and scroll events from reaching the parent element.
function stopTouchAndScrollEventPropagation(element) {
var eventList = ["touchstart", "touchmove", "touchend", "touchcancel", "wheel", "mousewheel"];
for (var i = 0; i < eventList.length; i++) {
element.addEventListener(eventList[i], function (event) {
event.stopPropagation();
});
}
}
function findSceneById(id) {
for (var i = 0; i < scenes.length; i++) {
if (scenes[i].data.id === id) {
return scenes[i];
}
}
return null;
}
function findSceneDataById(id) {
for (var i = 0; i < APP_DATA.scenes.length; i++) {
if (APP_DATA.scenes[i].id === id) {
return APP_DATA.scenes[i];
}
}
return null;
}
// Display the initial scene.
switchScene(scenes[0]);
// enable matomo analytics
// @ts-ignore
var _paq = (window._paq = window._paq || []);
_paq.push(["setDoNotTrack", true]);
_paq.push(["disableCookies"]);
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function () {
var u = "//analytics.cantorgymnasium.de/";
_paq.push(["setTrackerUrl", u + "matomo.php"]);
_paq.push(["setSiteId", "2"]);
var d = document,
g = d.createElement("script"),
s = d.getElementsByTagName("script")[0];
g.async = true;
g.src = u + "matomo.js";
// @ts-ignore
s.parentNode.insertBefore(g, s);
})();
// show introduction modal
const modal = document.getElementById("modal-intro");
// @ts-ignore
new bootstrap.Modal(modal).show();
// @ts-ignore
})(jQuery);

16
assets/marzipano.js Normal file

File diff suppressed because one or more lines are too long

412
assets/style.css Normal file
View File

@ -0,0 +1,412 @@
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
-webkit-user-drag: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
min-width: 0;
}
video {
width: 100%;
}
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
font-size: 16px;
background-color: #000;
}
a,
a:hover,
a:active,
a:visited {
text-decoration: none;
color: inherit;
}
#pano {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#titleBar {
position: absolute;
top: 0;
left: 0;
right: 40px;
height: 40px;
text-align: center;
border-radius: 12px;
margin: 10px;
margin-left: 20px;
margin-right: 30px;
}
/* If there is a fullscreen button the title bar must make space for it */
body.fullscreen-enabled #titleBar {
right: 80px;
}
body.fullscreen-enabled.mobile #titleBar {
right: 100px;
}
/* If there are multiple scenes the title bar must make space for the scene list toggle */
body.multiple-scenes #titleBar {
left: 40px;
}
#titleBar .sceneName {
width: 100%;
height: 100%;
line-height: 27.5px;
padding: 5px;
background-color: #1a1a37;
font-weight: 900;
font-size: 1.5rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
-webkit-user-select: text;
user-select: text;
border-radius: 30px;
}
.button {
cursor: pointer;
display: flex;
align-items: center;
font-size: 30px;
}
.button > .on {
display: none;
}
.button > .off {
display: block;
}
.button.enabled > .on {
display: block;
}
.button.enabled > .off {
display: none;
}
#fullscreenToggle {
justify-content: center;
position: absolute;
top: 0;
right: 0;
width: 40px;
height: 40px;
padding: 5px;
background-color: #ffbc3b;
border-radius: 50%;
margin: 10px;
color: #fff;
font-size: 30px;
}
#autorotateToggle {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
right: 0;
width: 40px;
height: 40px;
padding: 5px;
background-color: #ffbc3b;
border-radius: 20px;
margin: 10px;
margin-right: 20px;
cursor: pointer;
color: #fff;
font-size: 30px;
}
/* If there is a fullscreen button, autorotate must placed a bit to the left */
body.fullscreen-enabled #autorotateToggle {
right: 40px;
}
#sceneListToggle {
position: absolute;
top: 0;
left: 0;
width: 40px;
height: 40px;
padding: 5px;
background-color: #ffbc3b;
border-radius: 50%;
margin: 10px;
color: #fff;
}
#sceneList {
position: absolute;
width: 50px;
margin: 10px;
margin-top: 60px;
max-height: calc(100vh - 70px);
display: flex;
flex-direction: column;
gap: 5px;
padding: 5px;
overflow: auto;
background-color: #1a1a37;
border-radius: 15px;
transition: 0.2s ease;
}
#sceneList.enabled {
width: 250px;
}
/* Hide scene title on collapse */
#sceneList:not(.enabled) .scene > *:not(svg) {
display: none;
}
#sceneList .scene {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
border-radius: 10px;
color: #fff;
font-weight: 700;
height: 40px;
cursor: pointer;
}
#sceneList .scene svg {
font-size: 24px;
flex-shrink: 0;
}
#sceneList .scene span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
#sceneList .scene:hover,
#sceneList .scene:active {
background-color: #fff !important;
color: #1a1a37;
transition: 0.3s ease;
}
#sceneList .scene.current {
background-color: rgb(103, 115, 131);
background-color: #ffbc3b;
}
/* Link hotspot */
.link-hotspot {
width: 60px;
height: 60px;
margin-left: -30px;
margin-top: -30px;
opacity: 0.9;
transition: opacity 0.2s;
font-size: 60px;
}
.link-hotspot svg {
cursor: pointer;
}
.link-hotspot:hover,
.link-hotspot:active {
opacity: 1;
}
.mobile .link-hotspot {
width: 70px;
height: 70px;
}
.link-hotspot-tooltip {
position: absolute;
left: 100%;
top: 30px; /* ( 60 - (16 + 2*8) ) / 2 */
margin-left: 3px;
font-size: 16px;
max-width: 300px;
padding: 8px 10px;
border-radius: 5px;
background-color: rgb(58, 68, 84);
background-color: #1a1a37;
color: #fff;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
opacity: 0;
transform: translateX(-8px);
transition: -webkit-transform 0.3s, transform 0.3s, opacity 0.3s;
}
.link-hotspot:hover .link-hotspot-tooltip,
.link-hotspot:active .link-hotspot-tooltip {
opacity: 1;
transform: translateX(0);
}
/* Prevent tooltip from triggering */
.link-hotspot-tooltip {
pointer-events: none;
}
.link-hotspot:hover .link-hotspot-tooltip,
.link-hotspot:active .link-hotspot-tooltip {
pointer-events: all;
}
/* Info hotspot */
.info-hotspot {
line-height: 1.2em;
opacity: 0.9;
transition: opacity 0.2s 0.2s;
}
.info-hotspot svg {
font-size: 40px;
}
.info-hotspot .info-hotspot-header {
width: 50px;
height: 50px;
max-width: 50px;
padding: 5px;
padding-right: 10px;
border-radius: 25px;
background-color: #1a1a37;
cursor: pointer;
transition: max-width 0.5s ease;
color: #fff;
display: flex;
gap: 0.5rem;
align-items: center;
}
.info-hotspot.audio-room .info-hotspot-header {
background-color: #ffbc3b;
width: 75px;
height: 75px;
max-width: 75px;
border-radius: 37.5px;
}
.info-hotspot.audio-room svg {
font-size: 65px;
}
.info-hotspot-header:not(:hover):not(:active) .info-hotspot-title {
display: none;
}
.info-hotspot.visible .info-hotspot-header:hover,
.info-hotspot.visible .info-hotspot-header:active,
.info-hotspot .info-hotspot-header:hover,
.info-hotspot .info-hotspot-header:active {
width: auto;
max-width: 500px;
transition: max-width 0.2s ease;
}
.info-hotspot .info-hotspot-icon-wrapper {
flex-shrink: 0;
}
.info-hotspot .info-hotspot-title {
-webkit-user-select: text;
user-select: text;
font-weight: 900;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
/* View control buttons */
.viewControlButtons {
display: flex;
gap: 0.5rem;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 280px;
}
.viewControlButton {
width: 40px;
height: 40px;
padding: 5px;
background-color: rgb(103, 115, 131);
background-color: #fff;
border-radius: 50%;
color: #000;
}
/* Hide controls when width is too small */
@media (max-width: 600px) {
body.view-control-buttons .viewControlButton {
display: none;
}
}
.modal * {
-webkit-user-select: text;
user-select: text;
}
.modal-content > iframe {
height: 60vh;
}
.modal-body audio {
width: 100%;
}
.content li {
color: var(--bs-secondary-color);
font-family: var(--gcg-font-primary);
}