Initial commit

This commit is contained in:
Grit-Grenzdoerfer
2023-09-17 13:24:39 +02:00
commit 5f27fe0c5b
753 changed files with 15517 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
<script lang="ts">
import { navigate } from "svelte-routing"
import { serviceNavigation, sites } from "../stores"
</script>
<div class="footer">
<div class="infos">
<h3>Wasserski Erfurt</h3>
<div class="infos-inner">
<div class="upper">
<p>Inh. Michael Sadlon</p>
<p>Zum Nordstrand 4</p>
<p>99085 Erfurt</p>
</div>
<div class="lower">
<p>Tel.: 0361 - 796 876 4</p>
<p>Fax.: 0361 - 796 876 8</p>
<p>Email: info@wasserski-erfurt.de</p>
</div>
</div>
<div class="social">
<a href="https://www.instagram.com/wasserski_erfurt/">
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M11.7 3h12.6c4.8 0 8.7 3.9 8.7 8.7v12.6a8.7 8.7 0 0 1-8.7 8.7H11.7C6.9 33 3 29.1 3 24.3V11.7A8.7 8.7 0 0 1 11.7 3zm-.3 3A5.4 5.4 0 0 0 6 11.4v13.2c0 2.985 2.415 5.4 5.4 5.4h13.2a5.4 5.4 0 0 0 5.4-5.4V11.4C30 8.415 27.585 6 24.6 6H11.4zm14.475 2.25a1.875 1.875 0 1 1 0 3.75 1.875 1.875 0 0 1 0-3.75zM18 10.5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15zm0 3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"
fill="#333333"></path>
</svg>
</a>
<a href="https://www.facebook.com/wasserskierfurt/">
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M18 3.06c-8.25 0-15 6.735-15 15.03 0 7.5 5.49 13.725 12.66 14.85v-10.5h-3.81v-4.35h3.81v-3.315c0-3.765 2.235-5.835 5.67-5.835 1.635 0 3.345.285 3.345.285v3.705h-1.89c-1.86 0-2.445 1.155-2.445 2.34v2.82h4.17l-.675 4.35H20.34v10.5A15 15 0 0 0 33 18.09c0-8.295-6.75-15.03-15-15.03z"
fill="#333333"></path>
</svg>
</a>
</div>
</div>
<div class="services">
{#each $serviceNavigation?.elemente || [] as service, i (i)}
<button
on:click="{() => {
navigate(`${$sites[service.seite]?.path}`)
}}">{service?.name}</button
>
{/each}
</div>
</div>
<style lang="less">
@import "../assets/css/variables.less";
.social {
margin-top: 20px;
}
.footer {
margin-top: 60px;
width: 100vw;
font-size: 16px;
display: flex;
justify-content: space-between;
max-width: calc(@body-maxwidth - min(9vw, 200px));
background-color: @hover-color;
padding: min(4.5vw, 100px) min(4.5vw, 100px) 0px min(4.5vw, 100px);
}
.infos {
display: flex;
height: 70%;
.infos-inner {
gap: 10px;
display: flex;
}
}
.services {
display: flex;
flex-direction: column;
button {
font-size: inherit;
padding: 6px 0px;
text-align: start;
}
}
@media @mobile {
.infos {
flex-direction: column;
justify-content: start;
@media @mobile {
gap: 20px;
}
@media @tablet {
gap: 40px;
}
height: 350px;
.infos-inner {
flex-direction: column;
}
}
.footer {
}
}
@media @desktop {
.footer {
height: 350px;
.infos-inner {
gap: 5vw;
flex-direction: row;
}
}
}
</style>

View File

@@ -0,0 +1,60 @@
<script lang="ts">
export let cookieName
export let backgroundUrl = ""
export let textPosition = "center"
export let background = ""
let contentShown = false
const positions = {
oben: "flex-start",
mitte: "center",
unten: "flex-end",
}
window.addEventListener("ccAccept", (e) => {
if (e.detail[1] == cookieName) contentShown = true
})
//isCookieSet isnt really precise
function checkCookie(name) {
// Get all cookies
var allCookies = decodeURIComponent(document.cookie)
// Split into individual cookies
var cookies = allCookies.split(";")
var ccTagCookies = []
cookies.forEach((e) => {
e.includes("ccTags") ? (ccTagCookies = e.split(",")) : void 0
})
for (var i = 0; i < ccTagCookies.length; i++) {
var c = ccTagCookies[i]
// Trim whitespace
while (c.charAt(0) == " ") c = c.substring(1)
// If the cookie's name matches the given name
if (c == cookieName) return true
}
return false
}
// Verwendung
if (checkCookie(cookieName)) contentShown = true
</script>
{#if contentShown}
<slot />
{:else}
<div
style="display: flex;
justify-content: center;
align-items: {positions[textPosition]};
background-image: url({backgroundUrl});
background-size: cover;
width: 100%;
align-self: stretch;
flex-grow: 1;
"
>
<div style="background-color: rgba(255,255,255,0.7); padding: 20px; background: {background}; width: 100%;">
<p>Cookie ist nicht aktiviert. Bitte aktivieren Sie ihn.</p>
</div>
</div>
{/if}
<style lang="less"></style>

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import { onMount } from "svelte"
import CookieSet from "./cookieSet.svelte"
$: iframeTitle = "testrest"
let setHeight = (element) => {
element.style.height = (element.offsetWidth / 16) * 9 + "px"
}
</script>
<CookieSet cookieName="{'googleMaps'}" textPosition="{'unten'}" background="{'rgba(44, 44, 44, 0.4)'}">
<iframe
use:setHeight
id="iframe"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2510.8843160281504!2d11.046507612986247!3d50.99980984753832!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47a46d575a841fe1%3A0xd6703e9ebe1ca279!2sErfurt%20Wasserski-%20und%20Wakeboardanlage!5e0!3m2!1sde!2sde!4v1682691189533!5m2!1sde!2sde"
style="border:0;"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"></iframe>
</CookieSet>
<style>
iframe {
width: 100%;
max-width: 100%;
border: 0;
}
</style>

View File

@@ -0,0 +1,71 @@
<script lang="ts">
import DesktopHeader from "./desktop.svelte"
import MobileHeader from "./mobile.svelte"
import { navigation } from "../../stores"
</script>
<main class="headercontainer">
<nav>
<div class="mobile-header">
<MobileHeader />
</div>
<div class="desktop-header">
<DesktopHeader />
</div>
</nav>
</main>
<div class="placeholder"></div>
<style global lang="less">
@import "../../assets/css/main.less";
@desktop: ~"only screen and (min-width: 1440px)";
.ignore {
display: none !important;
visibility: hidden;
}
nav {
position: relative;
height: 100%;
width: 100%;
}
.placeholder {
height: 105px;
}
.headercontainer {
display: flex;
position: fixed;
z-index: 5500;
top: 0px;
justify-content: space-between;
width: 100%;
color: #333;
height: 105px;
}
@media @desktop {
.headercontainer,
.placeholder {
height: 120px;
}
nav {
position: initial;
}
}
@media @mobile {
.desktop-header {
display: none;
}
.mobile-header {
display: inherit;
}
}
@media @desktop {
.mobile-header {
display: none;
}
.desktop-header {
display: inherit;
}
}
</style>

View File

@@ -0,0 +1,305 @@
<script lang="ts">
import { navigation, sites } from "../../stores"
import { apiBaseURL } from "../../../config"
import { navigate } from "svelte-routing"
function changeStateOfSite(menuOn: boolean) {
let siteContainer = document.body
if (menuOn) siteContainer.style.overflow = "hidden"
else siteContainer.style.overflow = "initial"
}
async function changeSubmenu(e, i) {
changeStateOfSite(true)
let submenu = document.getElementById("submenu-container")
submenu.style.height = "calc(100vh - 120px)"
submenu.classList.add("show-submenu")
let elements = document.getElementsByClassName("innersubmenu-container")
Array.from(elements).forEach((element) => {
element.classList.remove("shown")
})
let shownMenu = document.getElementById("submenu-" + i)
shownMenu.classList.add("shown")
}
let hoverTimeout
</script>
<ul
class="menu"
on:mouseover="{(e) => {
clearTimeout(hoverTimeout)
hoverTimeout = setTimeout(() => {
let element = document.getElementById('submenu-container')
element.style.height = '0vh'
changeStateOfSite(false)
element.classList.remove('show-submenu')
let elements = document.getElementsByClassName('select-menu')
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
}, 500)
}}"
on:mouseleave="{() => {
clearTimeout(hoverTimeout)
}}"
>
<button
class="logo-container"
on:click="{() => {
let element = document.getElementById('submenu-container')
element.style.height = '0vh'
element.classList.remove('show-submenu')
changeStateOfSite(false)
navigate('/')
}}"
>
<button class="img-logo-container"><img src="media/logo.png" alt="logo" /></button>
<p class="logo-text">Wasserski-Erfurt</p>
</button>
<ul class="menuitem-container">
{#if $navigation?.elemente}
{#each $navigation.elemente as site, i (i)}
<li
class="menu-item"
on:mousedown="{() => {
if (site.endpoint) {
let element = document.getElementById('submenu-container')
element.style.height = '0vh'
element.classList.remove('show-submenu')
changeStateOfSite(false)
navigate(`${$sites[site.seite].path}`)
}
}}"
on:mouseenter|stopPropagation="{(e) => {
clearTimeout(hoverTimeout)
if (!site.endpoint) {
let target = e.currentTarget
hoverTimeout = setTimeout(() => {
changeSubmenu(target, i)
let elements = document.getElementsByClassName('select-menu')
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
target.classList.add('select-menu')
}, 500)
} else {
hoverTimeout = setTimeout(() => {
let elements = document.getElementsByClassName('select-menu')
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
let element = document.getElementById('submenu-container')
element.style.height = '0vh'
element.classList.remove('show-submenu')
changeStateOfSite(false)
}, 500)
}
}}"
on:mouseleave|stopPropagation="{(e) => {
clearTimeout(hoverTimeout)
}}"
>
{site.name}
</li>
{/each}
{/if}
</ul>
</ul>
<button
class="submenu-container"
id="submenu-container"
on:mouseover="{(e) => {
let element = e.currentTarget
element.style.height = '0vh'
changeStateOfSite(false)
element.classList.remove('show-submenu')
}}"
>
{#if $navigation?.elemente}
<div class="inner-container">
{#each $navigation?.elemente as submenu, i (i * 10)}
{#if !submenu?.endpoint}
<button
on:mouseover|stopPropagation
class="innersubmenu-container"
id="{`submenu-${i}`}"
on:click|stopPropagation
>
<div class="submenu-most-inner-container">
<div class="submenu-img">
<img
src="{`${apiBaseURL}navigation/${$navigation?.id}/${submenu.image?.src}?filter=${
window.innerWidth > 500 ? 'xl' : 'm'
}`}"
alt="img"
/>
</div>
<ul class="sub-menu">
{#each submenu?.elemente as submenu_point, i (i)}
<li>
<button
class="submenu-item"
on:click="{() => {
let element = document.getElementById('submenu-container')
element.style.height = '0vh'
element.classList.remove('show-submenu')
changeStateOfSite(false)
navigate(`${$sites[submenu_point.seite]?.path}`)
}}">{submenu_point?.name}</button
>
</li>
{/each}
</ul>
</div>
</button>
{/if}
{/each}
</div>
{/if}
</button>
<style lang="less" global>
@import "../../assets/css/variables.less";
@desktop: ~"only screen and (min-width: 1440px)";
@media @desktop {
nav {
flex-grow: 3;
.desktop-header {
margin: 0px auto 0px auto;
max-width: @body-maxwidth;
width: 100%;
}
.menu {
padding: 0px min(4.5vw, 100px);
max-width: 1800px;
width: 100%;
display: flex;
height: 120px;
align-items: center;
justify-content: space-between;
.logo-container {
height: 60px;
display: flex;
align-items: center;
.logo-text {
font-weight: bold;
font-size: 1.2rem;
padding-left: 10px;
}
.img-logo-container {
height: 100%;
img {
height: 100%;
width: auto;
object-fit: contain;
}
}
}
div {
margin-right: 10%;
}
.menuitem-container {
display: flex;
justify-content: flex-end;
align-items: center;
width: fit-content;
height: 100%;
max-width: 1400px;
margin-left: 15px;
.menu-item {
font-size: 24px;
border-radius: 60px;
padding: 3px 14px;
margin: 0px 2px;
height: fit-content;
display: flex;
align-items: center;
cursor: pointer;
&:hover {
background-color: @hover-color;
}
}
.select-menu {
background-color: @hover-color;
}
}
}
.submenu-container {
position: absolute;
left: 0px;
height: 0vh;
overflow: hidden;
width: 100vw;
z-index: 2000;
background-color: rgba(0, 0, 0, 0.854);
opacity: 0;
.inner-container {
width: 100%;
height: 100%;
position: relative;
.innersubmenu-container {
width: 100%;
height: 60vh;
max-height: 700px;
opacity: 0;
position: absolute;
visibility: hidden;
background-color: rgb(255, 255, 255);
display: flex;
justify-content: center;
.submenu-most-inner-container {
height: 100%;
width: 100%;
max-width: 1800px;
padding: 0px min(4.5vw, 100px);
display: flex;
justify-content: center;
}
.sub-menu {
display: flex;
max-width: calc(@body-maxwidth / 2 - min(3vw, 80px));
align-items: start;
padding-left: 20px;
flex-direction: column;
width: 50%;
li {
border-bottom: 1px solid #dee2e6;
width: 100%;
text-align: start;
&:hover {
border-bottom: 1px solid rgba(24, 24, 24, 0.795);
}
button {
padding: 10px 0px;
width: 100%;
height: 100%;
text-align: start;
}
}
}
.submenu-img {
max-width: calc(@body-maxwidth / 2 - min(3vw, 80px));
height: 100%;
width: 50%;
padding: 10px;
padding-right: 20px;
img {
height: 100%;
width: 100%;
object-fit: cover;
}
}
}
.shown {
opacity: 1;
visibility: visible;
}
}
}
.show-submenu {
height: 100vh;
opacity: 1;
}
}
}
</style>

View File

@@ -0,0 +1,355 @@
<script lang="ts">
import { navigation, sites } from "../../stores"
import { onMount } from "svelte"
import { apiBaseURL } from "../../../config"
import { navigate } from "svelte-routing"
let images: HTMLImageElement[] = []
function changeStateOfSite(menuOn: boolean) {
let element = document.getElementById("menu")
element.classList.toggle("show-menu")
let body = document.body
if (menuOn) {
body.style.overflow = "initial"
} else {
body.style.overflow = "hidden"
}
let button = document.getElementsByClassName("button-three")[0]
const currentState = button.getAttribute("data-state")
if (!currentState || currentState === "closed") {
button.setAttribute("data-state", "opened")
button.setAttribute("aria-expanded", "true")
} else {
button.setAttribute("data-state", "closed")
button.setAttribute("aria-expanded", "false")
}
}
function imageSlide(images) {
console.log(images)
let currentImage = 0
images[0].classList.add("show-img")
let interval = setInterval(() => {
images[currentImage].classList.remove("show-img")
currentImage += 1
if (images.length == currentImage) currentImage = 0
images[currentImage].classList.add("show-img")
}, 4000)
return () => clearInterval(interval)
}
function pushImages(node) {
images[0] = node
}
$: {
if (images.length != 0) imageSlide(document.getElementsByClassName("img-menu"))
}
</script>
<ul>
<div class="header">
<button
class="logo-container"
on:click="{() => {
navigate('/')
let element = document.getElementById('menu')
changeStateOfSite(element.classList.contains('show-menu'))
}}"
>
<button class="img-logo-container"><img src="media/logo.png" alt="logo" /></button>
<p class="logo-text">Wasserski-Erfurt</p>
</button>
<button
class="button-three"
on:click="{(e) => {
let element = document.getElementById('menu')
changeStateOfSite(element.classList.contains('show-menu'))
}}"
aria-controls="primary-navigation"
aria-expanded="false"
>
<svg stroke="var(--button-color)" fill="none" class="hamburger" viewBox="-10 -10 120 120" width="45">
<path
class="line"
stroke-width="10"
stroke-linecap="round"
stroke-linejoin="round"
d="m 20 40 h 60 a 1 1 0 0 1 0 20 h -60 a 1 1 0 0 1 0 -40 h 30 v 70"
>
</path>
</svg>
</button>
</div>
<div class="menu-container" id="menu">
{#if $navigation?.elemente}
<div class="inner-container">
<div class="higher-absolute">
{#each $navigation.elemente as link, i (i)}
<li
class="menu"
on:mousedown|stopPropagation="{(e) => {
if (link.endpoint) {
navigate(`${$sites[link.seite]?.path}`)
let element = document.getElementById('menu')
changeStateOfSite(element.classList.contains('show-menu'))
return
}
let element = e.currentTarget
element.classList.toggle('active')
let chevronContainer = document.getElementById('chevron-' + i)
chevronContainer.src =
chevronContainer.src.split('/')?.pop() == 'chevron-down.png'
? 'media/chevron-up.png'
: 'media/chevron-down.png'
}}"
>
<div class="menu-point">
<div>{link?.name}</div>
<div class:hidden="{link?.endpoint}">
<img id="{`chevron-${i}`}" src="media/chevron-down.png" alt="chev" />
</div>
</div>
{#if !link?.endpoint}
<ul class="submenu">
{#each link.elemente as submenu, i (i)}
<li>
<button
on:mousedown="{(e) => {
navigate(`${$sites[submenu.seite]?.path}`)
let element = document.getElementById('menu')
changeStateOfSite(element.classList.contains('show-menu'))
}}">{submenu.name}</button
>
</li>
{/each}
</ul>
{/if}
</li>
{/each}
<button class="socials">
<a target="_blank" href="https://www.instagram.com/wasserski_erfurt/">
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.7 3h12.6c4.8 0 8.7 3.9 8.7 8.7v12.6a8.7 8.7 0 0 1-8.7 8.7H11.7C6.9 33 3 29.1 3 24.3V11.7A8.7 8.7 0 0 1 11.7 3zm-.3 3A5.4 5.4 0 0 0 6 11.4v13.2c0 2.985 2.415 5.4 5.4 5.4h13.2a5.4 5.4 0 0 0 5.4-5.4V11.4C30 8.415 27.585 6 24.6 6H11.4zm14.475 2.25a1.875 1.875 0 1 1 0 3.75 1.875 1.875 0 0 1 0-3.75zM18 10.5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15zm0 3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"
fill="#fff"></path>
</svg>
</a>
<a target="_blank" href="https://www.facebook.com/wasserskierfurt/">
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18 3.06c-8.25 0-15 6.735-15 15.03 0 7.5 5.49 13.725 12.66 14.85v-10.5h-3.81v-4.35h3.81v-3.315c0-3.765 2.235-5.835 5.67-5.835 1.635 0 3.345.285 3.345.285v3.705h-1.89c-1.86 0-2.445 1.155-2.445 2.34v2.82h4.17l-.675 4.35H20.34v10.5A15 15 0 0 0 33 18.09c0-8.295-6.75-15.03-15-15.03z"
fill="#fff"></path>
</svg>
</a>
</button>
</div>
<div class="img-container">
<div class="img-relative">
{#each $navigation.elemente?.map((e) => e.image?.src) as imgSrc, i (i)}
{#if imgSrc != undefined}
<div>
<img
use:pushImages
src="{`${apiBaseURL}navigation/${$navigation.id}/${imgSrc}?filter=${
window.innerWidth > 500 ? 'xl' : 'm'
}`}"
alt="img"
class="img img-menu"
/>
</div>
{/if}
{/each}
</div>
</div>
</div>
{/if}
</div>
</ul>
<style lang="less" global>
@import "../../assets/css/variables.less";
@desktop: ~"only screen and (min-width: 1440px)";
@media @tablet {
.socials {
display: none;
}
}
@media @mobile {
nav {
.hidden {
visibility: hidden;
}
position: relative;
width: 100%;
height: 100vh;
background-color: white;
ul {
.header {
padding: 0px min(4.5vw, 100px);
display: flex;
align-items: center;
justify-content: space-between;
height: 105px;
.button-three {
--button-color: #333;
overflow: hidden;
background: transparent;
}
.button-three .hamburger {
transition: translate 400ms, rotate 400ms;
}
.button-three[aria-expanded="true"] .hamburger {
translate: 1px -1px;
rotate: 0.125turn;
}
.button-three .line {
transition: 1s;
stroke-dasharray: 60 31 60 300;
}
.button-three[aria-expanded="true"] .line {
stroke-dasharray: 60 105 60 300;
stroke-dashoffset: -90;
}
.logo-container {
height: 50px;
display: flex;
align-items: center;
.logo-text {
font-weight: bold;
font-size: 1.2rem;
padding-left: 10px;
color: #333;
}
.img-logo-container {
height: 100%;
img {
height: 100%;
width: auto;
object-fit: contain;
}
}
}
}
.img-container {
position: absolute;
bottom: 5px;
width: 100%;
left: 0px;
height: calc((105vw / 16) * 9);
padding: 0px min(4.5vw, 100px);
.img-relative {
position: relative;
height: 100%;
width: 100%;
div {
position: absolute;
height: 100%;
width: 100%;
.show-img {
visibility: visible !important;
opacity: 1;
}
img {
opacity: 0;
height: 100%;
width: 100%;
object-fit: cover;
}
}
}
}
.menu-container {
background-color: white;
position: absolute;
z-index: 2000;
opacity: 0;
top: 105px;
height: calc(100vh - 105px);
width: 100%;
left: -100vw;
overflow: scroll;
.inner-container {
position: relative;
height: 100%;
.menu {
padding: 10px;
border-radius: 10px;
}
.higher-absolute {
position: absolute;
z-index: 2000;
width: 100%;
left: 0px;
padding: 0px min(4.5vw, 100px);
background-color: white;
border-radius: 0px 0px 10px 10px;
}
.socials {
width: 100%;
background-color: @link-font-color;
height: 50px;
border-radius: 20px;
color: white;
}
.active {
background-color: rgba(128, 128, 128, 0.153) !important;
.submenu {
visibility: visible;
max-height: 250px;
}
}
li {
padding: 6px 0px;
margin: 2px 0px;
margin-left: 5px !important;
button {
height: 100%;
width: 100%;
text-align: start;
}
.menu-point {
display: flex;
justify-content: space-between;
}
div {
font-weight: bold;
}
.submenu {
visibility: hidden;
max-height: 0px;
overflow: hidden;
}
}
}
}
.show-menu {
left: 0vw;
opacity: 1;
}
}
}
}
</style>

View File

@@ -0,0 +1,148 @@
<script lang="ts">
import { onMount, onDestroy } from "svelte"
import { banner } from "../../stores"
let isExpanded = false
let currentIndex = 0
let interval
let img: HTMLImageElement
function toggleBanner() {
isExpanded = !isExpanded
img.src = img.src.includes("information") ? "media/close-circle.png" : "media/information.svg"
}
onMount(() => {
isExpanded = true
interval = setInterval(() => {
currentIndex = (currentIndex + 1) % $banner.length
}, 7000)
return () => clearInterval(interval)
})
</script>
{#if $banner[0] != undefined}
<div class="banner" class:expanded="{isExpanded}">
<div class="banner-container">
<div class="banner-text" class:visible="{isExpanded}">
{$banner[currentIndex]}
</div>
<button class="toggle" on:click="{() => toggleBanner()}">
<img src="media/close-circle.png" alt="info" bind:this="{img}" />
</button>
</div>
</div>
{/if}
<style lang="less">
@import "../../assets/css/variables.less";
* {
transition: all 0.9s;
}
@keyframes opacityText {
0%,
100% {
opacity: 0.3;
}
20%,
50%,
80% {
opacity: 1;
}
}
.banner-text {
animation: opacityText;
animation-duration: 7000ms;
animation-iteration-count: infinite;
visibility: hidden;
}
@media @mobile {
.banner {
width: 100vw;
height: 0px;
.banner-text {
line-height: 90%;
width: 100%;
}
&.expanded {
height: 80px;
}
}
.toggle {
position: absolute;
left: 50%;
background-color: @banner-color;
transform: translate(-50%, -100%);
border-radius: 10px;
}
}
@media @tablet {
.banner {
height: 60px;
width: 60px;
.banner-text {
width: 0px;
}
&.expanded {
height: 60px;
width: 80vw;
}
}
.toggle {
position: relative;
transform: translate(0%, 0%);
left: 0px;
border-radius: 0px;
}
}
.banner {
position: fixed;
border-radius: 0px 5px 0px 0px;
z-index: 4000;
bottom: 0;
left: 0;
right: 0;
background-color: @banner-color;
cursor: pointer;
transition: width 0.5s ease-in-out, height 0.5s ease-in-out;
img {
transform: scale(0.9);
}
}
.banner.expanded {
}
.banner-container {
width: 100%;
height: 100%;
padding: 10px;
display: flex;
justify-content: space-between;
position: relative;
color: white;
.toggle {
padding: 10px;
}
.banner-text {
color: white;
transition: opacity 0.3s ease-in-out;
pointer-events: none;
opacity: 0;
display: flex;
align-items: center;
justify-content: center;
}
.banner-text.visible {
flex: 1;
padding: 10px;
visibility: visible;
}
}
</style>

View File

@@ -0,0 +1,160 @@
<script lang="ts">
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
export let formRow: FormRow
export let index: number
export let formValues
function getSortedFields(column: FormColumn) {
const fields = [
...(column.text.length ? [{ text: column.text, type: "text", order: column.textfieldOrder ?? 3 }] : []),
...(column.showTimes ? [{ type: "times", order: column.timesfieldOrder ?? 3, times: column.times }] : []),
...(column.showDate
? [{ type: "date", order: column.datefieldOrder ?? 3, datePlaceholder: column.datePlaceholder }]
: []),
]
return fields.sort((a, b) => a.order - b.order)
}
//formRow.columns = formRow.columns.map((e) => getSortedFields(e))
function removeInvalid(e) {
let element = e.currentTarget
element.classList.remove("invalid")
}
</script>
<div class="form-row">
<div class="form-cols">
{#each formRow.columns as column, columnIndex}
<div class="form-column">
<h3>{column?.title ?? ""}</h3>
{#if column?.annotation}
<p>{column?.annotation}</p>
{/if}
{#if column.showLabelNumber}
<FormLabelNumberBlock column="{column}" formValues="{formValues}" rowIndex="{index}" />
{/if}
{#if column?.showTimes}
<label bind:this="{$formValues[`times_${column?.title ? column.title + '_' : ''}label`]}">
<select
id="time-select"
bind:this="{$formValues[
`times_${column?.title ?? 'Zeiten'}_${column.timesfieldOrder}_${index}_${
column.emailNameTimes || columnIndex + 'invalidtimes'
}`
]}"
required="{column?.timeNotRequired !== true}"
on:change="{removeInvalid}"
>
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
{#each column?.times as time}
<option value="{time?.timeFrom}-{time?.timeTo}">
{time?.timeFrom} - {time?.timeTo}
</option>
{/each}
</select>
</label>
{/if}
{#if column?.showSelect}
<label bind:this="{$formValues[`select_${column?.title ? column.title + '_' : ''}label`]}">
<select
required="{column?.dateSelectNotRequired !== true}"
bind:this="{$formValues[
`select_${column?.title ?? 'Auswahl'}_${column.datefieldOrder}_${index}_${
column?.emailNameTime || columnIndex + 'invalidtime'
}`
]}"
on:change="{removeInvalid}"
>
<option value="" disabled selected>{column.selectTitle}</option>
{#each column?.selectEntries as entry}
<option value="{entry?.leftSide}-{entry?.rightSide}">
{entry?.leftSide}-{entry?.rightSide}
</option>
{/each}
</select>
</label>
{/if}
{#if column.showDate}
<label bind:this="{$formValues[`date_${column?.title ? column.title + '_' : ''}label`]}">
<input
class="date"
type="date"
required="{column?.dateNotRequired !== true}"
on:change="{removeInvalid}"
bind:this="{$formValues[
`date_${column?.title ?? 'Datum'}_${column.datefieldOrder}_${index}_${
column?.emailNameDate || columnIndex + 'invaliddate'
}`
]}"
/>
</label>
{/if}
{#if column.showNumber}
<label
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${column?.numberPlaceholder}_label`
]}"
>
<input
type="number"
step="any"
required="{column?.numberNotRequired !== true}"
on:change="{removeInvalid}"
placeholder="{column?.numberPlaceholder}"
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${column?.numberPlaceholder}_${
column.numberfieldOrder
}_${index}_${column?.emailNameNumber || columnIndex + 'invalidnumber'}`
]}"
/>
</label>
{/if}
{#each column.text as textField, textFieldIndex}
{#if textField?.textArea}
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
<textarea
placeholder="{textField?.textPlaceholder}"
required="{textField?.notRequired !== true}"
on:change="{removeInvalid}"
bind:this="{$formValues[
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
}`
]}"></textarea>
</label>
{:else}
<label
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
]}"
>
<input
type="text"
placeholder="{textField?.textPlaceholder}"
on:change="{removeInvalid}"
required="{textField?.notRequired !== true}"
bind:this="{$formValues[
`${
textField?.telValidation
? 'Telefon'
: textField?.emailValidation
? 'Email'
: 'input'
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
textField.textfieldOrder
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
]}"
/>
</label>
{/if}
{/each}
</div>
{/each}
</div>
</div>
<style lang="less">
</style>

View File

@@ -0,0 +1,63 @@
<script lang="ts">
export let column
export let formValues
export let rowIndex
let blockContainer
$formValues["blockGroups"] = new Set(column.labelNumber.map((e) => e.group))
console.log($formValues["blockGroups"])
</script>
<div class="blockContainer" bind:this="{blockContainer}">
{#each column.labelNumber as outerblock, i}
<div class="{`block`}" bind:this="{$formValues['blockGroups'][i]}">
<h3>{outerblock.title}</h3>
<div class="innterBlockContainer">
{#each outerblock.block as innerBlock}
<div class="innerBlock">
<div class="label">{innerBlock.label}</div>
<input
placeholder="0"
on:change="{(e) => {
let element = e.currentTarget
element.classList.remove('border-red')
blockContainer.classList.remove('invalidBlocks')
}}"
type="number"
name="{outerblock.group}"
class="{`group-${outerblock.group}`}"
bind:this="{$formValues[
`numberLabel_${outerblock.title ?? ''}_${innerBlock.label}_${rowIndex}_${
innerBlock.emailName
}`
]}"
/>
</div>
{/each}
</div>
</div>
{/each}
</div>
<style lang="less">
.block {
width: 100%;
padding: 25px 0px;
h3 {
margin-bottom: 0px;
}
.innerBlock {
width: 100%;
display: flex;
justify-content: space-between;
.label {
display: flex;
align-items: flex-end;
}
input {
text-align: center;
width: 80px;
font-size: 1rem;
}
}
}
</style>

View File

@@ -0,0 +1,311 @@
<script lang="ts">
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
export let formRow: FormRow
export let formValues
export let index
function removeInvalid(e) {
let element = e.currentTarget
element.classList.remove("invalid")
}
function getPosition(column, pos, i = 0) {
let position = 0
if (pos == 0) return
if (column.showLabelNumber) position++
if (pos == 1) return position
if (column.showTimes) position++
if (pos == 2) return position
if (column.showSelect) position++
if (pos == 3) return position
if (column.showDate) position++
if (pos == 4) return position
if (column.showNumber) position++
return position + i
}
</script>
<div class="form-row">
<div class="form-cols mobile-fields">
{#each formRow.columns as column, columnIndex}
<h3>{column?.title ?? ""}</h3>
{#if column?.annotation}
<p>{column?.annotation}</p>
{/if}
{#if column.showLabelNumber}
<div class="{`column-${columnIndex} position-${getPosition(column, 0)}`}">
<FormLabelNumberBlock column="{column}" formValues="{formValues}" rowIndex="{index}" />
</div>
{/if}
{#if column?.showTimes}
<div class="column-{columnIndex} position-{getPosition(column, 1)}">
<label bind:this="{$formValues[`times_${column?.title ? column.title + '_' : ''}label`]}">
<select
id="time-select"
bind:this="{$formValues[
`times_${column?.title ?? 'Zeiten'}_${column.timesfieldOrder}_${index}_${
column.emailNameTimes || columnIndex + 'invalidtimes'
}`
]}"
required="{column?.timeNotRequired !== true}"
on:change="{removeInvalid}"
>
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
{#each column?.times as time}
<option value="{time?.timeFrom}-{time?.timeTo}">
{time?.timeFrom} - {time?.timeTo}
</option>
{/each}
</select>
</label>
</div>
{/if}
{#if column?.showSelect}
<div class="column-{columnIndex} position-{getPosition(column, 2)}">
<label bind:this="{$formValues[`select_${column?.title ? column.title + '_' : ''}label`]}">
<select
required="{column?.dateNotRequired !== true}"
bind:this="{$formValues[
`select_${column?.title ?? 'Auswahl'}_${column.datefieldOrder}_${index}_${
column?.emailNameTime || columnIndex + 'invalidtime'
}`
]}"
on:change="{removeInvalid}"
>
<option value="" disabled selected>{column.selectTitle}</option>
{#each column?.selectEntries as entry}
<option value="{entry?.leftSide}-{entry?.rightSide}">
{entry?.leftSide}-{entry?.rightSide}
</option>
{/each}
</select>
</label>
</div>
{/if}
{#if column.showDate}
<div class="column-{columnIndex} position-{getPosition(column, 3)}">
<label bind:this="{$formValues[`date_${column?.title ? column.title + '_' : ''}label`]}">
<input
class="date"
type="date"
required="{column?.dateNotRequired !== true}"
on:change="{removeInvalid}"
bind:this="{$formValues[
`date_${column?.title ?? 'Datum'}_${column.datefieldOrder}_${index}_${
column?.emailNameDate || columnIndex + 'invaliddate'
}`
]}"
/>
</label>
</div>
{/if}
{#if column.showNumber}
<div class=" column-{columnIndex} position-{getPosition(column, 4)}">
<label
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${column?.numberPlaceholder}_label`
]}"
>
<input
type="number"
step="any"
required="{column?.numberNotRequired !== true}"
on:change="{removeInvalid}"
placeholder="{column?.numberPlaceholder}"
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${column?.numberPlaceholder}_${
column.numberfieldOrder
}_${index}_${column?.emailNameNumber || columnIndex + 'invalidnumber'}`
]}"
/>
</label>
</div>
{/if}
{#each column.text as textField, textFieldIndex}
<div class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}">
{#if textField?.textArea}
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
<textarea
placeholder="{textField?.textPlaceholder}"
required="{textField?.notRequired !== true}"
on:change="{removeInvalid}"
bind:this="{$formValues[
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
}`
]}"></textarea>
</label>
{:else}
<label
bind:this="{$formValues[
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
]}"
>
<input
type="text"
placeholder="{textField?.textPlaceholder}"
on:change="{removeInvalid}"
required="{textField?.notRequired !== true}"
bind:this="{$formValues[
`${
textField?.telValidation
? 'Telefon'
: textField?.emailValidation
? 'Email'
: 'input'
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
textField.textfieldOrder
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
]}"
/>
</label>
{/if}
</div>
{/each}
{/each}
</div>
</div>
<style lang="less">
.mobile-fields {
display: flex;
flex-direction: column;
}
.form-field {
order: 1;
}
/* Order for first column */
.column-0.position-0 {
order: 1;
}
.column-0.position-1 {
order: 5;
}
.column-0.position-2 {
order: 9;
}
.column-0.position-3 {
order: 13;
}
.column-0.position-4 {
order: 17;
}
.column-0.position-5 {
order: 21;
}
.column-0.position-6 {
order: 25;
}
.column-0.position-7 {
order: 29;
}
.column-0.position-8 {
order: 33;
}
.column-0.position-9 {
order: 37;
}
/* Order for second column */
.column-1.position-0 {
order: 2;
}
.column-1.position-1 {
order: 6;
}
.column-1.position-2 {
order: 10;
}
.column-1.position-3 {
order: 14;
}
.column-1.position-4 {
order: 18;
}
.column-1.position-5 {
order: 22;
}
.column-1.position-6 {
order: 26;
}
.column-1.position-7 {
order: 30;
}
.column-1.position-8 {
order: 34;
}
.column-1.position-9 {
order: 38;
}
/* Order for third column */
.column-2.position-0 {
order: 3;
}
.column-2.position-1 {
order: 7;
}
.column-2.position-2 {
order: 11;
}
.column-2.position-3 {
order: 15;
}
.column-2.position-4 {
order: 19;
}
.column-2.position-5 {
order: 23;
}
.column-2.position-6 {
order: 27;
}
.column-2.position-7 {
order: 31;
}
.column-2.position-8 {
order: 35;
}
.column-2.position-9 {
order: 39;
}
/* Order for fourth column */
.column-3.position-0 {
order: 4;
}
.column-3.position-1 {
order: 8;
}
.column-3.position-2 {
order: 12;
}
.column-3.position-3 {
order: 16;
}
.column-3.position-4 {
order: 20;
}
.column-3.position-5 {
order: 24;
}
.column-3.position-6 {
order: 28;
}
.column-3.position-7 {
order: 32;
}
.column-3.position-8 {
order: 36;
}
.column-3.position-9 {
order: 40;
}
</style>

View File

@@ -0,0 +1,93 @@
<script lang="ts">
import { navigate } from "svelte-routing"
import { fly } from "svelte/transition"
export let col: Column
export let siteId
import { apiBaseURL } from "../../../config"
import inView from "../../functions/observer"
let visible = false
let node
</script>
<main>
<div
class="wrapper"
bind:this="{node}"
use:inView="{{ threshold: 0 }}"
on:enter="{() => {
visible = true
}}"
>
{#key visible}
{#each col.iconBoard as icon, i (i)}
<div
class="img-container"
id="{'img-container' + i}"
in:fly="{{ duration: 1000, delay: i * 150, y: 130, opacity: 0 }}"
>
<img alt="icon" src="{`${apiBaseURL}content/${siteId}/${icon.icon?.src}`}" class="icon" />
<div class="subText">{icon?.subText}</div>
</div>
{/each}
{/key}
</div>
</main>
<style lang="less">
@import "../../assets/css/variables.less";
main {
display: flex;
max-width: @body-small-maxwidth;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
width: 100%;
padding: 15px;
.wrapper {
width: 100%;
min-height: 400px;
margin-top: 75px;
display: flex;
justify-content: start;
align-items: center;
flex-wrap: wrap;
@media @mobile {
margin-top: 10px;
}
@media @tablet {
margin-top: 40px;
}
.img-container {
display: flex;
margin: 15px 0px;
flex-direction: column;
align-items: center;
min-width: 25%;
.subText {
text-align: center;
color: @heading-font-color;
}
@media @mobile {
width: 50%;
}
@media @tablet {
width: auto;
}
}
}
@media @tablet {
main {
margin-top: 300px !important;
}
.background-container {
margin-top: -180px !important;
}
.title {
font-size: 3rem !important;
}
}
}
</style>

View File

@@ -0,0 +1,104 @@
<script lang="ts">
import { onMount } from "svelte"
import { register } from "swiper/element/bundle"
import Pagebuilder from "./Pagebuilder.svelte"
import { apiBaseURL } from "../../../config"
export let siteId
export let siteImages
register(false)
let swiper
onMount(async () => {
if (swiper !== undefined) {
const response = await fetch("/dist/index.css")
const cssText = await response.text()
const params = {
injectStyles: [cssText],
}
Object.assign(swiper, params)
swiper.initialize()
}
})
let image = siteImages[0]
</script>
{#if siteImages.length > 1}
<div class="flex">
<swiper-container
bind:this="{swiper}"
slides-per-view="1"
loop="{true}"
direction="horizontal"
effect="slide"
autoplay-delay="2500"
mousewheel="{true}"
navigation="{true}"
init="{false}"
speed="600"
class="relative"
>
{#each siteImages as image, i (i)}
<swiper-slide class="relative">
<div class="image-container">
<img
src="{`${apiBaseURL}content/${siteId}/${image.image?.src}?filter=${
window.innerWidth > 500 ? 'xl' : 'm'
}`}"
alt="Bild"
/>
</div>
</swiper-slide>
{/each}
</swiper-container>
</div>
{:else if image}
<div class="image-container single flex">
<img
src="{`${apiBaseURL}content/${siteId}/${image.image?.src}?filter=${window.innerWidth > 500 ? 'xl' : 'm'}`}"
alt="Bild"
/>
</div>
{/if}
<style lang="less" global>
@import "swiper/swiper.less";
@import "swiper/modules/effect-fade/effect-fade.less";
@import "swiper/modules/navigation/navigation.less";
@import "swiper/modules/pagination/pagination.less";
@import "../../assets/css/variables.less";
@import "../../assets/css/swiperStyles.less";
swiper-container {
height: auto;
width: 100%;
}
swiper-slide {
width: 100% !important;
}
.flex {
flex: 2 !important;
}
.image-container {
max-width: 100%;
width: 100%;
overflow: hidden;
max-width: @body-maxwidth;
&:hover img {
transform: scale(1.05);
transform-origin: center;
}
img {
width: 100%;
height: auto;
object-fit: cover;
}
}
.single {
max-width: @body-small-maxwidth;
}
</style>

View File

@@ -0,0 +1,90 @@
<script lang="ts">
import { navigate } from "svelte-routing"
import { fly } from "svelte/transition"
export let col: Column
export let siteId
export let i
import { apiBaseURL } from "../../../config"
import inView from "../../functions/observer"
let visible
let node
</script>
{#key visible}
<main
bind:this="{node}"
use:inView="{{ threshold: 0 }}"
on:enter="{() => {
visible = true
}}"
in:fly="{{ duration: 600, delay: 100 + 100 * (i + 1), x: -300 - i * 200, opacity: 0 }}"
>
<div class="img-container">
<img
src="{`${apiBaseURL}content/${siteId}/${col.image?.src}?filter=${
window.innerWidth > 500 ? 'xl' : 'm'
}`}"
alt="img"
/>
</div>
<div class="title-container">
{@html col?.title}
</div>
<div class="description-container">
{@html col?.text}
</div>
<div class="links">
{#if col?.links}
{#each col?.links as link}
<button on:click="{() => navigate(link?.site)}">
<img src="media/arrow-right.svg" alt="arrow" />{link?.name}
</button>
{/each}
{/if}
</div>
</main>
{/key}
<style lang="less">
@import "../../assets/css/variables.less";
main {
flex: 1;
max-width: @body-small-maxwidth;
.img-container {
width: 100%;
height: 270px;
@media @tablet {
height: 65vw;
}
@media @desktop {
height: 270px;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
padding: 1rem 0px;
}
}
.title-container {
font-weight: 700;
padding-bottom: 1.2rem;
}
.description-container {
}
.links {
margin-top: 25px;
img {
transform: scale(1.4);
margin: 0.5rem 0.9rem 0.5rem 0.4rem;
}
button {
display: flex;
align-items: center;
color: @link-font-color;
font-weight: 600;
margin: 10px 0px;
}
}
}
</style>

View File

@@ -0,0 +1,57 @@
<script lang="ts">
import { fly } from "svelte/transition"
export let col: Column
export let siteId
import { apiBaseURL } from "../../../config"
</script>
<div class="mainPicture">
<div class="imgContainer">
<img
src="{`${apiBaseURL}content/${siteId}/${col.mainPicture?.src}?filter=${
window.innerWidth > 500 ? 'xl' : 'm'
}`}"
alt="img"
/>
</div>
<div class="inscription" in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">
{col.inscription}
</div>
</div>
<style lang="less">
@import "../../assets/css/variables.less";
.mainPicture {
max-width: @body-maxwidth;
position: relative;
height: 100%;
line-height: normal;
flex-grow: 2;
width: 100%;
.imgContainer {
width: 100%;
img {
width: 100%;
height: auto;
object-fit: contain;
}
}
.inscription {
position: absolute;
bottom: 35px;
left: 35px;
margin-right: 35px;
font-size: 1.7rem;
font-weight: 700;
color: white;
}
@media @tablet {
.inscription {
bottom: 35px;
left: 35px;
font-size: 2.7rem;
}
}
}
</style>

View File

@@ -0,0 +1,619 @@
<script lang="ts">
export let row: Row
export let rows: Row[]
import { apiBaseURL } from "../../../config"
import IconBoard from "./iconBoard.svelte"
import Image from "./image.svelte"
import InfoBoard from "./infoBoard.svelte"
import MainPicture from "./mainPicture.svelte"
import TextContent from "./textContent.svelte"
import Table from "./table.svelte"
import Form from "./form/form.svelte"
import MobileForm from "./form/mobileForm.svelte"
import { writable } from "svelte/store"
import { validateFields } from "../../functions/validateFields"
import { sendForm } from "../../functions/sendForm"
import VideoSwitch from "../videoSwitch.svelte"
import GoogleMaps from "../googleMaps.svelte"
import Video from "./video.svelte"
import { navigate } from "svelte-routing"
import { onMount } from "svelte"
export let siteId
export let rowNr
let formSend = false
let formValues = writable({})
function getRowClass(row) {
if (row.maxWidth || row.column.some((col) => col.iconBackgroundImage)) return "max-width"
return row.column.some((col) => col.contentType === "mainPicture" || col.contentType == "video")
? "max-width"
: "small-max-width"
}
function submitForm(e) {
const values = Object.entries($formValues).map((entry) => {
return [
entry[0],
!entry[0].includes("numberLabel")
? [entry[1].checked || entry[1].value, entry[1].required]
: [entry[1].value, entry[1], entry[1].getAttribute("name"), entry[1].required],
]
})
const fields = values.filter((entry) => !entry[0].includes("label"))
console.log(fields)
const validation = validateFields([...fields])
if (validation.length) {
validation.forEach((error) => {
if (error[0].includes("block")) {
error[1]()
} else {
$formValues[error[1]].classList.add("invalid")
const label = $formValues[`${error[1]}_label`]
const errorElement = document.createElement("div")
errorElement.className = "error-message"
errorElement.textContent = error[0]
label?.appendChild(errorElement)
}
})
} else {
const formObj = {}
fields.forEach((entry) => {
if (Array.isArray(entry[1]) && entry[1].length == 4) {
if (entry[1][0]) formObj[entry[0]] = entry[1]
} else {
if (!entry[1][0] && !entry[1][1]) return
formObj[entry[0]] = entry[1][0]
}
})
console.log(fields, formObj)
let form
row.column.forEach((col) => {
if (col.contentType == "form") form = col
})
formObj["formRows"] = form.formRows.map((r) => r.rowName)
formObj["formTitle"] = form.formEmailTitle
formSend = true
const hny = document.getElementById("hny")
formObj["honey"] = hny.checked
sendForm(formObj)
}
}
let videoElement
onMount(() => {
if (videoElement) {
var source = document.createElement("source")
if (window.innerWidth <= 767) {
source.src = "media/wasser_mobile.webm"
} else {
source.src = "media/wasser_desktop.webm"
}
videoElement.appendChild(source)
videoElement.load()
}
const handleResize = () => {
innerWidth = window.innerWidth
if (
(window.innerWidth >= 768 && innerWidthStore < 768) ||
(window.innerWidth < 768 && innerWidthStore >= 768)
) {
innerWidthStore = window.innerWidth
window.location.reload()
}
}
window.addEventListener("resize", handleResize)
// Cleanup function
return () => {
window.removeEventListener("resize", handleResize)
}
})
let innerWidth = window.innerWidth
let innerWidthStore = window.innerWidth
</script>
<main class="row" name="{row.title}" class:max-width="{getRowClass(row) === 'max-width'}" id="{`RowNr` + rowNr}">
{#if row?.iconBackgroundImage}
<div class="virtual-container">
<div class="wavebackground-container">
{#if row?.iconBackgroundTitle} <div class="title">Highlights des Sees</div>{/if}
<video class="video-background" autoplay loop muted playsinline bind:this="{videoElement}"> </video>
</div>
</div>
{/if}
{#if row.iconBackgroundImage}
<div class="wave-placeholder"></div>
{/if}
{#if row.title || row.iconBackgroundImage}
<h3 class="row-title" class:no-margin="{rowNr == 0 || row.iconBackgroundImage}">{row?.title || ""}</h3>
{/if}
<div class:no-gap="{row.noGap}">
{#each row.column as col, i}
{#if col.contentType == "mainPicture"}
<MainPicture col="{col}" siteId="{siteId}" />
{:else if col.contentType == "text"}
<TextContent rows="{rows}" col="{col}" />
{:else if col.contentType == "infoBoard"}
<InfoBoard siteId="{siteId}" col="{col}" i="{i}" />
{:else if col.contentType == "iconBoard"}
<IconBoard col="{col}" siteId="{siteId}" i="{i}" />
{:else if col.contentType == "image"}
<Image siteImages="{col.imageSlider}" siteId="{siteId}" />
{:else if col.contentType == "table"}
<Table col="{col}" rows="{rows}" />
{:else if col.contentType == "videos"}
<VideoSwitch col="{col}" siteId="{siteId}" />
{:else if col.contentType == "video"}
<Video col="{col}" siteId="{siteId}" />
{:else if col.contentType == "googleMaps"}{#if col.showGoogleMaps}
<GoogleMaps />
{/if}
{:else if col.contentType == "form"}
{#if formSend}
<div class="success-message">
<h1>Formular erfolgreich gesendet!</h1>
<p>Vielen Dank für Ihre Anfrage. Wir werden uns in Kürze bei Ihnen melden.</p>
</div>
{:else}
<form
class="form-rows"
on:submit="{(e) => {
e.preventDefault()
submitForm(e)
}}"
>
{#each col.formRows as formRow, i}
{#if innerWidth < 768}
<MobileForm formRow="{formRow}" formValues="{formValues}" index="{i}" />
{:else}
<Form formRow="{formRow}" formValues="{formValues}" index="{i}" />
{/if}
{/each}
<div class="row additional">
<div class="data-protection">
<label bind:this="{$formValues[`agreement_label`]}">
<input
required="{true}"
class="checkit"
type="checkbox"
on:change="{(e) => {
let element = e.currentTarget
element.classList.remove('invalid')
}}"
bind:this="{$formValues['agreement']}"
/>
<span class="checkit-span"></span>
</label>
<div class="datasec">
<button on:click|preventDefault="{() => navigate('/datenschutz')}" class="link">
Datenschutz
</button>
akzeptieren
</div>
</div>
<input
type="checkbox"
name="contact_me_by_fax_only"
id="hny"
value="1"
style="display:none !important"
tabindex="-1"
autocomplete="off"
/>
<button class="submit-request" type="submit">Anfrage absenden</button>
</div>
</form>
{/if}
{/if}
{/each}
</div>
</main>
<style lang="less" global>
@import "../../assets/css/variables.less";
.wave-placeholder {
height: 10px;
}
input,
select,
textarea,
.data-protection {
margin: 5px 0px;
box-shadow: 0 0 25px 10px rgba(0, 0, 0, 0.05);
}
.virtual-container {
display: flex;
padding-top: 90px;
max-width: @body-small-maxwidth;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
width: 100%;
.wavebackground-container {
position: absolute;
overflow: hidden;
display: flex;
justify-content: center;
width: 100vw;
left: 0px;
height: 450px;
z-index: -1;
.video-background {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
-webkit-mask-image: url("../../../../media/welle.svg");
mask-image: url("../../../../media/welle.svg");
-webkit-mask-size: 30px;
mask-size: 30px;
-webkit-mask-repeat: repeat-x;
mask-repeat: repeat-x;
z-index: -1;
}
@media @mobile {
.title {
margin-top: 40px;
}
}
@media @tablet {
.title {
margin-top: 75px;
}
}
.title {
font-size: 2rem;
color: white;
font-weight: bold;
}
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, rgb(255, 255, 255), rgba(255, 255, 255, 0.144));
z-index: 10;
}
}
}
.success-message {
h1 {
color: @banner-color;
font-size: 36px;
margin-top: 50px;
}
p {
font-size: 20px;
margin-top: 20px;
}
}
.invalidBlocks {
border: 2px solid rgb(255, 0, 0) !important;
position: relative;
&::after {
font-size: 0.9rem !important;
color: red !important;
position: absolute;
bottom: 2px;
content: "Bitte wähle entweder eine Kartenanzahl oder einen Wunschbetrag aus.";
}
}
.border-red {
border-color: red !important;
}
li {
}
.row-title {
font-size: 1.6rem;
font-weight: bold;
line-height: normal;
width: 100%;
color: @heading-font-color;
@media @mobile {
margin: 3.2rem 1.5vw 1.6rem;
}
@media @desktop {
margin: 6rem 0vw 1.6rem 0vw;
}
}
.no-margin {
margin-top: 15px !important;
}
.invalid {
border-bottom: 2px solid red !important;
}
.error-message {
font-size: 0.9rem !important;
color: red !important;
position: absolute;
}
.row {
width: 100%;
padding: 0px 0px 15px 0;
display: flex;
flex-direction: column;
align-items: center;
max-width: @body-small-maxwidth;
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
height: 100%;
}
input[type="number"] {
-moz-appearance: textfield;
}
ul {
list-style-type: none; /* Remove default bullet points */
padding: 0;
li {
padding-left: 1.5em; /* Add padding to the left of the list items */
position: relative;
}
li::before {
content: ""; /* Add an empty content */
background-image: url("../../../../media/arrow-right.svg"); /* Replace this with the path to your SVG file */
background-size: contain;
background-repeat: no-repeat;
position: absolute;
left: 0; /* Position the SVG at the beginning of the list item */
width: 1em; /* Adjust the width of the SVG */
height: 1em; /* Adjust the height of the SVG */
top: 0.2em; /* Adjust the vertical alignment of the SVG */
}
}
& > div {
width: 100%;
}
& > h3 {
width: 100%;
}
.checkit {
display: none;
}
.checkit-span {
height: 20px;
width: 20px;
border: 1px solid grey;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
[type="checkbox"]:checked + span:before {
content: "\2714";
position: absolute;
transform-origin: bottom;
}
&.additional {
display: flex;
@media @mobile {
flex-direction: column;
}
@media @tablet {
flex-direction: row;
}
gap: 2.5rem;
div {
flex: 1;
display: flex;
align-items: center;
justify-content: start;
}
.submit-request {
flex: 1;
box-shadow: 0 0 25px 10px rgba(0, 0, 0, 0.05);
width: 100%;
display: flex;
align-items: center;
justify-content: start;
background-color: @heading-font-color;
color: white;
padding: 10px 20px;
}
}
.form-rows {
display: flex;
flex-direction: column;
gap: 1.5rem;
width: 100%;
h3 {
font-weight: bold !important;
}
.form-row {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.5rem;
.date {
max-width: 100%;
box-sizing: border-box;
}
label {
width: 100% !important;
font-size: inherit;
input,
select,
textarea {
width: 100%;
font-size: inherit;
}
}
.form-cols {
display: flex;
gap: 1.5rem;
width: 100%;
}
}
.form-column {
display: flex;
flex: 1;
flex-direction: column;
justify-content: flex-end;
gap: 1rem;
border-radius: 4px;
}
h3 {
margin-bottom: 0.5rem;
font-size: 1.2rem;
font-weight: bold;
}
p {
margin-bottom: 0.5rem;
color: #777;
}
input,
select,
textarea,
.data-protection {
padding: 10px 20px;
border: 0px solid black;
border-bottom: 3px solid @heading-font-color;
outline: 0px solid black;
background-color: white;
resize: none;
}
.data-protection {
display: flex;
flex-wrap: nowrap;
gap: 5px !important;
justify-content: start;
flex-direction: row !important;
}
input[type="date"] {
font-family: inherit;
width: 100% !important;
position: relative;
}
select {
padding: 10px 20px;
border: 0;
border-bottom: 3px solid @heading-font-color;
outline: none;
}
select:focus {
border-bottom-color: @heading-font-color;
}
#time-select {
appearance: none;
background-image: url("../../../../media/clock.svg");
background-repeat: no-repeat;
background-position: right 20px center;
background-size: 18px;
option {
padding: 10px 20px;
background-color: white;
}
}
@media @mobile {
.date {
width: 100vw !important;
}
.form-cols {
}
}
@media @tablet {
.date {
width: 100% !important;
}
.form-cols {
flex-direction: row;
}
}
}
@media @mobile {
.no-gap {
gap: 0px !important;
}
& > div {
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
gap: 20px;
& > div {
flex: 1;
}
}
}
@media @tablet {
& > div {
gap: 40px;
}
}
@media @desktop {
.no-gap {
gap: 40px !important;
}
.row-title {
font-size: 2.5rem !important;
}
& > div {
flex-direction: row;
align-items: start;
justify-content: center;
}
}
}
.max-width {
max-width: @body-maxwidth !important;
}
.datasec {
display: flex;
align-items: center !important;
.link {
height: 100%;
display: flex;
align-items: flex-end !important;
text-decoration: underline;
margin-right: 3px;
color: rgb(14, 91, 146);
}
}
</style>

View File

@@ -0,0 +1,52 @@
<script lang="ts">
import inView from "../../functions/observer"
import { fly } from "svelte/transition"
export let rows: Row[]
function scrollToRow(name) {
const element = document.getElementsByName(name)[0]
if (element) {
element.scrollIntoView({ behavior: "smooth" })
}
}
let visible = false
let node
</script>
{#key visible}
<div
class="siteRefs"
bind:this="{node}"
use:inView="{{ threshold: 0 }}"
on:enter="{() => {
visible = true
}}"
>
{#each rows as row, i}
{#if row.title && i != 0}
<button
class="siteRef"
on:click="{() => scrollToRow(row.title)}"
in:fly="{{ duration: 1000, delay: 40 * i, opacity: 0, y: 150 }}"
><img src="media/arrow-bottom-right.svg" alt="arrow" />{row?.title}</button
>
{/if}
{/each}
</div>
{/key}
<style lang="less">
@import "../../assets/css/variables.less";
.siteRefs {
margin-top: 25px;
button {
display: flex;
align-items: center;
img {
transform: scale(1.4);
margin: 0.5rem 0.9rem 0.5rem 0rem;
}
color: @link-font-color;
font-weight: 600;
}
}
</style>

View File

@@ -0,0 +1,128 @@
<script lang="ts">
export let col: Column
import { apiBaseURL } from "../../../config"
import { fly } from "svelte/transition"
import SiteRefs from "./siteRefs.svelte"
import inView from "../../functions/observer"
let visible = false
let node
export let rows: Row[]
</script>
<div
class="tableContainer"
bind:this="{node}"
use:inView="{{ threshold: 0 }}"
on:enter="{() => {
visible = true
}}"
>
<h3>{col?.tableFieldHeading ?? ""}</h3>
{#key visible}
{#each col?.table as table, i (table?.title)}
<div class="table" in:fly="{{ duration: 1000, delay: i * 150, y: 130, opacity: 0 }}">
<div class="tableTitle">{table?.title ?? ""}</div>
<table>
{#each table?.tableRow as row}
<tr class:font-bold="{row.bold}">
{#if row?.left}
<td>{row?.left}</td>
{/if}
{#if row?.center}
<td>{row.center}</td>
{/if}
{#if row.right}
<td>{row?.right}</td>
{/if}
</tr>
{/each}
</table>
{#if table.hintsTable}
<div class="hints-table">
<h5>Hinweise:</h5>
<p>{@html table?.hintsTable}</p>
</div>
{/if}
</div>
{/each}
{/key}
{#if col.hintsTable}
<div in:fly="{{ duration: 1000, y: 130, opacity: 0 }}">
<h5>Hinweise:</h5>
<p>{@html col?.hintsTable}</p>
</div>
{/if}
{#if col.siteRefs}
<SiteRefs rows="{rows}" />
{/if}
</div>
<style lang="less">
@import "../../assets/css/variables.less";
* {
border: 0px solid black !important;
transition: font-size 0ms;
}
.hints-table {
padding: 0.3rem 0px;
h5 {
font-size: 0.85rem;
font-weight: 700;
}
p {
font-size: 0.85rem;
padding: 0.3rem 0px;
}
}
.tableContainer {
max-width: @body-maxwidth;
position: relative;
height: 100%;
width: 100%;
line-height: normal;
h3 {
width: 100%;
font-size: 2rem;
font-weight: bold;
margin: 0rem 0vw 1.6rem 0vw;
color: @heading-font-color;
}
h5 {
font-size: 0.85rem;
font-weight: 700;
}
p {
font-size: 0.85rem;
padding: 0.3rem 0px;
}
.font-bold {
font-weight: 700;
}
.table {
width: 100%;
border-collapse: collapse;
.tableTitle {
font-weight: bold;
margin-bottom: 0.5rem;
}
table {
width: 100%;
tr {
border: 0px solid black;
display: flex;
}
td {
padding: 0.3rem 0px;
flex: 1;
}
}
}
}
</style>

View File

@@ -0,0 +1,55 @@
<script lang="ts">
import { navigate } from "svelte-routing"
export let site: Site
import Image from "./image.svelte"
export let index
</script>
<main class="teaser">
{#if index % 2 == 0 || window.innerWidth < 1023}
<Image siteId="{site?.id}" siteImages="{site?.teaserImages}" />
{/if}
<div class="content">
<h3>{site?.teaserTitle}</h3>
<p>{site?.teaserDescription}</p>
<button on:click="{() => navigate(site.path)}">MEHR</button>
</div>
{#if index % 2 == 1 && window.innerWidth > 1023}
<Image siteId="{site?.id}" siteImages="{site?.teaserImages}" />
{/if}
</main>
<style lang="less">
@import "../../assets/css/variables.less";
.teaser {
max-width: @body-small-maxwidth;
display: flex;
flex-direction: column;
gap: 2vw;
width: 100%;
@media @desktop {
flex-direction: row;
}
div {
flex: 1;
}
.content {
flex: 1;
display: flex;
flex-direction: column;
h3 {
font-size: 2rem;
font-weight: bold;
margin: 0rem 0 1.6rem 0;
color: @heading-font-color;
}
button {
font-weight: bold;
color: @link-font-color;
width: fit-content;
border-top: 3px solid @link-font-color;
margin-top: 3rem;
}
}
}
</style>

View File

@@ -0,0 +1,48 @@
<script lang="ts">
import SiteRefs from "./siteRefs.svelte"
export let col: Column
export let rows: Row[]
</script>
<div class="text-container">
<h3 class:noMargin={!col.textFieldHeading}>{col.textFieldHeading ?? ""}</h3>
{#if col?.textContent}
<div>
{@html col?.textContent}
</div>
{/if}
{#if col.siteReference}
<SiteRefs rows="{rows}" />
{/if}
</div>
<style lang="less">
@import "../../assets/css/variables.less";
.noMargin{
margin: 0px !important;
}
.text-container {
text-align: left;
width: 100%;
h3 {
width: 100%;
font-size: 2rem;
font-weight: bold;
margin: 0rem 0vw 1.6rem 0vw;
color: @heading-font-color;
}
}
@media @mobile {
.text-container {
li {
padding-left: 16px !important;
}
}
}
@media @desktop {
.text-container {
margin: 0px;
}
}
</style>

View File

@@ -0,0 +1,163 @@
<script lang="ts">
import { apiBaseURL } from "../../../config"
import { navigate } from "svelte-routing"
import { fly } from "svelte/transition"
let container
let videoElement
let videoText
let videoWrapper
let cooldown = false
export let col
export let siteId
</script>
<div id="wrapper" class="video-container" bind:this="{container}">
<div class="video-wrapper video-wrapper-big" bind:this="{videoWrapper}">
<div class="text shown" bind:this="{videoText}">
<h2 in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">{col.titleVideo}</h2>
<p in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">
{col.descriptionVideo}
</p>
</div>
<video
autoplay
class="video"
playsinline
src="{`${apiBaseURL}content/${siteId}/${col.video?.src}`}"
loop
alt="video1"
muted
bind:this="{videoElement}"><track kind="captions" /></video
>
</div>
</div>
<style lang="less">
@import "../../assets/css/variables.less";
#wrapper {
width: 100%;
flex: 2;
}
.video-wrapper {
width: 100%;
display: flex;
max-height: min(700px, 55vh);
overflow: hidden;
position: relative;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
z-index: 10;
}
@media @mobile {
.hidden {
p,
button {
visibility: hidden !important;
opacity: 0;
height: 0px;
margin-top: 0px !important;
transition: opacity 0s;
}
h2 {
margin-bottom: 0px !important;
transform: translateY(50%);
}
}
.shown {
opacity: 1;
visibility: visible;
}
}
@media @desktop {
.hidden {
h2 {
visibility: hidden;
transition: opacity 0s;
}
}
}
.text {
position: absolute;
z-index: 20;
max-width: 85%;
color: rgb(255, 255, 255);
animation-delay: 500ms;
bottom: 35px;
left: 35px;
@media @mobile {
h2 {
font-size: 2.8rem;
font-weight: bold;
line-height: normal;
margin-bottom: 5px;
}
p {
line-height: normal;
}
button {
border-top: 3px solid white;
font-size: 1.4rem;
font-weight: bold;
color: white;
margin-top: 15px;
}
}
@media @desktop {
max-width: 70%;
h2 {
font-size: 2.7rem;
}
p {
}
button {
font-size: 1.5rem;
}
}
}
}
.video {
width: 100%;
min-height: max(35vh, 400px);
height: 100% !important;
object-fit: cover;
}
@media (max-width: 1023px) {
.video-container {
flex-direction: column;
}
.text {
max-width: 90%;
}
video {
height: 100% !important;
min-height: max(45vh, 60vw) !important;
width: auto !important;
min-width: 100%;
object-fit: cover;
object-position: center;
}
.video-wrapper-small,
.video-wrapper-big {
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,315 @@
<script lang="ts">
import { onMount } from "svelte"
import { apiBaseURL } from "../../config"
import { navigate } from "svelte-routing"
import { temperature } from "../stores"
export let siteId
let container
let videoElements = []
let videoTexts = []
let videoWrappers = []
let cooldown = false
export let col
onMount(() => {
container.style.height = videoElements[0].offsetHeight + "px"
Array.from(videoElements).forEach((e) => {
e.style.height = "100%"
})
videoElements[0].play()
videoElements[1].play()
setTimeout(() => {
videoElements[1].pause()
}, 0)
videoWrappers.forEach((videoWrapper) => {
const video = videoWrapper.querySelector(".video")
let eventFunc = (e) => {
if (cooldown) return
let selected = e.currentTarget
cooldown = true
setTimeout(() => {
cooldown = false
}, 502)
let text = selected.querySelector(".text")
videoWrappers.forEach((vw) => {
if (selected == vw) {
vw.classList.add("video-wrapper-big")
vw.classList.remove("video-wrapper-small")
} else {
vw.classList.add("video-wrapper-small")
vw.classList.remove("video-wrapper-big")
}
vw.querySelector(".video").pause()
})
videoTexts.forEach((vt) => {
if (text == vt) {
setTimeout(() => {
vt.classList.add("shown")
vt.classList.remove("hidden")
}, 500)
} else {
vt.classList.add("hidden")
vt.classList.remove("shown")
}
})
video.play()
}
videoWrapper.addEventListener("mousemove", (e) => eventFunc(e))
videoWrapper.addEventListener("click", (e) => eventFunc(e))
})
})
let innerWidth = window.innerWidth
</script>
<div class="video-top-lvl-container">
<div id="wrapper" class="video-container" bind:this="{container}">
<div class="video-wrapper video-wrapper-big" bind:this="{videoWrappers[0]}">
<div class="text shown" bind:this="{videoTexts[0]}">
<h2>{col.videoSwitch[0]?.title}</h2>
<p>
{col.videoSwitch[0]?.description}
</p>
<button
class="link"
on:click="{() => {
navigate(col.videoSwitch[0]?.link)
}}">MEHR</button
>
</div>
<video
class="video"
playsinline
src="{`${apiBaseURL}content/${siteId}/${col.videoSwitch[0].video?.src}`}"
loop
alt="video1"
muted
bind:this="{videoElements[0]}"><track kind="captions" /></video
>
</div>
<div class="video-wrapper video-wrapper-small" bind:this="{videoWrappers[1]}">
<div class="text hidden" bind:this="{videoTexts[1]}">
<h2>{col.videoSwitch[1]?.title}</h2>
<p>
{col.videoSwitch[1]?.description}
</p>
<button
class="link"
on:click="{() => {
navigate(col.videoSwitch[1]?.link)
}}">MEHR</button
>
</div>
<video
class="video"
loop
playsinline
src="{`${apiBaseURL}content/${siteId}/${col.videoSwitch[1].video?.src}`}"
muted
bind:this="{videoElements[1]}"><track kind="captions" /></video
>
</div>
</div>
<div class="icons">
<button class="thermo">
<img src="/media/thermometer.svg" alt="temp" />
{Number($temperature).toFixed(1) || "-"} °C
</button>
</div>
</div>
<style lang="less">
@import "../assets/css/variables.less";
.video-top-lvl-container {
width: 100%;
display: flex;
flex-direction: column;
gap: 40px;
}
.video-container {
display: flex;
width: 100%;
@media @mobile {
gap: 20px;
}
@media @tablet {
gap: 40px;
}
}
.icons {
display: flex;
width: 100%;
@media @mobile {
justify-content: end;
}
@media @tablet {
justify-content: end;
button {
margin: 28px 2rem !important;
}
}
margin-bottom: 60px;
img {
transform: scale(1.5);
margin: 0px 0.4rem;
}
button {
display: flex;
font-weight: bold;
justify-content: center;
font-size: 1rem;
position: relative;
margin: 0 1rem;
}
button::before {
font-weight: 400;
position: absolute;
transform: translateY(-150%);
}
.camera::before {
content: "Webcam";
}
.thermo::before {
content: "Lufttemperatur";
}
.waves::before {
content: "Wassertemperatur";
}
}
.video-wrapper {
overflow: hidden;
position: relative;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
z-index: 10;
}
@media @mobile {
.hidden {
p,
button {
visibility: hidden !important;
opacity: 0;
height: 0px;
margin-top: 0px !important;
transition: opacity 0s;
}
h2 {
margin-bottom: 0px !important;
transform: translateY(50%);
}
}
.shown {
opacity: 1;
visibility: visible;
}
}
@media @desktop {
.hidden {
h2 {
visibility: hidden;
transition: opacity 0s;
}
}
}
.text {
position: absolute;
z-index: 20;
max-width: 85%;
color: rgb(255, 255, 255);
animation-delay: 500ms;
bottom: 35px;
left: 35px;
@media @mobile {
h2 {
font-size: 2.8rem;
font-weight: bold;
line-height: normal;
margin-bottom: 5px;
}
p {
line-height: normal;
}
button {
border-top: 3px solid white;
font-weight: bold;
padding-top: 2px;
color: white;
font-size: 16px;
margin-top: 15px;
}
}
@media @desktop {
max-width: 70%;
h2 {
font-size: 2.7rem;
}
p {
}
button {
font-size: 24px;
}
}
}
}
.video {
width: 100%;
min-height: max(35vh, 400px);
height: auto;
object-fit: cover;
position: absolute;
top: 0;
left: 0;
}
.video-wrapper-big {
flex: 3;
}
.video-wrapper-small {
flex: 1 !important;
}
.video-wrapper-big:hover,
.video-wrapper-small:hover {
flex: 3;
}
@media (max-width: 1023px) {
.video-container {
flex-direction: column;
}
.text {
max-width: 90%;
}
video {
height: 100% !important;
min-height: 75vh !important;
width: auto !important;
min-width: 100%;
object-fit: cover;
object-position: center;
}
.video-wrapper-small,
.video-wrapper-big {
width: 100%;
}
}
</style>