Compare commits

...
Sign in to create a new pull request.

14 commits

43 changed files with 6652 additions and 4638 deletions

8
.dockerignore Normal file
View file

@ -0,0 +1,8 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.output
.vinxi
.git

View file

@ -2,4 +2,7 @@ module.exports = {
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
plugins: ["solid"], plugins: ["solid"],
extends: ["eslint:recommended", "plugin:solid/typescript", "prettier"], extends: ["eslint:recommended", "plugin:solid/typescript", "prettier"],
env: {
node: true,
},
}; };

3
.gitignore vendored
View file

@ -1,6 +1,5 @@
dist dist
.solid .vinxi
.output .output
.vercel .vercel
.netlify .netlify

53
Dockerfile Normal file
View file

@ -0,0 +1,53 @@
# Use the desired base image
FROM node:21-alpine AS base
# Set the NODE_ENV to production
ENV NODE_ENV production
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
# Pass the Font Awesome token as a build argument
ARG FONT_AWESOME_TOKEN
RUN echo "@fortawesome:registry=https://npm.fontawesome.com/" > ~/.npmrc \
&& echo "//npm.fontawesome.com/:_authToken=${FONT_AWESOME_TOKEN}" >> ~/.npmrc \
&& if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
# Remove existing 'node' user and create a new user 'node' with UID 99 and use the existing group with GID 100
RUN deluser --remove-home node \
&& adduser -S -G users -u 99 node
COPY --from=builder /app/public ./public
COPY --from=builder --chown=node:users /app/.output ./.output
COPY --from=builder --chown=node:users /app/.vinxi ./.vinxi
# Switch to the non-root user
USER node
EXPOSE 3000
# Set the default values for environment variables
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
CMD ["node", ".output/server/index.mjs"]

3
app.config.ts Normal file
View file

@ -0,0 +1,3 @@
import { defineConfig } from "@solidjs/start/config";
export default defineConfig({});

View file

@ -1,35 +1,34 @@
{ {
"name": "jg-eucs", "name": "jg-eucs",
"scripts": { "scripts": {
"dev": "solid-start dev", "dev": "vinxi dev",
"build": "solid-start build", "build": "vinxi build",
"start": "solid-start start", "start": "vinxi start",
"lint": "eslint --fix \"**/*.{ts,tsx,js,jsx}\"", "lint": "eslint --fix \"src/**/*.{ts,tsx,js,jsx}\"",
"typecheck": "tsc --noEmit --checkJs false --skipLibCheck" "typecheck": "tsc --noEmit --checkJs false --skipLibCheck"
}, },
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@types/node": "^20.8.6", "@types/node": "^20.11.21",
"@typescript-eslint/parser": "^6.8.0", "@typescript-eslint/parser": "^7.1.0",
"esbuild": "^0.19.5", "esbuild": "^0.20.1",
"eslint": "^8.51.0", "eslint": "^8.57.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-solid": "^0.13.0", "eslint-plugin-solid": "^0.13.1",
"postcss": "^8.4.31", "prettier": "^3.2.5",
"prettier": "^3.0.3", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-organize-imports": "^3.2.3", "typescript": "^5.3.3"
"solid-start-node": "^0.3.6",
"typescript": "^5.2.2",
"vite": "^4.4.11"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/pro-regular-svg-icons": "^6.4.2", "@fortawesome/pro-regular-svg-icons": "^6.5.1",
"@solidjs/meta": "^0.28.6", "@solidjs/meta": "^0.29.3",
"@solidjs/router": "^0.8.3", "@solidjs/router": "^0.12.4",
"solid-js": "^1.8.1", "@solidjs/start": "^0.6.0",
"solid-start": "^0.3.6" "sass": "^1.71.1",
"solid-js": "^1.8.15",
"vinxi": "^0.3.4"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"

5932
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

40
public/sitemap.xml Normal file
View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://jg-eucs.com/en</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/en/KSS22</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/en/manufacturers</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/en/overview</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/de</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/de/imprint</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/de/KSS22</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/de/manufacturers</loc>
<lastmod>2024-03-13</lastmod>
</url>
<url>
<loc>https://jg-eucs.com/de/overview</loc>
<lastmod>2024-03-13</lastmod>
</url>
</urlset>

108
public/sitemap.xsl Normal file
View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>XML Sitemap</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body {
font-family: sans-serif;
font-size: 16px;
color: #242628;
}
a {
color: #000;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
table {
border: none;
border-collapse: collapse;
width: 100%
}
th {
text-align: left;
padding-right: 30px;
font-size: 11px;
}
thead th {
border-bottom: 1px solid #7d878a;
cursor: pointer;
}
td {
font-size:11px;
padding: 5px;
}
tr:nth-child(odd) td {
background-color: rgba(0,0,0,0.04);
}
tr:hover td {
background-color: #e2edf2;
}
#content {
margin: 0 auto;
padding: 2% 5%;
max-width: 800px;
}
.desc {
margin: 18px 3px;
line-height: 1.2em;
}
.desc a {
color: #5ba4e5;
}
</style>
</head>
<body>
<div id="content">
<h1>XML Sitemap</h1>
<p class="desc">
This is a sitemap created by <a href="https://unlimited-dev.de">Unlimited Development</a> to allow search engines to discover this site's content.
</p>
<table id="sitemap" cellpadding="3">
<thead>
<tr>
<th width="70%">URL (<xsl:value-of select="count(sitemap:urlset/sitemap:url)"/> total)</th>
<th width="15%">Images</th>
<th title="Last Modification Time" width="15%">Last Modified</th>
</tr>
</thead>
<tbody>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:for-each select="sitemap:urlset/sitemap:url">
<tr>
<td>
<xsl:variable name="itemURL">
<xsl:value-of select="sitemap:loc"/>
</xsl:variable>
<a href="{$itemURL}">
<xsl:value-of select="sitemap:loc"/>
</a>
</td>
<td>
<xsl:value-of select="count(image:image)"/>
</td>
<td>
<xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)))"/>
</td>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,144 +0,0 @@
* {
box-sizing: border-box;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #7f5af0;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
[class*="col-"] {
float: right;
}
#sidenavbar {
z-index: 1;
margin-left: -8px;
overflow: visible;
background-color: #121629;
position: fixed;
bottom: 0;
width: 100%;
height: 50px;
text-align: left;
display: flex;
justify-content: space-between;
}
#sidenavbar button {
all: unset;
margin: 5px auto;
color: #eff0f3;
padding-left: 10px;
padding-right: 10px;
text-decoration: none;
font-size: 1.4em;
border: none;
}
#sidenavbar button:hover {
background: #eff0f3;
color: #2a2a2a;
cursor: pointer;
}
.main {
height: 100%;
}
body {
background-color: #16161a;
color: #94a1b2;
font-size: 1.4em;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.6em;
margin-left: 140px;
}
p {
text-align: justify;
font-size: 0.875em;
}
header {
text-align: center;
}
footer,
aside,
article {
text-align: center;
padding: 2%;
margin: 1.5%;
}
img {
width: 100%;
max-width: max-content;
padding: 16px;
height: auto;
display: block;
}
.col-1 {
width: 8.33%;
}
.col-2 {
width: 16.66%;
}
.col-3 {
width: 25%;
}
.col-4 {
width: 33.33%;
}
.col-5 {
width: 41.66%;
}
.col-6 {
width: 50%;
}
.col-7 {
width: 58.33%;
}
.col-8 {
width: 66.66%;
}
.col-9 {
width: 75%;
}
.col-10 {
width: 83.33%;
}
.col-11 {
width: 91.66%;
}
.col-12 {
width: 100%;
}
@media only screen and (max-width: 767px) {
[class*="col-"] {
width: 100%;
}
}

View file

@ -1,407 +0,0 @@
* {
scroll-margin-block-start: 60px;
scroll-margin-block-end: 60px;
box-sizing: border-box;
scroll-behavior: smooth;
max-width: 100%;
max-height: 100%;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #7f5af0;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
[class*="col-"] {
float: left;
}
.row {
clear: both;
}
#navbar {
z-index: 1;
overflow-y: auto;
overflow-x: hidden;
background-color: #121629;
position: fixed;
top: 0;
height: 100%;
margin-left: -8px;
}
#navbar button {
border-radius: 16px;
scale: 0.9;
}
#navbar button:hover {
scale: 1.06;
}
#navbar a {
float: none;
display: block;
color: #eff0f3;
text-align: left;
padding: 8px 8px;
text-decoration: none;
font-size: 0.9em;
}
#navbar a:hover {
background: #eff0f3;
color: #121629;
cursor: pointer;
}
#sidenavbar {
z-index: 1;
margin-left: -8px;
overflow: visible;
background-color: #121629;
position: fixed;
bottom: 0;
width: 100%;
height: 50px;
text-align: left;
display: flex;
justify-content: space-between;
}
#sidenavbar button {
all: unset;
margin: 5px auto;
color: #eff0f3;
padding-left: 10px;
padding-right: 10px;
text-decoration: none;
font-size: 1.4em;
border: none;
}
#sidenavbar button:hover {
background: #eff0f3;
color: #2a2a2a;
cursor: pointer;
}
.main {
height: 100%;
}
body {
background-color: #16161a;
color: #94a1b2;
text-align: center;
font-size: 1.4em;
}
h1 {
font-size: 2.5em;
color: #fffffe;
}
h2 {
font-size: 2em;
color: #fffffe;
}
h3 {
font-size: 1.6em;
clear: both;
color: #fffffe;
}
p {
text-align: justify;
font-size: 0.875em;
}
header {
text-align: center;
padding-left: 140px;
}
footer,
aside,
article {
text-align: center;
padding-left: 15px;
margin: 1.5%;
margin-left: 145px;
}
img {
width: 100%;
max-width: max-content;
height: auto;
margin-top: -8px;
}
button {
background-color: #121629;
color: #eff0f3;
text-align: left;
padding: 8px 8px;
text-decoration: none;
font-size: 0.9em;
}
p a {
text-align: justify;
text-decoration: none;
color: #91c4ff;
border-bottom: 1px solid navy;
}
p a:hover {
border-bottom: 1px solid #91c4ff;
}
.svg-inline--fa,
b {
color: #91c4ff;
}
.righties {
margin: 0 2%;
margin-right: 0%;
padding: 0%;
width: 33%;
float: right;
transition: width 1.5s;
clear: both;
}
.righties:hover {
width: 50%;
}
.lefties {
margin-right: 20px;
width: 33%;
height: 100%;
float: left;
transition: width 1.5s;
display: none;
}
.lefties:hover {
width: 50%;
}
#vcutout {
width: 25%;
}
#vcutout:hover {
width: 30%;
}
.hidden {
/*position:absolute;
transform:translate(-50%,-50%);
height:200px;
width:200px; */
float: left;
padding: 2%;
padding-left: 0%;
display: none;
}
/*wenn hover über text, zeige bild*/
.imghover:hover + .hidden {
display: block;
}
.light-mode {
background-color: #eff0f3;
color: #2a2a2a;
}
.light-mode article p a {
text-align: justify;
text-decoration: underline;
color: #2a2a2a;
}
.light-mode b {
color: #2a2a2a;
}
.light-mode b a {
color: #2a2a2a;
}
.light-mode h3 {
color: #2a2a2a;
}
.light-mode h1 {
color: #2a2a2a;
}
.light-mode h2 {
color: #2a2a2a;
}
.light-mode #navbar {
background-color: #b8c1ec;
}
.light-mode #sidenavbar {
background-color: #b8c1ec;
}
.light-mode #navbar a {
color: black;
}
.light-mode #sidenavbar a {
color: black;
}
.light-mode button {
background-color: #b8c1ec;
color: black;
}
/*Raster Einstellungen*/
.light-mode .raster {
background-color: #eff0f3;
}
.light-mode a {
color: #2a2a2a;
}
a {
display: inline;
color: rgb(225, 223, 210);
}
a svg.left {
margin-right: 2px;
}
a svg.right {
margin-left: 6px;
}
.raster {
width: 300px;
height: 350px;
float: left;
padding: 1%;
padding-top: 0;
border: #555;
border-width: 2px;
border-style: solid;
border-radius: 10%;
scale: 0.9;
font-size: 0.9em;
}
a div img,
a div video {
border-radius: 10%;
max-width: 260px;
max-height: 290px;
padding-top: 8px;
bottom: 0;
}
a div h3 {
margin: 0.5%;
}
.raster:hover {
scale: 1.06;
}
.raster:hover a div img {
width: 110%;
}
.logos {
height: 1.6em;
margin-bottom: -18px;
}
.col-1 {
width: 8.33%;
}
.col-2 {
width: 12.5%;
}
.col-3 {
width: 25%;
}
.col-4 {
width: 33.33%;
}
.col-5 {
width: 41.66%;
}
.col-6 {
width: 50%;
}
.col-7 {
width: 58.33%;
}
.col-8 {
width: 66.66%;
}
.col-9 {
width: 75%;
}
.col-10 {
width: 83.33%;
}
.col-11 {
width: 91.66%;
}
.col-12 {
width: 100%;
}
@media (max-width: 767px) /*unter handy größe*/ {
header,
article,
img,
p,
h1,
h2,
h3 {
margin-left: 0%;
padding-left: 0;
}
[class*="col-"] {
width: 100%;
}
#navbar {
visibility: hidden;
}
#sidenavbar {
visibility: visible;
}
/*.raster {width: calc(100%/2);}*/
.righties {
width: 100%;
}
.righties:hover {
width: 100%;
}
}
@media only screen and (min-width: 767px) /*über handy größe*/ {
#navbar {
visibility: visible;
}
#sidenavbar {
visibility: hidden;
}
/*.raster {width: calc(100%/5);}*/
div div button {
visibility: hidden;
}
}
/*@media screen and (min-width:1200px) {.raster {width: calc(100%/6);}}
@media screen and (min-width:1500px) {.raster {width: calc(100%/8);}}*/
@media screen and (min-width: 1900px) /*HD Fullscreen only*/ {
.lefties {
display: block;
width: 27%;
}
.righties {
width: 27%;
}
}
@media screen and (min-width: 2250px) /*ab 2000px nicht weiter skalieren*/ {
* {
width: 1950px;
margin-left: auto;
margin-right: auto;
}
}

View file

@ -1,109 +0,0 @@
* {
scroll-margin-block-start: 60px;
scroll-margin-block-end: 60px;
box-sizing: border-box;
scroll-behavior: smooth;
max-width: 100%;
max-height: 100%;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #ff8906;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
[class*="col-"] {
float: left;
}
.row {
clear: both;
}
body {
background-color: #0f0e17;
color: #a7a9be;
text-align: left;
font-size: 1.4em;
max-width: 900px;
margin: auto;
}
p {
padding: 10px;
}
#cover {
opacity: 60%;
}
.container {
position: relative;
text-align: center;
color: white;
}
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#gone {
display: none;
color: #fffffe;
text-align: center;
}
#MoreButton {
margin: auto;
position: relative;
height: auto;
max-height: max-content;
width: auto;
max-width: max-content;
background-color: #ff8906;
border-radius: 5px;
color: #fffffe;
font-size: 1.2em;
}
a {
text-decoration: none;
}
a div p {
text-align: center;
padding: 20px;
}
a :hover {
scale: 1.06;
}
.righties {
padding-bottom: 30px;
padding-top: 20px;
width: 100%;
clear: both;
}
@media (max-width: 767px) /*unter handy größe*/ {
.centered {
display: none;
}
#gone {
display: block;
}
#cover {
opacity: 100%;
}
.righties {
width: 100%;
}
}

110
src/app.tsx Normal file
View file

@ -0,0 +1,110 @@
// @refresh reload
import "@fortawesome/fontawesome-svg-core/styles.css";
import { Link, Meta, MetaProvider, Title } from "@solidjs/meta";
import { Router } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start";
import { Suspense } from "solid-js";
import "./styles/global.scss";
export default function App() {
return (
<Router
root={(props) => (
<MetaProvider>
<Link
rel="apple-touch-icon"
sizes="57x57"
href="/favicon/apple-icon-57x57.png"
/>
<Link
rel="apple-touch-icon"
sizes="60x60"
href="/favicon/apple-icon-60x60.png"
/>
<Link
rel="apple-touch-icon"
sizes="72x72"
href="/favicon/apple-icon-72x72.png"
/>
<Link
rel="apple-touch-icon"
sizes="76x76"
href="/favicon/apple-icon-76x76.png"
/>
<Link
rel="apple-touch-icon"
sizes="114x114"
href="/favicon/apple-icon-114x114.png"
/>
<Link
rel="apple-touch-icon"
sizes="120x120"
href="/favicon/apple-icon-120x120.png"
/>
<Link
rel="apple-touch-icon"
sizes="144x144"
href="/favicon/apple-icon-144x144.png"
/>
<Link
rel="apple-touch-icon"
sizes="152x152"
href="/favicon/apple-icon-152x152.png"
/>
<Link
rel="apple-touch-icon"
sizes="180x180"
href="/favicon/apple-icon-180x180.png"
/>
<Link
rel="icon"
type="image/png"
sizes="192x192"
href="/favicon/android-icon-192x192.png"
/>
<Link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon/favicon-32x32.png"
/>
<Link
rel="icon"
type="image/png"
sizes="96x96"
href="/favicon/favicon-96x96.png"
/>
<Link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon/favicon-16x16.png"
/>
<Link rel="manifest" href="/favicon/manifest.json" />
<Meta name="msapplication-TileColor" content="#ffffff" />
<Meta
name="msapplication-TileImage"
content="/favicon/ms-icon-144x144.png"
/>
<Meta name="theme-color" content="#ffffff" />
<Meta http-equiv="X-UA-Compatible" content="IE=edge" />
<Meta charset="UTF-8" />
<Meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<Meta name="author" content="Julian Gerhardt" />
<Meta
name="keywords"
content="Elektrische Einräder, EUC, Monowheels, Kingsong, Inmotion, Gotway"
/>
<Title>jg-eucs.com</Title>
<Suspense>{props.children}</Suspense>
</MetaProvider>
)}
>
<FileRoutes />
</Router>
);
}

225
src/components/Asset.tsx Normal file
View file

@ -0,0 +1,225 @@
import {
faMagnifyingGlassMinus,
faMagnifyingGlassPlus,
faSlidersSimple,
faVolume,
faVolumeSlash,
faXmark,
} from "@fortawesome/pro-regular-svg-icons";
import {
Match,
Setter,
Show,
Switch,
createEffect,
createSignal,
onCleanup,
} from "solid-js";
import { FontAwesomeIcon } from "./FontAwesomeIcon";
interface Asset {
src: string;
}
function AssetHandler() {
const [moving, setMoving] = createSignal(false);
const [active, setActive] = createSignal("");
const [zoomLevel, setZoomLevel] = createSignal(0);
const zoomAmount = () => 1 + zoomLevel() * 0.5;
const [x, setX] = createSignal(0);
const [y, setY] = createSignal(0);
function FullscreenView() {
const [muted, setMuted] = createSignal(true);
const [controlls, setControlls] = createSignal(false);
const [clientX, setClientX] = createSignal(0);
const [clientY, setClientY] = createSignal(0);
const [ref, setRef] = createSignal<HTMLElement | null>(null);
const handleMouseMove = (event: MouseEvent) => {
const { clientX, clientY } = event;
setClientX(clientX);
setClientY(clientY);
};
createEffect(() => {
const thisRef = ref();
if (!thisRef) return;
const rectA = thisRef.getBoundingClientRect();
const origSizeW = rectA.width / zoomAmount();
const origSizeH = rectA.height / zoomAmount();
const rectW = wrapperRef.getBoundingClientRect();
const hori = rectW.width - origSizeW + origSizeW / zoomAmount();
const verti = rectW.height - origSizeH + origSizeH / zoomAmount();
const xP = (clientX() - hori / 2) / (rectW.width - hori);
const yP = (clientY() - verti / 2) / (rectW.height - verti);
setX((xP > 0 ? (xP < 1 ? xP : 1) : 0) * origSizeW);
setY((yP > 0 ? (yP < 1 ? yP : 1) : 0) * origSizeH);
const moving =
clientX() > (rectW.width - origSizeW) / 2 &&
clientX() < rectW.width - (rectW.width - origSizeW) / 2 &&
clientY() > (rectW.height - origSizeH) / 2 &&
clientY() < rectW.height - (rectW.height - origSizeH) / 2;
setMoving(moving);
});
let wrapperRef: HTMLDivElement;
createEffect(() => {
if (active()) return;
setZoomLevel(0);
setMuted(true);
setControlls(false);
});
const handleKeyDown = (event: KeyboardEvent) => {
if (!active() || "Escape" != event.key) return;
event.preventDefault();
setActive("");
};
const handleWheel = (event: WheelEvent) => {
if (!active()) return;
event.preventDefault();
if (event.deltaY > 0 && !(zoomLevel() <= 0)) setZoomLevel((e) => e - 1);
else if (event.deltaY < 0 && !(zoomLevel() >= 4))
setZoomLevel((e) => e + 1);
};
createEffect(() => {
window.addEventListener("keydown", handleKeyDown);
window.addEventListener("wheel", handleWheel, { passive: false });
onCleanup(() => {
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("wheel", handleWheel);
});
});
return (
<div
ref={wrapperRef!}
onClick={(e) => e.target === wrapperRef && setActive("")}
onMouseMove={handleMouseMove}
classList={{ "fullscreen-asset": true, active: !!active() }}
>
<Asset
src={active()}
volume={!muted()}
controlls={controlls()}
setRef={setRef}
/>
<div class="controlls">
<button onClick={() => setActive("")} title="Close">
<FontAwesomeIcon icon={faXmark} />
</button>
<Show when={active().startsWith("/videos")}>
<button
onClick={() => setMuted((e) => !e)}
style={{ "border-style": controlls() ? "dashed" : "" }}
title={muted() ? "Unmute" : "Mute"}
>
<FontAwesomeIcon icon={!muted() ? faVolume : faVolumeSlash} />
</button>
<button
onClick={() => setControlls((e) => !e)}
style={{ "border-style": controlls() ? "inset" : "" }}
title="Show controlls"
>
<FontAwesomeIcon icon={faSlidersSimple} />
</button>
</Show>
<button
onClick={() => setZoomLevel((e) => e + 1)}
disabled={zoomLevel() >= 4}
title="Zoom +"
>
<FontAwesomeIcon icon={faMagnifyingGlassPlus} />
</button>
<button
onClick={() => setZoomLevel((e) => e - 1)}
disabled={zoomLevel() <= 0}
title="Zoom -"
>
<FontAwesomeIcon icon={faMagnifyingGlassMinus} />
</button>
</div>
</div>
);
}
function Asset(
props: Asset & {
class?: string;
volume?: boolean;
controlls?: boolean;
setRef?: Setter<HTMLElement | null>;
},
) {
let imgRef: HTMLImageElement;
let videoRef: HTMLVideoElement;
const shouldZoom = () => active() === props.src && !!zoomLevel();
return (
<Switch>
<Match when={props.src.startsWith("/images")}>
<img
ref={imgRef!}
style={
shouldZoom()
? {
"--zoom": zoomAmount(),
"--x": x() + "px",
"--y": y() + "px",
}
: {}
}
onMouseEnter={() => props.setRef && props.setRef(imgRef)}
classList={{
[props.class ?? ""]: !!props.class,
zoomed: shouldZoom(),
move: moving(),
}}
onClick={() => setActive(props.src)}
src={props.src}
alt={props.src}
/>
</Match>
<Match when={props.src.startsWith("/videos")}>
<video
ref={videoRef!}
onMouseEnter={() => props.setRef && props.setRef(videoRef)}
style={
shouldZoom()
? {
"--zoom": zoomAmount(),
"--x": x() + "px",
"--y": y() + "px",
}
: {}
}
classList={{
[props.class ?? ""]: !!props.class,
zoomed: shouldZoom(),
move: moving(),
active: !props.setRef && active() === props.src,
}}
onClick={() => setActive(props.src)}
width="auto"
height="auto"
autoplay
muted={!props.volume}
loop
controls={props.controlls}
>
<source src={props.src} type="video/mp4" />
</video>
</Match>
</Switch>
);
}
return { FullscreenView, Asset };
}
export default AssetHandler;

View file

@ -1,21 +1,18 @@
import { Show } from "solid-js"; import { Show } from "solid-js";
import { A } from "solid-start";
function DeviceTile(props: { href?: string; name: string; src: string }) { function DeviceTile(props: { href?: string; name: string; src: string }) {
return ( return (
<A href={props.href ?? "/soon"}> <a href={props.href ?? "/soon"}>
<div class="raster"> <h3>{props.name}</h3>
<h3>{props.name}</h3> <Show when={props.src.startsWith("/images")}>
<Show when={props.src.startsWith("/images")}> <img src={props.src} alt={props.name} />
<img src={props.src} alt={props.name} /> </Show>
</Show> <Show when={props.src.startsWith("/videos")}>
<Show when={props.src.startsWith("/videos")}> <video width="auto" height="auto" autoplay muted loop>
<video width="auto" height="auto" autoplay muted loop> <source src={props.src} type="video/mp4" />
<source src={props.src} type="video/mp4" /> </video>
</video> </Show>
</Show> </a>
</div>
</A>
); );
} }

View file

@ -0,0 +1,82 @@
import { JSX, createEffect, createSignal, onCleanup } from "solid-js";
function ProgressHandler() {
const [scrollPercentage, setScrollPercentage] = createSignal(0);
// const [active, setActive] = createSignal("");
// const [zoomLevel, setZoomLevel] = createSignal(0);
// const zoomAmount = () => 1 + zoomLevel() * 0.5;
// const [x, setX] = createSignal(0);
// const [y, setY] = createSignal(0);
function ProgressBar() {
// const [muted, setMuted] = createSignal(true);
// const [controlls, setControlls] = createSignal(false);
// const [clientX, setClientX] = createSignal(0);
// const [clientY, setClientY] = createSignal(0);
// const [ref, setRef] = createSignal<HTMLElement | null>(null);
const handleScroll = () => {
const scrollHeight =
document.documentElement.scrollHeight - window.innerHeight;
const currentScroll = window.scrollY;
const scrollPercentage = (currentScroll / scrollHeight) * 100;
setScrollPercentage(scrollPercentage);
};
createEffect(() => {
window.addEventListener("scroll", handleScroll);
onCleanup(() => {
window.removeEventListener("scroll", handleScroll);
});
});
createEffect(() => {
// const thisRef = ref();
// if (!thisRef) return;
// const rectA = thisRef.getBoundingClientRect();
// const origSizeW = rectA.width / zoomAmount();
// const origSizeH = rectA.height / zoomAmount();
// const rectW = wrapperRef.getBoundingClientRect();
// const hori = rectW.width - origSizeW + origSizeW / zoomAmount();
// const verti = rectW.height - origSizeH + origSizeH / zoomAmount();
// const xP = (clientX() - hori / 2) / (rectW.width - hori);
// const yP = (clientY() - verti / 2) / (rectW.height - verti);
// setX((xP > 0 ? (xP < 1 ? xP : 1) : 0) * origSizeW);
// setY((yP > 0 ? (yP < 1 ? yP : 1) : 0) * origSizeH);
// const moving =
// clientX() > (rectW.width - origSizeW) / 2 &&
// clientX() < rectW.width - (rectW.width - origSizeW) / 2 &&
// clientY() > (rectW.height - origSizeH) / 2 &&
// clientY() < rectW.height - (rectW.height - origSizeH) / 2;
// setMoving(moving);
});
// let wrapperRef: HTMLDivElement;
createEffect(() => {
// if (active()) return;
// setZoomLevel(0);
// setMuted(true);
// setControlls(false);
});
return (
<div class="progress">
<></>
</div>
);
}
function Chapter(props: { children: JSX.Element }) {
let divRef: HTMLDivElement;
// let videoRef: HTMLVideoElement;
// const shouldZoom = () => active() === props.src && !!zoomLevel();
return <div ref={divRef!}>{props.children}</div>;
}
return { FullscreenView: ProgressBar, Asset: Chapter };
}
export default ProgressHandler;

View file

@ -4,7 +4,6 @@ import {
faHashtag, faHashtag,
} from "@fortawesome/pro-regular-svg-icons"; } from "@fortawesome/pro-regular-svg-icons";
import { JSXElement, Show, createMemo } from "solid-js"; import { JSXElement, Show, createMemo } from "solid-js";
import { A } from "solid-start";
import { FontAwesomeIcon } from "./FontAwesomeIcon"; import { FontAwesomeIcon } from "./FontAwesomeIcon";
const types = { const types = {
@ -38,12 +37,12 @@ function R(props: {
return ( return (
<> <>
{" "} {" "}
<A <a
href={props.href} href={props.href}
target={type() === "external" ? "_blank" : ""} target={type() === "external" ? "_blank" : ""}
rel={type() === "external" ? "noreferrer noopener" : ""} rel={type() === "external" ? "noreferrer noopener" : ""}
id={props.id} id={props.id}
class={props.class} classList={{ reference: true, [props.class ?? ""]: !!props.class }}
> >
<Show when={type() === "id"}> <Show when={type() === "id"}>
<FontAwesomeIcon class="left" icon={types["id"]} /> <FontAwesomeIcon class="left" icon={types["id"]} />
@ -52,7 +51,7 @@ function R(props: {
<Show when={type() !== "id"}> <Show when={type() !== "id"}>
<FontAwesomeIcon class="right" icon={types[type()]} title={type()} /> <FontAwesomeIcon class="right" icon={types[type()]} title={type()} />
</Show> </Show>
</A>{" "} </a>{" "}
</> </>
); );
} }

View file

@ -0,0 +1,15 @@
import { JSX, Suspense } from "solid-js";
function Wrapper(props: {
class: string;
classList: Record<string, boolean>;
children: JSX.Element | JSX.Element[];
}) {
return (
<div id="body" class={props.class} classList={props.classList}>
<Suspense>{props.children}</Suspense>
</div>
);
}
export default Wrapper;

View file

@ -1,100 +1,157 @@
import { import {
faBars,
faBookOpen, faBookOpen,
faCircleHalfStroke, faCircleHalfStroke,
faGavel,
faGlobe, faGlobe,
faXmark, faXmark,
} from "@fortawesome/pro-regular-svg-icons"; } from "@fortawesome/pro-regular-svg-icons";
import { createSignal } from "solid-js"; import {
import { A, useNavigate } from "solid-start"; useIsRouting,
useLocation,
useNavigate,
useSearchParams,
} from "@solidjs/router";
import { createEffect, createSignal, onCleanup } from "solid-js";
import { FontAwesomeIcon } from "../FontAwesomeIcon"; import { FontAwesomeIcon } from "../FontAwesomeIcon";
export const [lightMode, setLightMode] = createSignal(false); export const [lightMode, setLightMode] = createSignal(false);
const [menu, setMenu] = createSignal(false);
function Navbar() { function Navbar() {
const [menu, setMenu] = createSignal(false);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
const [searchParams] = useSearchParams();
const isRouting = useIsRouting();
createEffect(() => {
const mode = searchParams.lightMode;
const prefersDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (typeof mode === "undefined") {
setLightMode(!prefersDarkMode);
return;
}
const parsedMode = JSON.parse(mode);
if (typeof parsedMode !== "boolean") return;
setLightMode(parsedMode);
});
createEffect(() => {
if (!isRouting() || !menu()) return;
setMenu(false);
});
const handleKeyDown = (event: KeyboardEvent) => {
if (!menu() || "Escape" != event.key) return;
event.preventDefault();
setMenu(false);
};
createEffect(() => {
window.addEventListener("keydown", handleKeyDown);
onCleanup(() => {
window.removeEventListener("keydown", handleKeyDown);
});
});
return ( return (
<> <>
<div id="navbar" style={{ visibility: menu() ? "visible" : "hidden" }}> <div id="navbar" style={{ visibility: menu() ? "visible" : "hidden" }}>
<A href="/de/"> <a href="/de">
<FontAwesomeIcon icon={faBookOpen} /> Einführung <FontAwesomeIcon icon={faBookOpen} /> Einführung
</A> </a>
<A href="/de/overview"> <a href="/de/overview">
<FontAwesomeIcon icon={faBookOpen} /> Start <FontAwesomeIcon icon={faBookOpen} /> Start
</A> </a>
<ol> <ol>
<li> <li>
<A href="/de/overview#start">Was sind EUCs?</A> <a href="/de/overview#start">Was sind EUCs?</a>
</li> </li>
<li> <li>
<A href="/de/overview#why">Warum EUCs?</A> <a href="/de/overview#why">Warum EUCs?</a>
</li> </li>
<li> <li>
<A href="/de/overview#funktion">Funktionsweise</A> <a href="/de/overview#funktion">Funktionsweise</a>
</li> </li>
<li> <li>
<A href="/de/overview#begriffe">Begriffe</A> <a href="/de/overview#begriffe">Begriffe</a>
</li> </li>
<li> <li>
<A href="/de/overview#sicherheit">Sicherheit</A> <a href="/de/overview#sicherheit">Sicherheit</a>
</li> </li>
<li> <li>
<A href="/de/overview#ausrüstung">Ausrüstung</A> <a href="/de/overview#ausrüstung">Ausrüstung</a>
</li> </li>
<li> <li>
<A href="/de/overview#cutout">Cut-out's</A> <a href="/de/overview#cutout">Cut-out's</a>
</li> </li>
<li> <li>
<A href="/de/overview#akkuss">Akkusicherheit</A> <a href="/de/overview#akkuss">Akkusicherheit</a>
</li> </li>
<li> <li>
<A href="/de/overview#fahrweise">Fahrweise</A> <a href="/de/overview#fahrweise">Fahrweise</a>
</li> </li>
<li> <li>
<A href="/de/overview#wobbles">Wobbles</A> <a href="/de/overview#wobbles">Wobbles</a>
</li> </li>
<li> <li>
<A href="/de/overview#leistung">Leistung</A> <a href="/de/overview#leistung">Leistung</a>
</li> </li>
<li> <li>
<A href="/de/overview#federung">Federung</A> <a href="/de/overview#federung">Federung</a>
</li> </li>
<li> <li>
<A href="/de/overview#reifen">Reifen</A> <a href="/de/overview#reifen">Reifen</a>
</li> </li>
<li> <li>
<A href="/de/overview#historie">Historie</A> <a href="/de/overview#historie">Historie</a>
</li> </li>
<li> <li>
<A href="/de/overview#geräte">Geräte Liste</A> <a href="/de/overview#geraete">Geräte Liste</a>
</li> </li>
</ol> </ol>
<A href="/de/manufacturers"> <a href="/de/manufacturers">
<FontAwesomeIcon icon={faBookOpen} /> Hersteller <FontAwesomeIcon icon={faBookOpen} /> Hersteller
</A> </a>
<button onClick={() => setLightMode((e) => !e)}> <a href="/de/imprint">
{lightMode() ? "Dark Mode " : "Light Mode "} <FontAwesomeIcon icon={faGavel} /> Impressum
<FontAwesomeIcon icon={faCircleHalfStroke} /> </a>
</button>
<button onClick={() => navigate("/en/overview")}> <div class="modes">
Englisch <FontAwesomeIcon icon={faGlobe} /> <button
</button> onClick={() => {
<button onClick={() => setMenu(false)}> const mode = !lightMode() ? "?lightMode=true" : "";
Close <FontAwesomeIcon icon={faXmark} /> const url = location.pathname + mode;
</button> navigate(url, {
replace: true,
scroll: false,
});
}}
>
{lightMode() ? "Dark Mode " : "Light Mode "}
<FontAwesomeIcon icon={faCircleHalfStroke} />
</button>
<button
onClick={() =>
navigate("/en" + location.pathname.slice(3), { scroll: false })
}
>
Englisch <FontAwesomeIcon icon={faGlobe} />
</button>
<button onClick={() => setMenu(false)}>
Close <FontAwesomeIcon icon={faXmark} />
</button>
</div>
</div> </div>
<div <button class="menu" title="Menu" onClick={() => setMenu(true)}>
id="sidenavbar" <FontAwesomeIcon icon={faBars} />
style={{ visibility: menu() ? "hidden" : "visible" }} </button>
>
<button onClick={() => navigate(-1)}>Zurück</button>
<A href="#start">Start</A>
<button onClick={() => setMenu(true)}>Menu</button>
</div>
</> </>
); );
} }

View file

@ -1,100 +1,157 @@
import { import {
faBars,
faBookOpen, faBookOpen,
faCircleHalfStroke, faCircleHalfStroke,
faGavel,
faGlobe, faGlobe,
faXmark, faXmark,
} from "@fortawesome/pro-regular-svg-icons"; } from "@fortawesome/pro-regular-svg-icons";
import { createSignal } from "solid-js"; import {
import { A, useNavigate } from "solid-start"; useIsRouting,
useLocation,
useNavigate,
useSearchParams,
} from "@solidjs/router";
import { createEffect, createSignal, onCleanup } from "solid-js";
import { FontAwesomeIcon } from "../FontAwesomeIcon"; import { FontAwesomeIcon } from "../FontAwesomeIcon";
export const [lightMode, setLightMode] = createSignal(false); export const [lightMode, setLightMode] = createSignal(false);
const [menu, setMenu] = createSignal(false);
function Navbar() { function Navbar() {
const [menu, setMenu] = createSignal(false);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
const [searchParams] = useSearchParams();
const isRouting = useIsRouting();
createEffect(() => {
const mode = searchParams.lightMode;
const prefersDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (typeof mode === "undefined") {
setLightMode(!prefersDarkMode);
return;
}
const parsedMode = JSON.parse(mode);
if (typeof parsedMode !== "boolean") return;
setLightMode(parsedMode);
});
createEffect(() => {
if (!isRouting() || !menu()) return;
setMenu(false);
});
const handleKeyDown = (event: KeyboardEvent) => {
if (!menu() || "Escape" != event.key) return;
event.preventDefault();
setMenu(false);
};
createEffect(() => {
window.addEventListener("keydown", handleKeyDown);
onCleanup(() => {
window.removeEventListener("keydown", handleKeyDown);
});
});
return ( return (
<> <>
<div id="navbar" style={{ visibility: menu() ? "visible" : "hidden" }}> <div id="navbar" style={{ visibility: menu() ? "visible" : "hidden" }}>
<A href="/en/"> <a href="/en">
<FontAwesomeIcon icon={faBookOpen} /> Introduction <FontAwesomeIcon icon={faBookOpen} /> Introduction
</A> </a>
<A href="/en/overview"> <a href="/en/overview">
<FontAwesomeIcon icon={faBookOpen} /> Start <FontAwesomeIcon icon={faBookOpen} /> Start
</A> </a>
<ol> <ol>
<li> <li>
<A href="/en/overview#start">What are EUCs?</A> <a href="/en/overview#start">What are EUCs?</a>
</li> </li>
<li> <li>
<A href="/en/overview#why">Why EUCs?</A> <a href="/en/overview#why">Why EUCs?</a>
</li> </li>
<li> <li>
<A href="/en/overview#funktion">Functionality</A> <a href="/en/overview#funktion">Functionality</a>
</li> </li>
<li> <li>
<A href="/en/overview#begriffe">Glossarry</A> <a href="/en/overview#begriffe">Glossarry</a>
</li> </li>
<li> <li>
<A href="/en/overview#sicherheit">Safety</A> <a href="/en/overview#sicherheit">Safety</a>
</li> </li>
<li> <li>
<A href="/en/overview#ausrüstung">Gear</A> <a href="/en/overview#ausrüstung">Gear</a>
</li> </li>
<li> <li>
<A href="/en/overview#cutout">Cut-out's</A> <a href="/en/overview#cutout">Cut-out's</a>
</li> </li>
<li> <li>
<A href="/en/overview#akkuss">Battery safety</A> <a href="/en/overview#akkuss">Battery safety</a>
</li> </li>
<li> <li>
<A href="/en/overview#fahrweise">Ride style</A> <a href="/en/overview#fahrweise">Ride style</a>
</li> </li>
<li> <li>
<A href="/en/overview#wobbles">Wobbles</A> <a href="/en/overview#wobbles">Wobbles</a>
</li> </li>
<li> <li>
<A href="/en/overview#leistung">Performance</A> <a href="/en/overview#leistung">Performance</a>
</li> </li>
<li> <li>
<A href="/en/overview#federung">Suspension</A> <a href="/en/overview#federung">Suspension</a>
</li> </li>
<li> <li>
<A href="/en/overview#reifen">Tires</A> <a href="/en/overview#reifen">Tires</a>
</li> </li>
<li> <li>
<A href="/en/overview#historie">History</A> <a href="/en/overview#historie">History</a>
</li> </li>
<li> <li>
<A href="/en/overview#geräte">Device list</A> <a href="/en/overview#geraete">Device list</a>
</li> </li>
</ol> </ol>
<A href="/en/manufacturers"> <a href="/en/manufacturers">
<FontAwesomeIcon icon={faBookOpen} /> Manufacturers <FontAwesomeIcon icon={faBookOpen} /> Manufacturers
</A> </a>
<button onClick={() => setLightMode((e) => !e)}> <a href="/de/imprint">
{lightMode() ? "Dark Mode " : "Light Mode "} <FontAwesomeIcon icon={faGavel} /> Legal Notice (DE)
<FontAwesomeIcon icon={faCircleHalfStroke} /> </a>
</button>
<button onClick={() => navigate("/de/overview")}> <div class="modes">
Deutsch <FontAwesomeIcon icon={faGlobe} /> <button
</button> onClick={() => {
<button onClick={() => setMenu(false)}> const mode = !lightMode() ? "?lightMode=true" : "";
Close <FontAwesomeIcon icon={faXmark} /> const url = location.pathname + mode;
</button> navigate(url, {
replace: true,
scroll: false,
});
}}
>
{lightMode() ? "Dark Mode " : "Light Mode "}
<FontAwesomeIcon icon={faCircleHalfStroke} />
</button>
<button
onClick={() =>
navigate("/de" + location.pathname.slice(3), { scroll: false })
}
>
Deutsch <FontAwesomeIcon icon={faGlobe} />
</button>
<button onClick={() => setMenu(false)}>
Close <FontAwesomeIcon icon={faXmark} />
</button>
</div>
</div> </div>
<div <button class="menu" title="Menu" onClick={() => setMenu(true)}>
id="sidenavbar" <FontAwesomeIcon icon={faBars} />
style={{ visibility: menu() ? "hidden" : "visible" }} </button>
>
<button onClick={() => navigate(-1)}>Back</button>
<A href="#start">Start</A>
<button onClick={() => setMenu(true)}>Menu</button>
</div>
</> </>
); );
} }

View file

@ -1,3 +1,3 @@
import { mount, StartClient } from "solid-start/entry-client"; import { mount, StartClient } from "@solidjs/start/client";
mount(() => <StartClient />, document); mount(() => <StartClient />, document.getElementById("app")!);

View file

@ -1,9 +1,29 @@
import { import { StartServer, createHandler } from "@solidjs/start/server";
createHandler, import { getRequestEvent } from "solid-js/web";
renderAsync,
StartServer,
} from "solid-start/entry-server";
export default createHandler( export default createHandler(() => (
renderAsync((event) => <StartServer event={event} />), <StartServer
); document={({ assets, children, scripts }) => {
const event = getRequestEvent();
const pathname = event?.request.url
? new URL(event?.request.url).pathname
: "/";
return (
<html lang={pathname.startsWith("/de") ? "de" : "en"}>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
{assets}
</head>
<body id="app">
{children}
{scripts}
</body>
</html>
);
}}
/>
));

2
src/global.d.ts vendored
View file

@ -1 +1 @@
/// <reference types="solid-start/env" /> /// <reference types="@solidjs/start/env" />

View file

@ -1,115 +0,0 @@
// @refresh reload
import "@fortawesome/fontawesome-svg-core/styles.css";
import { Suspense } from "solid-js";
import {
FileRoutes,
Head,
Html,
Link,
Meta,
Routes,
Scripts,
Title,
useLocation,
} from "solid-start";
export default function Root() {
const location = useLocation();
return (
<Html lang={location.pathname.startsWith("/de") ? "de" : "en"}>
<Head>
<Link
rel="apple-touch-icon"
sizes="57x57"
href="/favicon/apple-icon-57x57.png"
/>
<Link
rel="apple-touch-icon"
sizes="60x60"
href="/favicon/apple-icon-60x60.png"
/>
<Link
rel="apple-touch-icon"
sizes="72x72"
href="/favicon/apple-icon-72x72.png"
/>
<Link
rel="apple-touch-icon"
sizes="76x76"
href="/favicon/apple-icon-76x76.png"
/>
<Link
rel="apple-touch-icon"
sizes="114x114"
href="/favicon/apple-icon-114x114.png"
/>
<Link
rel="apple-touch-icon"
sizes="120x120"
href="/favicon/apple-icon-120x120.png"
/>
<Link
rel="apple-touch-icon"
sizes="144x144"
href="/favicon/apple-icon-144x144.png"
/>
<Link
rel="apple-touch-icon"
sizes="152x152"
href="/favicon/apple-icon-152x152.png"
/>
<Link
rel="apple-touch-icon"
sizes="180x180"
href="/favicon/apple-icon-180x180.png"
/>
<Link
rel="icon"
type="image/png"
sizes="192x192"
href="/favicon/android-icon-192x192.png"
/>
<Link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon/favicon-32x32.png"
/>
<Link
rel="icon"
type="image/png"
sizes="96x96"
href="/favicon/favicon-96x96.png"
/>
<Link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon/favicon-16x16.png"
/>
<Link rel="manifest" href="/favicon/manifest.json" />
<Meta name="msapplication-TileColor" content="#ffffff" />
<Meta
name="msapplication-TileImage"
content="/favicon/ms-icon-144x144.png"
/>
<Meta name="theme-color" content="#ffffff" />
<Meta http-equiv="X-UA-Compatible" content="IE=edge" />
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta name="author" content="Julian Gerhardt" />
<Meta
name="keywords"
content="Elektrische einräder, EUC, Monowheels, Kingsong, Inmotion, Gotway"
/>
<Title>SolidStart - Bare</Title>
</Head>
<Suspense>
<Routes>
<FileRoutes />
</Routes>
</Suspense>
<Scripts />
</Html>
);
}

View file

@ -1,19 +1,26 @@
import { Title } from "solid-start"; import { Title } from "@solidjs/meta";
import { HttpStatusCode } from "solid-start/server"; import { useNavigate } from "@solidjs/router";
import { HttpStatusCode } from "@solidjs/start";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/overview.scss";
export default function NotFound() { export default function NotFound() {
const navigate = useNavigate();
return ( return (
<main> <Wrapper class="overview" classList={{ "light-mode": lightMode() }}>
<Title>Not Found</Title> <Title>Not Found</Title>
<HttpStatusCode code={404} /> <HttpStatusCode code={404} />
<h1>Page Not Found</h1> <Navbar />
<p> <div
Visit{" "} style={{
<a href="https://start.solidjs.com" target="_blank"> "min-height": "100vh",
start.solidjs.com display: "inline-block",
</a>{" "} }}
to learn how to build SolidStart apps. >
</p> <p style={{ "text-align": "center" }}>This side could not be found.</p>
</main> <button onClick={() => navigate(-1)}>Back</button>
</div>
</Wrapper>
); );
} }

View file

@ -1,226 +1,222 @@
import { Body, Link, Title, useNavigate } from "solid-start"; import { Title } from "@solidjs/meta";
import { lightMode } from "~/components/en/Navbar"; import AssetHandler from "~/components/Asset";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/devices.scss";
function KSS22() { function KSS22() {
const navigate = useNavigate(); const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="devices" classList={{ "light-mode": lightMode() }}>
<Title>KS S22</Title> <Title>KS S22</Title>
<Link rel="stylesheet" href="/styles/devices.css" /> <FullscreenView />
<Navbar />
<div id="sidenavbar"> <article>
<button onClick={() => navigate(-1)}>Zurück</button> <div>
<button onClick={() => navigate("/de/overview")}>Start</button> <h2>Kingsong S22</h2>
</div> <div class="righties">
<Asset src="/images/KSS22/S22shutterkode2.jpg" />
</div>
<div class="row"> <p>
<div class="col-4"> Das Kingsong S22, früher S20, ist ein klar Offroad und Trail
<img src="/images/KSS22/S22shutterkode2.jpg" /> orientiertes Einrad. Es hat unter anderem 130 mm travel und eine
robuste Metallkonstruktion, welches es einmalig ideal für große
Sprünge und hohe Drops macht.
</p>
<p>
Es ist der Nachfolger vom kleineren S18, aber mit doppeltem Akku und
50 % mehr Motor Leistung, so wie 70 statt 50 km/h top
Geschwindigkeit. Wobei der Freespin bis zu 114 km/h hoch ist, also
ideal für längere Sprünge bei denen der Reifen in der Luft ist.
</p>
<p>
Außerdem hat es gleich mitgeliefert einen Sitz, ziemlich brauchbare
Jump wie Powerpads und Spiked-Pedals. Dazu einen robusten, wenn auch
komisch platzierten und etwas kurzen Trolleyhandle, sowie einen
stabilen Kickstand und höhenverstellbare helle Lichter. Es ist
Wasserfest, aber nicht eintauchbar, und das Beste: es ist
superleicht daran zu arbeiten, weil das Gerät sehr modular designt
wurde. So lässt sich der Reifen mit theoretisch nur 2 schrauben
rausnehmen
</p>
<p>
Während all das wahr ist, haben sich leider mit diesem hoch
erwartetem und gehypten Rad auch viele Probleme ergeben. So gab es
Motorprobleme mit den ersten Geräten, welche zu cut-offs führten und
dadurch das Motherboard durchbrannten. Auch ist das Slider Design
sehr schwerfällig und über die Zeit immer schwerer zu bewegen. So
mussten viele s22 Käufer lange auf Ersatzmotoren warten, so wie für
100 bis 200 die Slider upgraden. Mit den Upgrades jedoch ist es
das momentan bester Suspension Einrad auf dem Markt. (Bis das
Veteran Sherman S zu kaufen ist.)
</p>
</div> </div>
<div class="col-8"> <div class="grid">
<article> <Asset src="/images/KSS22/S22shutterkode5.jpg" />
<h2>Kingsong S22</h2> <Asset class="span-2" src="/images/KSS22/BusJump.jpg" />
<Asset src="/images/KSS22/S22shutterkode4.jpg" />
<p>
Das Kingsong S22, früher S20, ist ein klar Offroad und Trail
orientiertes Einrad. Es hat unter anderem 130mm travel und eine
robuste Metallkonstruktion, welches es einmalig ideal für große
Sprünge und hohe Drops macht.
</p>
<p>
Es ist der Nachfolger vom kleineren S18, aber mit doppeltem Akku
und 50% mehr Motor Leistung, so wie 70 statt 50 km/h top
Geschwindigkeit. Wobei der Freespin bis zu 114 km/h hoch ist, also
ideal für längere Sprünge bei denen der Reifen in der Luft ist.
</p>
<p>
Außerdem hat es gleich mitgeliefert einen Sitz, ziemlich
brauchbare Jump wie Powerpads und Spiked-Pedals. Dazu einen
robusten, wenn auch komisch platzierten und etwas kurzen
Trolleyhandle, sowie einen stabilen Kickstand und
höhenverstellbare helle Lichter. Es ist Wasserfest, aber nicht
eintauchbar, und das Beste: es ist superleicht daran zu arbeiten,
weil das Gerät sehr modular designt wurde. So lässt sich der
Reifen mit theoretisch nur 2 schrauben rausnehmen
</p>
<p>
Während all das wahr ist, haben sich leider mit diesem hoch
erwartetem und gehypten Rad auch viele Probleme ergeben. So gab es
Motorprobleme mit den ersten Geräten, welche zu cut-offs führten
und dadurch das Motherboard durchbrannten. Auch ist das Slider
Design sehr schwerfällig und über die Zeit immer schwerer zu
bewegen. So mussten viele s22 Käufer lange auf Ersatzmotoren
warten, so wie für 100 bis 200 die Slider upgraden. Mit den
Upgrades jedoch ist es das momentan bester Suspension Einrad auf
dem Markt. (Bis das Veteran Sherman S zu kaufen ist.)
</p>
</article>
</div> </div>
</div>
<div class="row"> <table>
<div class="col-4"> <thead>
<img src="/images/KSS22/S22shutterkode5.jpg" /> <tr>
</div> <th>Eigenschaft</th>
<div class="col-4"> <th>Wert</th>
<img src="/images/KSS22/BusJump.jpg" /> </tr>
</div> </thead>
<div class="col-4"> <tbody>
<img src="/images/KSS22/S22shutterkode4.jpg" /> <tr>
</div> <td>Größe</td>
</div> <td>582L 330W 747H</td>
</tr>
<tr>
<td>Radumfang</td>
<td>20 inch</td>
</tr>
<tr>
<td>Pedalhöhe</td>
<td>231 &plusmn; 26 mm</td>
</tr>
<tr>
<td>Gewicht</td>
<td>35 kg</td>
</tr>
<tr>
<td>Suspension travel (bei Federung)</td>
<td>130 mm</td>
</tr>
<tr>
<td>Suspension Type (bei Federung)</td>
<td>Oil Shock</td>
</tr>
<tr>
<td>Suspension Adjustments (bei Federung)</td>
<td>Rebound, compression</td>
</tr>
<tr>
<td>Freespin</td>
<td>114 km/h</td>
</tr>
<tr>
<td>Top speed</td>
<td>70 km/h</td>
</tr>
<tr>
<td>Reichweite bei 30 km/h</td>
<td>200 km</td>
</tr>
<tr>
<td>Minimale Reichweite bei starker Nutzung</td>
<td>70 km</td>
</tr>
<tr>
<td>Max climb angle</td>
<td>45°</td>
</tr>
<tr>
<td>Max. Zuladung</td>
<td>120 kg</td>
</tr>
<table> <tr>
<tbody> <td>Motor Typ</td>
<tr> <td>High Speed</td>
<td>Größe</td> </tr>
<td>582L 330W 747H</td> <tr>
</tr> <td>Motor Leistung</td>
<tr> <td>3.300 W</td>
<td>Radumfang</td> </tr>
<td>20 inch</td> <tr>
</tr> <td>Peak Leistung</td>
<tr> <td>7.500 W</td>
<td>Pedalhöhe</td> </tr>
<td>231+-26mm</td> <tr>
</tr> <td>Battery Size</td>
<tr> <td>2.220 Wh</td>
<td>Gewicht</td> </tr>
<td>35kg</td> <tr>
</tr> <td>Voltage</td>
<tr> <td>126 V</td>
<td>Suspension travel (bei Federung)</td> </tr>
<td>130mm</td> <tr>
</tr> <td>Max amps</td>
<tr> <td>100 A</td>
<td>Suspension Type (bei Federung)</td> </tr>
<td>Oil Shock</td> <tr>
</tr> <td>BMS</td>
<tr> <td>Smart BMS</td>
<td>Suspension Adjustments (bei Federung)</td> </tr>
<td>Rebound, compression</td> <tr>
</tr> <td>Battery cell type</td>
<tr> <td>LG 18600</td>
<td>Freespin</td> </tr>
<td>114kmh</td> <tr>
</tr> <td>IP Rating</td>
<tr> <td>nope</td>
<td>Top speed</td> </tr>
<td>70kmh</td>
</tr>
<tr>
<td>Reichweite bei 30kmh</td>
<td>200km</td>
</tr>
<tr>
<td>Minimale Reichweite bei starker Nutzung</td>
<td>70km</td>
</tr>
<tr>
<td>Max climb angle</td>
<td>45°</td>
</tr>
<tr>
<td>Max. Zuladung</td>
<td>120kg</td>
</tr>
<tr> <tr>
<td>Motor Typ</td> <td>Accessoires</td>
<td>High Speed</td> <td>Powerpads, Jumppads, Seat, Spiked-Pedals</td>
</tr> </tr>
<tr> <tr>
<td>Motor Leistung</td> <td>Lichter</td>
<td>3300W</td> <td>8 x 5 W Verstellbare Scheinwerfer</td>
</tr> </tr>
<tr> <tr>
<td>Peak Leistung</td> <td>Standard Reifen</td>
<td>7500W</td> <td>Knobby (Noppenreifen)</td>
</tr> </tr>
<tr> <tr>
<td>Battery Size</td> <td>Anti spin button?</td>
<td>2220wh</td> <td>im Griff</td>
</tr> </tr>
<tr> <tr>
<td>Voltage</td> <td>Display?</td>
<td>126V</td> <td>Dot-Matrix</td>
</tr> </tr>
<tr> <tr>
<td>Max amps</td> <td>RGB?</td>
<td>100A</td> <td>Rücklicht</td>
</tr> </tr>
<tr> <tr>
<td>BMS</td> <td>Pads?</td>
<td>Smart BMS</td> <td>Alle inklusive</td>
</tr> </tr>
<tr> <tr>
<td>Battery cell type</td> <td>Ladeausgänge?</td>
<td>LG 18600</td> <td>nope</td>
</tr> </tr>
<tr> <tr>
<td>IP Rating</td> <td>Ladegerät:</td>
<td>nope</td> <td />
</tr> </tr>
<tr>
<tr> <td>Standard Ladezeit:</td>
<td>Accessoires</td> <td>3,3 h</td>
<td>Powerpads, Jumppads, Seat, Spiked-Pedals</td> </tr>
</tr> <tr>
<tr> <td>Max Amps:</td>
<td>Lichter</td> <td>10 A</td>
<td>8x5W Verstellbare Scheinwerfer</td> </tr>
</tr> <tr>
<tr> <td>Schnellste Ladezeit:</td>
<td>Standard Reifen</td> <td>100 Minuten</td>
<td>Nobby</td> </tr>
</tr> <tr>
<tr> <td>Ladeports:</td>
<td>Anti spin button?</td> <td>2</td>
<td>im Griff</td> </tr>
</tr> </tbody>
<tr> </table>
<td>Display?</td> </article>
<td>Dot-Matrix</td> </Wrapper>
</tr>
<tr>
<td>RGB?</td>
<td>Rücklicht</td>
</tr>
<tr>
<td>Pads?</td>
<td>Alle inklusive</td>
</tr>
<tr>
<td>Ladeausgänge?</td>
<td>nope</td>
</tr>
<tr>
<td>Ladegerät:</td>
<td />
</tr>
<tr>
<td>Standard Ladezeit:</td>
<td>3.3h</td>
</tr>
<tr>
<td>Max Amps:</td>
<td>10A</td>
</tr>
<tr>
<td>Schnellste Ladezeit:</td>
<td>100 Min</td>
</tr>
<tr>
<td>Ladeports:</td>
<td>2</td>
</tr>
</tbody>
</table>
</Body>
); );
} }

55
src/routes/de/imprint.tsx Normal file
View file

@ -0,0 +1,55 @@
import { Title } from "@solidjs/meta";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/overview.scss";
function imprint() {
return (
<Wrapper class="overview" classList={{ "light-mode": lightMode() }}>
<Title>Impressum</Title>
<Navbar />
<article
style={{
"min-height": "100vh",
display: "inline-block",
}}
>
<h1>Impressum</h1>
<h2>Verantwortlich für den Inhalt gemäß § 18 Abs. 1 MStV:</h2>
<p>Julian Gerhardt</p>
<h2>Technischer Ansprechpartner:</h2>
<p>
Aron Malcher
<br />
<br />
Unlimited Development
<br />
<br />
Brunnenstr. 12
<br />
48531 Nordhorn
<br />
Deutschland
<br />
<br />
E-Mail:{" "}
<a href="mailto:aron@unlimited-dev.de">aron@unlimited-dev.de</a>
</p>
<h2>Hinweis:</h2>
<p>
Die redaktionelle Verantwortung für die Inhalte der Webseite liegt bei
Julian Gerhardt. Technische Fragen und Anfragen richten Sie bitte an
den technischen Ansprechpartner von Unlimited Development, welche als
Hosting- und IT-Service agiert, jedoch nicht für den redaktionellen
Inhalt verantwortlich ist.
</p>
</article>
</Wrapper>
);
}
export default imprint;

View file

@ -1,14 +1,19 @@
import { faYoutube } from "@fortawesome/free-brands-svg-icons"; import { faYoutube } from "@fortawesome/free-brands-svg-icons";
import { faBookOpen, faGlobe } from "@fortawesome/pro-regular-svg-icons"; import { faBookOpen, faGlobe } from "@fortawesome/pro-regular-svg-icons";
import { A, Body, Link, Title } from "solid-start"; import { Title } from "@solidjs/meta";
import AssetHandler from "~/components/Asset";
import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"; import { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
import Wrapper from "~/components/Wrapper";
import { lightMode } from "~/components/de/Navbar"; import { lightMode } from "~/components/de/Navbar";
import "~/styles/start.scss";
function Introduction() { function Introduction() {
const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="start" classList={{ "light-mode": lightMode() }}>
<Title>Einführung</Title> <Title>Einführung</Title>
<Link rel="stylesheet" href="/styles/start.css" />
<FullscreenView />
<div class="container"> <div class="container">
<img id="cover" src="/images/Gear3.webp" /> <img id="cover" src="/images/Gear3.webp" />
@ -23,66 +28,52 @@ function Introduction() {
Flexible - Modern - schneller als die Polizei erlaubt. Das sind moderne Flexible - Modern - schneller als die Polizei erlaubt. Das sind moderne
eletrische Einräder. eletrische Einräder.
</p> </p>
<div class="righties"> <Asset src="/images/ShermanStanding.jpg" />
<img src="/images/ShermanStanding.jpg" />
</div>
<p> <p>
Von 0 auf 50kmh in 3s, 100kmh top Geschwindigkeit und 230km Reichweite Von 0 auf 50 km/h in 3 s, 100 km/h top Geschwindigkeit und 230 km
machen aus diesen Geräten den ultimativen Sport. Reichweite machen aus diesen Geräten den ultimativen Sport.
</p> </p>
<div class="righties"> <Asset src="/images/UltimativeSport.jpg" />
<img src="/images/UltimativeSport.jpg" />
</div>
<p> <p>
Gleichzeitig 50° steile Wände hochfahren und MTB Trails mit leichtigkeit Gleichzeitig 50° steile Wände hochfahren und MTB Trails mit leichtigkeit
nehmen. nehmen.
</p> </p>
<div class="righties"> <Asset src="/videos/MTBtrailsEase.mp4" />
<video width="auto" height="auto" autoplay muted loop>
<source src="/videos/MTBtrailsEase.mp4" type="video/mp4" />
</video>
</div>
<p>Jeden Weg nutzen und nie wieder im Verkehr stecken.</p> <p>Jeden Weg nutzen und nie wieder im Verkehr stecken.</p>
<div class="righties"> <Asset src="/videos/traffic.mp4" />
<video width="auto" height="auto" autoplay muted loop>
<source src="/videos/traffic.mp4" type="video/mp4" />
</video>
</div>
<p>Und trotzdem leicht zu transportiren und untern Tisch zu packen.</p> <p>Und trotzdem leicht zu transportiren und untern Tisch zu packen.</p>
<div class="righties"> <Asset src="/images/KidsKS16X.jpg" />
<img src="/images/KidsKS16X.jpg" />
</div>
<p>Interessiert? Dann tauche in die Welt der PEV's und EUC's ein:</p> <p>Interessiert? Dann tauche in die Welt der PEV's und EUC's ein:</p>
<A href="/de/overview"> <a href="/de/overview">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
Ich will alles darüber lesen! <FontAwesomeIcon icon={faBookOpen} /> Ich will alles darüber lesen! <FontAwesomeIcon icon={faBookOpen} />
</p> </p>
</div> </div>
</A> </a>
<A href="https:/youtube.com/playlist?list=PLfoxTRt1qLuAg-Al9JNHrl_7KVl-uSxwV"> <a href="https://youtube.com/playlist?list=PLfoxTRt1qLuAg-Al9JNHrl_7KVl-uSxwV">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
Mir reichen Videos <FontAwesomeIcon icon={faYoutube} /> Mir reichen Videos <FontAwesomeIcon icon={faYoutube} />
</p> </p>
</div> </div>
</A> </a>
<A href="/en/"> <a href="/en">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
Switch to English <FontAwesomeIcon icon={faGlobe} /> Switch to English <FontAwesomeIcon icon={faGlobe} />
</p> </p>
</div> </div>
</A> </a>
</Body> </Wrapper>
); );
} }

View file

@ -1,18 +1,23 @@
import { Body, Link, Title } from "solid-start"; import { Title } from "@solidjs/meta";
import AssetHandler from "~/components/Asset";
import R from "~/components/Reference"; import R from "~/components/Reference";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/de/Navbar"; import Navbar, { lightMode } from "~/components/de/Navbar";
import "~/styles/overview.scss";
function Manufacturers() { function Manufacturers() {
const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="overview" classList={{ "light-mode": lightMode() }}>
<Title>Hersteller</Title> <Title>Hersteller</Title>
<Link rel="stylesheet" href="/styles/overview.css" /> <FullscreenView />
<Navbar /> <Navbar />
<article> <article>
{/* {/*
<!--hersteller--> <!--hersteller-->
*/} */}
<div class="row"> <div>
<h3 id="manufacturers">Erklärung und Geschichte der Produzenten</h3> <h3 id="manufacturers">Erklärung und Geschichte der Produzenten</h3>
<p> <p>
Es gibt/gab viele Hersteller von elektrischen Einrädern, hier werden Es gibt/gab viele Hersteller von elektrischen Einrädern, hier werden
@ -24,17 +29,22 @@ function Manufacturers() {
</p> </p>
<h3 id="ninebot"> <h3 id="ninebot">
Ninebot <img class="logos" src="/images/ninebotLogo.jpg" /> Ninebot <img src="/images/ninebotLogo.jpg" />
</h3> </h3>
<img class="righties" src="/images/NineBot.webp" />
<img class="lefties" src="/images/NinebotZ10goood.webp" /> <div class="righties">
<Asset src="/images/NineBot.webp" />
</div>
<div class="lefties">
<Asset src="/images/NinebotZ10goood.webp" />
</div>
<p> <p>
Ninebot ist für die Meisten bekannt als Sooter Hersteller, manche Ninebot ist für die Meisten bekannt als Scooter Hersteller, manche
kenne auch vielleicht deren elektrische Schuhe oder die Segway kenne auch vielleicht deren elektrische Schuhe oder die Segway
ähnlichen Geräte mit kurzer Lenkstange. Ninebot ist die größte und ähnlichen Geräte mit kurzer Lenkstange. Ninebot ist die größte und
vielseitigste Firma der hier gelisteten. Sie experimentieren viel vielseitigste Firma der hier gelisteten. Sie experimentieren viel
herum, und haben bei den standard-Scootern viel Erfolg, aber leider herum, und haben bei den standard-Scootern viel Erfolg, aber leider
bei den Einrädern aufgegeben. So gibt es Heute nur wenige Modelle, bei den Einrädern aufgegeben. So gibt es heute nur wenige Modelle,
alle sind eher Anfängergeräte bis untere Mittelklasse. Trotzdem hat alle sind eher Anfängergeräte bis untere Mittelklasse. Trotzdem hat
Ninebot vor allem durch das Ninebot Z10 ein ikonisches Gerät auf dem Ninebot vor allem durch das Ninebot Z10 ein ikonisches Gerät auf dem
Markt hinterlassen, welches durch außergewöhnliches Design und Markt hinterlassen, welches durch außergewöhnliches Design und
@ -42,91 +52,103 @@ function Manufacturers() {
</p> </p>
<h3 id="inmotion"> <h3 id="inmotion">
Inmotion <img class="logos" src="/images/inmotionLogo.png" /> Inmotion <img src="/images/inmotionLogo.png" />
</h3> </h3>
<img class="righties" src="/images/InmotionLineup.jpg" /> <div class="righties">
<img class="lefties" src="/images/V11 3.webp" /> <Asset src="/images/InmotionLineup.jpg" />
</div>
<div class="lefties">
<Asset src="/images/V11 3.webp" />
</div>
<p> <p>
Inmotion ist der zweitgrößte Hersteller der hier gelisteten. Inmotion ist der zweitgrößte Hersteller der hier gelisteten.
Ebenfallsgroß im standard-Scooter Segment, hat Inmotion aber auch Ebenfalls groß im standard-Scooter Segment, hat Inmotion aber auch
einen großen wenn nicht den größten Marktanteil an EUCs. Vor allen einen großen, wenn nicht den größten Marktanteil an EUCs. Vor allen
das Inmotion V8 hat als einsteiger und Commuter Gerät eine hohe das Inmotion V8 hat als Einsteiger und Commuter Gerät eine hohe
Beliebtheit und somit hohe Verkaufszahlen. Auch war es Inmotion, Beliebtheit und somit hohe Verkaufszahlen. Auch war es Inmotion,
welches das äußerst professionell aussehende erste Suspension EUC welches das äußerst professionell aussehende erste Suspension EUC
V11 auf den Markt brachte. Inmotion steht im allgemeinen für V11 auf den Markt brachte. Inmotion steht im Allgemeinen für
Qualität, Design und Sicherheit dank gutem{" "} Qualität, Design und Sicherheit dank gutem{" "}
<R href="#tiltback">Tiltback</R> und hoher Sicherheitsmarge. Aber <R href="#tiltback">Tiltback</R> und hoher Sicherheitsmarge. Aber
das alles im Tausch gegen Performance. Bis vor kurzem war Inmotion das alles im Tausch gegen Performance. Bis vor kurzem war Inmotion
Synonym für schwach und wenig Reichweite. Das änderte sich, als das Synonym für schwach und wenig Reichweite. Das änderte sich, als das
V12 rauskam und bald das V13 rauskommt. Jetzt erhofft man sich V12 rauskam und bald das V13 rauskommt. Jetzt erhofft man sich
sichere und gut designte 90+kmh mit hoher Sicherheitsmarge, und sichere und gut designte 90+ km/h mit hoher Sicherheitsmarge, und
sollte das V13 funktionieren wie erhofft wird es das Image der Firma sollte das V13 funktionieren wie erhofft wird es das Image der Firma
ändern. ändern.
</p> </p>
<h3 id="kingsong"> <h3 id="kingsong">
Kingsong <img class="logos" src="/images/kingsongLogo.png" /> Kingsong <img src="/images/kingsongLogo.png" />
</h3> </h3>
<img class="righties" src="/images/KidsKS16X.jpg" /> <div class="righties">
<img class="lefties" src="/images/kingsong2.jpg" /> <Asset src="/images/KidsKS16X.jpg" />
</div>
<div class="lefties">
<Asset src="/images/kingsong2.jpg" />
</div>
<p> <p>
Kingsong ist sehr ähnlich zu Inmotion, nur kleiner und ohne den Kingsong ist sehr ähnlich zu Inmotion, nur kleiner und ohne den
großen Scooter und E-bike Markt dahinter. Qualität und Design waren großen Scooter und E-Bike Markt dahinter. Qualität und Design waren
die Merkmale, so wie Langlebigkeit und Robustheit. Mit dem S18 war die Merkmale, so wie Langlebigkeit und Robustheit. Mit dem S18 war
Kingsong auch einer der ersten Firmen mit Federung für EUCs. Kingsong auch einer der ersten Firmen mit Federung für EUCs.
Kingsong pionierte das heute oft genutze Schwingarm Design für Kingsong pionierte das heute oft genutzte Schwingarm Design für
Federungen. Aber mit dem S18, und später S20 hat das Image etwas Federungen. Aber mit dem S18, und später S20 hat das Image etwas
Schaden genommen. Beide Geräte hatten große Proble am Anfang, bis Schaden genommen. Beide Geräte hatten große Problem am Anfang, bis
hin zum abbrennen des S20 Prototypen. Trotzdem waren beide Geräte hin zum Abbrennen des S20 Prototypen. Trotzdem waren beide Geräte
ein großer Erfolg, und die Fehler wurden größtenteils behoben. ein großer Erfolg, und die Fehler wurden größtenteils behoben.
Kingsong ist ebenfals bekannt für die extrem guten{" "} Kingsong ist ebenfalls bekannt für die extrem guten{" "}
<R href="#trolley">Trolley Handle</R>, wie der beim KS 16X und <R href="#trolley">Trolley Handle</R>, wie der beim KS 16X und
voherigen Modellen. vorherigen Modellen.
</p> </p>
<h3 id="begode"> <h3 id="begode">
Gotway/Begode <img class="logos" src="/images/BEGODElogo.jpg" /> Gotway/Begode <img src="/images/BEGODElogo.jpg" />
</h3> </h3>
<img class="righties" src="/images/BegodeLineup.jpg" /> <div class="righties">
<img class="lefties" src="/images/BegodeMemeBurn.jpg" /> <Asset src="/images/BegodeLineup.jpg" />
</div>
<div class="lefties">
<Asset src="/images/BegodeMemeBurn.jpg" />
</div>
<p> <p>
Gotway, oder wie sie sich heute nennen Begode, ist schwer zu Gotway, oder wie sie sich heute nennen, Begode, ist schwer zu
beschreiben und einzuordnen. Viele Meinungen und Kontroversen. Die beschreiben und einzuordnen. Viele Meinungen und Kontroversen. Die
Firma wurde nach allen oben genannten gegründet, und wie im Kapitel{" "} Firma wurde nach allen oben genannten gegründet, und wie im Kapitel{" "}
<R href="#historie">Historie</R> zu lesen, hatten sie den Fokus <R href="#historie">Historie</R> zu lesen, hatten sie den Fokus
gleich auf Leistung gesetzt. Das Design und die Qualität waren am gleich auf Leistung gesetzt. Das Design und die Qualität waren am
Anfang und auch eigentlich bis vor kurzem grauenvoll. Aber sie waren Anfang und auch eigentlich bis vor kurzem grauenvoll. Aber sie waren
die ersten die 40kmh, dann 50, dann 60, dann 70, dann 80 und heute die ersten die 40 km/h, dann 50, dann 60, dann 70, dann 80 und heute
100kmh erreichen können, sie sind die die <R href="#wh">4800wh</R>{" "} 100 km/h erreichen können, sie sind die die{" "}
in ein Gerät packen, egal wies aussieht oder wie schwer es ist. <R href="#wh">4.800 Wh</R> in ein Gerät packen, egal wies aussieht
Gotway hat aktiv die grenzen des Sports und der Einräder nach vorne oder wie schwer es ist. Gotway hat aktiv die Grenzen des Sports und
gebracht. Immer wenn ein neues schnelleres Gerät raus kam hieß es, der Einräder nach vorne gebracht. Immer wenn ein neues schnelleres
ach wer fährt denn schon 40kmh mit so nem Teil. Heute ist 40kmh die Gerät rauskam, hieß es, ach wer fährt denn schon 40 km/h mit so
mittel Geschwindigkeit, und es wird 70+ erwartet. Auch typisch einem Teil. Heute ist 40 km/h die mittel Geschwindigkeit, und es
Begode ist es, durch bis zu 7+ neue Geräte im Jahr die eigenen wird 70+ erwartet. Auch typisch Begode ist es, durch bis zu 7+ neue
Geräte schnell veralten zu lassen. Kingsong und Inmotion bringen Geräte im Jahr die eigenen Geräte schnell veralten zu lassen.
meist 1 Gerät pro jahr raus. Kingsong und Inmotion bringen meist 1 Gerät pro Jahr raus.
</p> </p>
<p> <p>
Durch die fehlende Qualität, die fehlenden Sicherheitesmaßnahmen und Durch die fehlende Qualität, die fehlenden Sicherheitsmaßnahmen und
minimalen <R href="#BMS">BMSs</R> die Gotway verbaute kam es in der minimalen <R href="#BMS">BMSs</R> die Gotway verbaute kam es in der
Vergangenheit all zu oft zu <R href="#akkuss">Akkubränden</R>, wofür Vergangenheit allzu oft zu <R href="#akkuss">Akkubränden</R>, wofür
Begode auch in der ganzen Community bekannt ist. Dazu gibt es da die Begode auch in der ganzen Community bekannt ist. Dazu gibt es da die
fehlende Kommunikation mit der Community und fehlende Reaktion auf fehlende Kommunikation mit der Community und fehlende Reaktion auf
Fehler der Geräte. Trotzdem war Begode die erste Firma die Fehler der Geräte. Trotzdem war Begode die erste Firma die
standardmäßig <R href="#spiked-pedals">Spiked-pedals</R> verbaute, standardmäßig <R href="#spiked-pedals">Spiked-pedals</R> verbaute,
was ein Wunsch der der Community war und welche bis heute die besten was ein Wunsch, der der Community war und welche bis heute die
mitgelieferten Spiked-pedals sind. Alle anderen Firmen zogen mit besten mitgelieferten Spiked-pedals sind. Alle anderen Firmen zogen
schlechteren Versionen nach, was normalerweise von Begode erwartet mit schlechteren Versionen nach, was normalerweise von Begode
wird. Begode waren die ersten, die von 84V auf 100V umstiegen, und erwartet wird. Begode waren die ersten, die von 84 V auf 100 V
neuerdings auch auf 134V, welches ungesehene Leistung bereitstellt. umstiegen, und neuerdings auch auf 134 V, welches ungesehene
Wieder ziehen die anderen Hersteller langsam nach, und haben Leistung bereitstellt. Wieder ziehen die anderen Hersteller langsam
trotzdem schwächere Geräte. Die neue Generation von Begode hat nach, und haben trotzdem schwächere Geräte. Die neue Generation von
besseres, fast gutes Design und in manchen Aspekten auch bessere Begode hat besseres, fast gutes Design und in manchen Aspekten auch
Federungen als die Konkurrenz, trotzdem brechen die (völlig bessere Federungen als die Konkurrenz, trotzdem brechen die (völlig
freiliegenden) Batterie Befestigungen leicht ab und man muss sich freiliegenden) Batterie Befestigungen leicht ab und man muss sich
DIY Lösungen kaufen um weiter fahren zu können (bei fast 5000 DIY-Lösungen kaufen, um weiter fahren zu können (bei fast 5.000
Geräten). Geräten).
</p> </p>
@ -136,23 +158,26 @@ function Manufacturers() {
</p> </p>
<h3 id="veteran"> <h3 id="veteran">
Leaperkim/Veteran{" "} Leaperkim/Veteran <img src="/images/veteranLogo.png" />
<img class="logos" src="/images/veteranLogo.png" />
</h3> </h3>
<img class="righties" src="/images/Shermangrey.jpg" /> <div class="righties">
<img class="lefties" src="/images/abrahams.jpg" /> <Asset src="/images/Shermangrey.jpg" />
</div>
<div class="lefties">
<Asset src="/images/abrahams.jpg" />
</div>
<p> <p>
Veteran ist für viele der Lieling. Bestehend aus Ex Gotway Veteran ist für viele der Liebling. Bestehend aus Ex Gotway
Ingenieuren und Mitarbeitern, die mit den Entscheidungen von Gotway Ingenieuren und Mitarbeitern, die mit den Entscheidungen von Gotway
nicht einverstanden waren, brachte Veteran 2020 als erstes Gerät das nicht einverstanden waren, brachte Veteran 2020 als erstes Gerät das
Veteran Sherman raus. Und es Schlug ein wie eine Bombe, es war ein Veteran Sherman raus. Und es schlug ein wie eine Bombe, es war ein
voller Erfolg. Das Robuste, fast militärische Design zusammen mit voller Erfolg. Das Robuste, fast militärische Design zusammen mit
der hohen stabilen Geschwindigkeit und der großen Reichweite sorgte der hohen stabilen Geschwindigkeit und der großen Reichweite sorgte
für eine starke Beliebtheit, auch Heute noch und sogar außerhalb der für eine starke Beliebtheit, auch heute noch und sogar außerhalb der
EUC Community. Allein dieses Gerät und der Kontent dazu brachte eine EUC-Community. Allein dieses Gerät und der Content dazu brachte eine
ganze Welle an neuen Fahrern zum Sport. Schnell war Veteran in den ganze Welle an neuen Fahrern zum Sport. Schnell war Veteran in den
Köpfen als robust, zuverlässig und schnell eingespeichert. Als dann Köpfen als robust, zuverlässig und schnell eingespeichert. Als dann
das neue Modell Veteran Abrahams mit größerem Reifen angeküdigt das neue Modell Veteran Abrahams mit größerem Reifen angekündigt
wurde, war der Hype groß. Doch als es dann raus kam gab es große wurde, war der Hype groß. Doch als es dann raus kam gab es große
Enttäuschungen, das Gerät hat in jeder Hinsicht versagt und war dazu Enttäuschungen, das Gerät hat in jeder Hinsicht versagt und war dazu
sehr anfällig für <R href="#cutout">Cut-outs</R>. Danach war das sehr anfällig für <R href="#cutout">Cut-outs</R>. Danach war das
@ -164,23 +189,23 @@ function Manufacturers() {
Veteran scheint aus den Fehlern mit dem Abrahams gelernt zu haben, Veteran scheint aus den Fehlern mit dem Abrahams gelernt zu haben,
denn mit dem neusten Release des Sherman S haben sie ein weiteres denn mit dem neusten Release des Sherman S haben sie ein weiteres
vielversprechenden Gerät vorgestellt. Vollständige Metall vielversprechenden Gerät vorgestellt. Vollständige Metall
Konsstruktion, weltklasse Federung, Großer Akku und genug Leistung. Konstruktion, Weltklasse Federung, Großer Akku und genug Leistung.
</p> </p>
<h3 id="extremebull">Extreme Bull</h3> <h3 id="extremebull">Extreme Bull</h3>
<p> <p>
Bei Extreme Bull ist nicht alles ganz klar. Es scheint eine Bei Extreme Bull ist nicht alles ganz klar. Es scheint eine
Untermarke von Begode zu sein, die noch dreister andere Geräte Untermarke von Begode zu sein, die noch dreister andere Geräte
kopiert und in billger anbietet als es Begode tut. Man sieht kaum kopiert und in billiger anbietet als es Begode tut. Man sieht kaum
Geräte von Extreme Bull herumfahren, und viele Verkäufer bieten die Geräte von Extreme Bull herumfahren, und viele Verkäufer bieten die
auch gar nicht erst an. Aber seit kurzem gibt es Gerüchte über eine auch gar nicht erst an. Aber seit kurzem gibt es Gerüchte über eine
Sherman S Kopie namens Commander Pro. Sollten die Gerüchte stimmen Sherman S Kopie namens Commander Pro. Sollten die Gerüchte stimmen
und das Gerät halten was es verspricht, könnte Extreme Bull auf dem und das Gerät halten, was es verspricht, könnte Extreme Bull auf dem
Vormarsch sein. Vormarsch sein.
</p> </p>
</div> </div>
</article> </article>
</Body> </Wrapper>
); );
} }

File diff suppressed because it is too large Load diff

View file

@ -1,218 +1,220 @@
import { Body, Link, Title } from "solid-start"; import { Title } from "@solidjs/meta";
import { lightMode } from "~/components/en/Navbar"; import AssetHandler from "~/components/Asset";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/devices.scss";
function KSS22() { function KSS22() {
const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="devices" classList={{ "light-mode": lightMode() }}>
<Title>KS S22</Title> <Title>KS S22</Title>
<Link rel="stylesheet" href="/styles/devices.css" /> <FullscreenView />
{/* <Navbar /> */} <Navbar />
<div class="row"> <article>
<div class="col-4"> <div>
<img src="/images/KSS22/S22shutterkode2.jpg" /> <h2>Kingsong S22</h2>
<div class="righties">
<Asset src="/images/KSS22/S22shutterkode2.jpg" />
</div>
<p>
The Kingsong S22, formerly S20, is a clearly off-road and
trail-oriented unicycle. Among other things, it has 130 mm
suspension travel and a robust metal construction, which makes it
ideal for big jumps and high drops.
</p>
<p>
It is the successor to the smaller S18, but with double the battery
and 50 % more motor power, such as a top speed of 70 instead of 50
km/h. The freespin is up to 114 km/h, so ideal for longer jumps
where the tire is spinning up in the air.
</p>
<p>
It also comes with a seat, pretty good jump- and power pads and
spiked pedals. Plus, a sturdy, albeit oddly placed and somewhat
short trolley handle, as well as a sturdy kickstand and
height-adjustable bright lights. It's waterproof, but not
submersible, and best of all, it's super easy to work with because
the device has a very modular design. The tire can theoretically be
removed with just 2 screws
</p>
<p>
While all of this is true, many problems have unfortunately arisen
with this highly anticipated and hyped wheel. There were motor
problems with the first devices, which led to cut-offs and burned
the motherboard. Also, the slider design is very clumsy and gets
harder and harder to move over time. Many S22 buyers had to wait a
long time for replacement motors, such as upgrading the sliders for
100 to 200 . However, with the upgrades, it is currently the best
suspension unicycle on the market. (Until the Veteran Sherman S goes
on sale.)
</p>
</div> </div>
<div class="col-8"> <div class="grid">
<article> <Asset src="/images/KSS22/S22shutterkode5.jpg" />
<h2>Kingsong S22</h2> <Asset class="span-2" src="/images/KSS22/BusJump.jpg" />
<Asset src="/images/KSS22/S22shutterkode4.jpg" />
<p>
The Kingsong S22, formerly S20, is a clearly off-road and trail
oriented unicycle. Among other things, it has 130mm suspension
travel and a robust metal construction, which makes it ideal for
big jumps and high drops.
</p>
<p>
It is the successor to the smaller S18, but with double the
battery and 50% more motor power, such as a top speed of 70
instead of 50 km/h. The freespin is up to 114 km/h, so ideal for
longer jumps where the tire is spinning up in the air.
</p>
<p>
It also comes with a seat, pretty good jump- and power pads and
spiked pedals. Plus a sturdy, albeit oddly placed and somewhat
short trolley handle, as well as a sturdy kickstand and
height-adjustable bright lights. It's waterproof, but not
submersible, and best of all, it's super easy to work with because
the device has a very modular design. The tire can theoretically
be removed with just 2 screws
</p>
<p>
While all of this is true, many problems have unfortunately arisen
with this highly anticipated and hyped wheel. There were motor
problems with the first devices, which led to cut-offs and burned
the motherboard. Also, the slider design is very clumsy and gets
harder and harder to move over time. Many S22 buyers had to wait a
long time for replacement motors, such as upgrading the sliders
for 100 to 200. However, with the upgrades, it is currently the
best suspension unicycle on the market. (Until the Veteran Sherman
S goes on sale.)
</p>
</article>
</div> </div>
</div>
<div class="row"> <table>
<div class="col-4"> <thead>
<img src="/images/KSS22/S22shutterkode5.jpg" /> <tr>
</div> <th>Attribute</th>
<div class="col-4"> <th>Value</th>
<img src="/images/KSS22/BusJump.jpg" /> </tr>
</div> </thead>
<div class="col-4"> <tbody>
<img src="/images/KSS22/S22shutterkode4.jpg" /> <tr>
</div> <td>Size</td>
</div> <td>582L 330W 747H</td>
</tr>
<table> <tr>
<tbody> <td>Wheel Circumference</td>
<tr> <td>20 inches</td>
<td>Size</td> </tr>
<td>582L 330W 747H</td> <tr>
</tr> <td>Pedal Height</td>
<tr> <td>231 &plusmn; 26 mm</td>
<td>Wheel Circumference</td> </tr>
<td>20 inches</td> <tr>
</tr> <td>Weight</td>
<tr> <td>35 kg</td>
<td>Pedal Height</td> </tr>
<td>231+-26mm</td> <tr>
</tr> <td>Suspension travel</td>
<tr> <td>130 mm</td>
<td>Weight</td> </tr>
<td>35kg</td> <tr>
</tr> <td>Suspension Type</td>
<tr> <td>Oil Shock</td>
<td>Suspension travel</td> </tr>
<td>130mm</td> <tr>
</tr> <td>Suspension Adjustments (for suspension)</td>
<tr> <td>Rebound, compression</td>
<td>Suspension Type</td> </tr>
<td>Oil Shock</td> <tr>
</tr> <td>Free Spin</td>
<tr> <td>114 km/h</td>
<td>Suspension Adjustments (for suspension)</td> </tr>
<td>Rebound, compression</td> <tr>
</tr> <td>Top speed</td>
<tr> <td>70 km/h</td>
<td>Free Spin</td> </tr>
<td>114kmh</td> <tr>
</tr> <td>Range at 30 km/h</td>
<tr> <td>200 km</td>
<td>Top speed</td> </tr>
<td>70kmh</td> <tr>
</tr> <td>Minimum range for heavy use</td>
<tr> <td>70 km</td>
<td>Range at 30kmh</td> </tr>
<td>200km</td> <tr>
</tr> <td>Max climb angle</td>
<tr> <td>45°</td>
<td>Minimum range for heavy use</td> </tr>
<td>70km</td> <tr>
</tr> <td>Max. payload</td>
<tr> <td>120 kg</td>
<td>Max climb angle</td> </tr>
<td>45°</td> <tr>
</tr> <td>Engine Type</td>
<tr> <td>High Speed</td>
<td>Max. payload</td> </tr>
<td>120kg</td> <tr>
</tr> <td>Engine Power</td>
<tr> <td>3,300 W</td>
<td>Engine Type</td> </tr>
<td>High Speed</td> <tr>
</tr> <td>Peak Power</td>
<tr> <td>7,500 W</td>
<td>Engine Power</td> </tr>
<td>3300W</td> <tr>
</tr> <td>Battery Size</td>
<tr> <td>2,220 Wh</td>
<td>Peak Power</td> </tr>
<td>7500W</td> <tr>
</tr> <td>Voltage</td>
<tr> <td>126 V</td>
<td>Battery Size</td> </tr>
<td>2220wh</td> <tr>
</tr> <td>Max amps</td>
<tr> <td>100 A</td>
<td>Voltage</td> </tr>
<td>126V</td> <tr>
</tr> <td>BMS</td>
<tr> <td>Smart BMS</td>
<td>Max amps</td> </tr>
<td>100A</td> <tr>
</tr> <td>Battery cell type</td>
<tr> <td>LG 18600</td>
<td>BMS</td> </tr>
<td>Smart BMS</td> <tr>
</tr> <td>IP-Rating</td>
<tr> <td>nope</td>
<td>Battery cell type</td> </tr>
<td>LG 18600</td> <tr>
</tr> <td>Accessories</td>
<tr> <td>Powerpads, Jumppads, Seat, Spiked Pedals</td>
<td>IPRating</td> </tr>
<td>nope</td> <tr>
</tr> <td>Lights</td>
<tr> <td>8 x 5 W adjustable headlights</td>
<td>Accessories</td> </tr>
<td>Powerpads, Jumppads, Seat, Spiked Pedals</td> <tr>
</tr> <td>Default tires</td>
<tr> <td>Knobby</td>
<td>Lights</td> </tr>
<td>8x5W adjustable headlights</td> <tr>
</tr> <td>Anti spin button?</td>
<tr> <td>under control</td>
<td>Default tires</td> </tr>
<td>Nobby</td> <tr>
</tr> <td>Display?</td>
<tr> <td>dot matrix</td>
<td>Anti spin button?</td> </tr>
<td>under control</td> <tr>
</tr> <td>RGB?</td>
<tr> <td>Taillight</td>
<td>Display?</td> </tr>
<td>dot matrix</td> <tr>
</tr> <td>Pads?</td>
<tr> <td>All inclusive</td>
<td>RGB?</td> </tr>
<td>Taillight</td> <tr>
</tr> <td>Charge outlets?</td>
<tr> <td>nope</td>
<td>Pads?</td> </tr>
<td>All inclusive</td> <tr>
</tr> <td>Charger:</td>
<tr> <td />
<td>Charge outlets?</td> </tr>
<td>nope</td> <tr>
</tr> <td>Default load time:</td>
<tr> <td>3.3 h</td>
<td>Charger:</td> </tr>
<td /> <tr>
</tr> <td>Max Amps:</td>
<tr> <td>10 A</td>
<td>Default load time:</td> </tr>
<td>3.3h</td> <tr>
</tr> <td>Fastest load time:</td>
<tr> <td>100 minutes</td>
<td>Max Amps:</td> </tr>
<td>10A</td> <tr>
</tr> <td>Load ports:</td>
<tr> <td>2</td>
<td>Fastest load time:</td> </tr>
<td>100min</td> </tbody>
</tr> </table>
<tr> </article>
<td>Load ports:</td> </Wrapper>
<td>2</td>
</tr>
</tbody>
</table>
</Body>
); );
} }

View file

@ -1,14 +1,18 @@
import { faYoutube } from "@fortawesome/free-brands-svg-icons"; import { faYoutube } from "@fortawesome/free-brands-svg-icons";
import { faBookOpen, faGlobe } from "@fortawesome/pro-regular-svg-icons"; import { faBookOpen, faGlobe } from "@fortawesome/pro-regular-svg-icons";
import { A, Body, Link, Title } from "solid-start"; import { Title } from "@solidjs/meta";
import AssetHandler from "~/components/Asset";
import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"; import { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
import Wrapper from "~/components/Wrapper";
import { lightMode } from "~/components/en/Navbar"; import { lightMode } from "~/components/en/Navbar";
import "~/styles/start.scss";
function Introduction() { function Introduction() {
const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="start" classList={{ "light-mode": lightMode() }}>
<Title>Introduction</Title> <Title>Introduction</Title>
<Link rel="stylesheet" href="/styles/start.css" /> <FullscreenView />
<div class="container"> <div class="container">
<img id="cover" src="/images/Gear3.webp" /> <img id="cover" src="/images/Gear3.webp" />
@ -24,68 +28,54 @@ function Introduction() {
unicycles: unicycles:
</p> </p>
<div class="righties"> <Asset src="/images/ShermanStanding.jpg" />
<img src="/images/ShermanStanding.jpg" />
</div>
<p> <p>
From 0 auf 50kmh in 3s, 100kmh top speed and 230km range make these From 0 auf 50 km/h in 3 s, 100 km/h top speed and 230 km range make
devices the ultimate sport. these devices the ultimate sport.
</p> </p>
<div class="righties"> <Asset src="/images/UltimativeSport.jpg" />
<img src="/images/UltimativeSport.jpg" />
</div>
<p>Meanwhile climbing 50° steep walls and taking MTB trails with ease.</p> <p>Meanwhile climbing 50° steep walls and taking MTB trails with ease.</p>
<div class="righties"> <Asset src="/videos/MTBtrailsEase.mp4" />
<video width="auto" height="auto" autoplay muted loop>
<source src="/videos/MTBtrailsEase.mp4" type="video/mp4" />
</video>
</div>
<p>Taking every path and never get stuck in traffic again.</p> <p>Taking every path and never get stuck in traffic again.</p>
<div class="righties"> <Asset src="/videos/traffic.mp4" />
<video width="auto" height="auto" autoplay muted loop>
<source src="/videos/traffic.mp4" type="video/mp4" />
</video>
</div>
<p>But still being easy to carry and store just under your desk.</p> <p>But still being easy to carry and store just under your desk.</p>
<div class="righties"> <Asset src="/images/KidsKS16X.jpg" />
<img src="/images/KidsKS16X.jpg" />
</div>
<p>Interested? Then take a deep dive into PEV's and EUC's:</p> <p>Interested? Then take a deep dive into PEV's and EUC's:</p>
<A href="/en/overview"> <a href="/en/overview">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
I want to read everything about it!{" "} I want to read everything about it!{" "}
<FontAwesomeIcon icon={faBookOpen} /> <FontAwesomeIcon icon={faBookOpen} />
</p> </p>
</div> </div>
</A> </a>
<A href="https:/youtube.com/playlist?list=PLfoxTRt1qLuAg-Al9JNHrl_7KVl-uSxwV"> <a href="https://youtube.com/playlist?list=PLfoxTRt1qLuAg-Al9JNHrl_7KVl-uSxwV">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
Na, videos are just fine <FontAwesomeIcon icon={faYoutube} /> Na, videos are just fine <FontAwesomeIcon icon={faYoutube} />
</p> </p>
</div> </div>
</A> </a>
<A href="/de/"> <a href="/de">
<div id="MoreButton"> <div id="MoreButton">
<p> <p>
Wechsel zu Deutsch <FontAwesomeIcon icon={faGlobe} /> Wechsel zu Deutsch <FontAwesomeIcon icon={faGlobe} />
</p> </p>
</div> </div>
</A> </a>
</Body> </Wrapper>
); );
} }

View file

@ -1,18 +1,24 @@
import { Body, Link, Title } from "solid-start"; import { Title } from "@solidjs/meta";
import AssetHandler from "~/components/Asset";
import R from "~/components/Reference"; import R from "~/components/Reference";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar"; import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/overview.scss";
function Manufacturers() { function Manufacturers() {
const { FullscreenView, Asset } = AssetHandler();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="overview" classList={{ "light-mode": lightMode() }}>
<Title>Manufacturers</Title> <Title>Manufacturers</Title>
<Link rel="stylesheet" href="/styles/overview.css" /> <Navbar /> <FullscreenView />
<Navbar />
<article> <article>
{/* {/*
<!--hersteller--> <!--hersteller-->
*/} */}
<div class="row"> <div>
<h3 id="manufacturers">History and explonation of manufacturers</h3> <h3 id="manufacturers">History and explanation of manufacturers</h3>
<p> <p>
There are/were many manufacturers of electric unicycles, only the There are/were many manufacturers of electric unicycles, only the
larger and more important ones are described here. In addition to larger and more important ones are described here. In addition to
@ -23,10 +29,14 @@ function Manufacturers() {
</p> </p>
<h3 id="ninebot"> <h3 id="ninebot">
Ninebot <img class="logos" src="/images/ninebotLogo.jpg" /> Ninebot <img src="/images/ninebotLogo.jpg" />
</h3> </h3>
<img class="righties" src="/images/NineBot.webp" /> <div class="righties">
<img class="lefties" src="/images/NinebotZ10goood.webp" /> <Asset src="/images/NineBot.webp" />
</div>
<div class="lefties">
<Asset src="/images/NinebotZ10goood.webp" />
</div>
<p> <p>
Ninebot is known to most as a sooter manufacturer, some may also Ninebot is known to most as a sooter manufacturer, some may also
know their electric shoes or Segway-like devices with short know their electric shoes or Segway-like devices with short
@ -40,10 +50,14 @@ function Manufacturers() {
</p> </p>
<h3 id="inmotion"> <h3 id="inmotion">
Inmotion <img class="logos" src="/images/inmotionLogo.png" /> Inmotion <img src="/images/inmotionLogo.png" />
</h3> </h3>
<img class="righties" src="/images/InmotionLineup.jpg" /> <div class="righties">
<img class="lefties" src="/images/V11 3.webp" /> <Asset src="/images/InmotionLineup.jpg" />
</div>
<div class="lefties">
<Asset src="/images/V11 3.webp" />
</div>
<p> <p>
Inmotion is the second largest manufacturer of those listed here. Inmotion is the second largest manufacturer of those listed here.
Also big in the standard scooter segment, Inmotion also has a large Also big in the standard scooter segment, Inmotion also has a large
@ -53,18 +67,22 @@ function Manufacturers() {
professional looking first Suspension EUC V11. Inmotion generally professional looking first Suspension EUC V11. Inmotion generally
stands for quality, design and safety thanks to good{" "} stands for quality, design and safety thanks to good{" "}
<R href="#tiltback">Tiltback</R> and high safety margin. But all <R href="#tiltback">Tiltback</R> and high safety margin. But all
this in exchange for performance. Until recently, inmotion was this is in exchange for performance. Until recently, inmotion was
synonymous with weak and little range. That changed when the V12 synonymous with weak and little range. That changed when the V12
came out and soon the V13 will come out. Now we are hoping for a came out and soon the V13 will come out. Now we are hoping for a
safe and well-designed 90+kmh with a high safety margin, and should safe and well-designed 90+ km/h with a high safety margin and should
the V13 perform as hoped it will change the company's image. the V13 perform as hoped it will change the company's image.
</p> </p>
<h3 id="kingsong"> <h3 id="kingsong">
Kingsong <img class="logos" src="/images/kingsongLogo.png" /> Kingsong <img src="/images/kingsongLogo.png" />
</h3> </h3>
<img class="righties" src="/images/KidsKS16X.jpg" /> <div class="righties">
<img class="lefties" src="/images/kingsong2.jpg" /> <Asset src="/images/KidsKS16X.jpg" />
</div>
<div class="lefties">
<Asset src="/images/kingsong2.jpg" />
</div>
<p> <p>
Kingsong is very similar to Inmotion, only smaller and without the Kingsong is very similar to Inmotion, only smaller and without the
big scooter and e-bike market behind it. Quality and design were the big scooter and e-bike market behind it. Quality and design were the
@ -81,10 +99,14 @@ function Manufacturers() {
</p> </p>
<h3 id="begode"> <h3 id="begode">
Gotway/Begode <img class="logos" src="/images/BEGODElogo.jpg" /> Gotway/Begode <img src="/images/BEGODElogo.jpg" />
</h3> </h3>
<img class="righties" src="/images/BegodeLineup.jpg" /> <div class="righties">
<img class="lefties" src="/images/BegodeMemeBurn.jpg" /> <Asset src="/images/BegodeLineup.jpg" />
</div>
<div class="lefties">
<Asset src="/images/BegodeMemeBurn.jpg" />
</div>
<p> <p>
Gotway, or Begode as they call themselves today, is difficult to Gotway, or Begode as they call themselves today, is difficult to
describe and classify. Many opinions and controversies. The company describe and classify. Many opinions and controversies. The company
@ -92,15 +114,15 @@ function Manufacturers() {
<R href="#historie">History</R> chapter, they had the focus on <R href="#historie">History</R> chapter, they had the focus on
performance right away. The design and the quality were terrible in performance right away. The design and the quality were terrible in
the beginning and actually until recently. But they were the first the beginning and actually until recently. But they were the first
to be able to hit 40kmh, then 50, then 60, then 70, then 80 and now to be able to hit 40 km/h, then 50, then 60, then 70, then 80 and
100kmh, they're the ones who pack <R href="#wh">4800wh</R> into one now 100 km/h, they're the ones who pack <R href="#wh">4,800 Wh</R>{" "}
device, no matter what it looks like or how heavy it is. Gotway has into one device, no matter what it looks like or how heavy it is.
actively pushed the boundaries of the sport and unicycles. Whenever Gotway has actively pushed the boundaries of the sport and
a new, faster device came out, it was said, oh who rides 40kmh on a unicycles. Whenever a new, faster device came out, it was said, oh
unicycle anyway. Today 40kmh is the medium speed and 70+ is who rides 40 km/h on a unicycle anyway. Today 40 km/h is the medium
expected. It is also typical of Begode to let their own devices speed and 70+ is expected. It is also typical of Begode to let their
quickly become obsolete with up to 7+ new devices a year. Kingsong own devices quickly become obsolete with up to 7+ new devices a
and Inmotion usually release 1 device per year. year. Kingsong and Inmotion usually release 1 device per year.
</p> </p>
<p> <p>
@ -111,17 +133,17 @@ function Manufacturers() {
is also a lack of communication with the community and a lack of is also a lack of communication with the community and a lack of
reaction to productions defects. Nevertheless, Begode was the first reaction to productions defects. Nevertheless, Begode was the first
company to use <R href="#spiked-pedals">spiked pedals</R> as company to use <R href="#spiked-pedals">spiked pedals</R> as
standard, which was a request from the community and which are the standard, which was a request from the community, and which are the
best included default <R href="#spiked-pedals">spiked pedals</R> to best included default <R href="#spiked-pedals">spiked pedals</R> to
date. All other companies followed suit with worse versions, which date. All other companies followed suit with worse versions, which
is what is normally expected of Begode. Begode were the first to is what is normally expected of Begode. Begode were the first to
move from 84V to 100V, and more recently to 134V, which provides move from 84 V to 100 V, and more recently to 134 V, which provides
unprecedented power. Again, the other manufacturers are slowly unprecedented power. Again, the other manufacturers are slowly
catching up and still have weaker devices. The new generation of catching up and still have weaker devices. The new generation of
Begode has better, almost good design and in some aspects also Begode has better, almost good design and in some aspects also
better suspension than the competition, nevertheless the (completely better suspension than the competition, nevertheless the (completely
exposed) battery mounts break off easily and you have to buy DIY exposed) battery mounts break off easily and you have to buy DIY
solutions to continue riding (for an almost 5000 Device). solutions to continue riding (for an almost 5,000 Device).
</p> </p>
<p> <p>
@ -130,11 +152,14 @@ function Manufacturers() {
</p> </p>
<h3 id="veteran"> <h3 id="veteran">
Leaperkim/Veteran{" "} Leaperkim/Veteran <img src="/images/veteranLogo.png" />
<img class="logos" src="/images/veteranLogo.png" />
</h3> </h3>
<img class="righties" src="/images/Shermangrey.jpg" /> <div class="righties">
<img class="lefties" src="/images/abrahams.jpg" /> <Asset src="/images/Shermangrey.jpg" />
</div>
<div class="lefties">
<Asset src="/images/abrahams.jpg" />
</div>
<p> <p>
Veteran is the favorite for many. Comprised of ex-Gotway engineers Veteran is the favorite for many. Comprised of ex-Gotway engineers
and employees who disagreed with Gotway's decisions, Veteran and employees who disagreed with Gotway's decisions, Veteran
@ -166,12 +191,12 @@ function Manufacturers() {
and offers them cheaper than Begode does. Extreme Bull devices are and offers them cheaper than Begode does. Extreme Bull devices are
rarely seen riding around, and many resellers don't even offer them. rarely seen riding around, and many resellers don't even offer them.
But, as of recently there are rumors about a Sherman S copy called But, as of recently there are rumors about a Sherman S copy called
Commander pro. should the rumors be true, and should the device Commander pro. Should the rumors be true, and should the device
deliver whats promised, Extreme Bull might be on the rise. deliver what's promised, Extreme Bull might be on the rise.
</p> </p>
</div> </div>
</article> </article>
</Body> </Wrapper>
); );
} }

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,18 @@
import { Title } from "@solidjs/meta";
import { useNavigate } from "@solidjs/router";
import { HttpStatusCode } from "@solidjs/start";
import { createEffect } from "solid-js"; import { createEffect } from "solid-js";
import { Title, useNavigate } from "solid-start";
export default function Home() { export default function Home() {
const navigate = useNavigate(); const navigate = useNavigate();
createEffect(() => { createEffect(() => {
const isGerman = navigator.language.startsWith("de"); const isGerman = navigator.language.startsWith("de");
navigate(isGerman ? "/de/" : "/en/"); navigate(isGerman ? "/de" : "/en", { replace: true });
}); });
return <Title>Language detection...</Title>; return (
<>
<Title>Language detection...</Title>
<HttpStatusCode code={302} />
</>
);
} }

View file

@ -1,16 +1,27 @@
import { Body, Link, Title, useNavigate } from "solid-start"; import { Title } from "@solidjs/meta";
import { useNavigate } from "@solidjs/router";
import Wrapper from "~/components/Wrapper";
import Navbar, { lightMode } from "~/components/en/Navbar"; import Navbar, { lightMode } from "~/components/en/Navbar";
import "~/styles/overview.scss";
function soon() { function soon() {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<Body classList={{ "light-mode": lightMode() }}> <Wrapper class="overview" classList={{ "light-mode": lightMode() }}>
<Title>soon</Title> <Title>soon</Title>
<Link rel="stylesheet" href="/styles/overview.css" />
<Navbar /> <Navbar />
<p style={{ "text-align": "center" }}>This side is not available yet.</p> <div
<button onClick={() => navigate(-1)}>Back</button> style={{
</Body> "min-height": "100vh",
display: "inline-block",
}}
>
<p style={{ "text-align": "center" }}>
This side is not available yet.
</p>
<button onClick={() => navigate(-1)}>Back</button>
</div>
</Wrapper>
); );
} }

125
src/styles/devices.scss Normal file
View file

@ -0,0 +1,125 @@
* {
box-sizing: border-box;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #7f5af0;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
#body.devices {
background-color: #16161a;
color: #94a1b2;
font-size: 1.4em;
// #sidenavbar {
// z-index: 1;
// margin-left: -8px;
// overflow: visible;
// background-color: #121629;
// position: fixed;
// bottom: 0;
// width: 100%;
// height: 50px;
// text-align: left;
// display: flex;
// justify-content: space-between;
// button {
// all: unset;
// margin: 5px auto;
// color: #eff0f3;
// padding-left: 10px;
// padding-right: 10px;
// text-decoration: none;
// font-size: 1.4em;
// border: none;
// &:hover {
// background: #eff0f3;
// color: #2a2a2a;
// cursor: pointer;
// }
// }
// }
.main {
height: 100%;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.6em;
margin-left: 140px;
}
p {
text-align: justify;
font-size: 0.875em;
}
header {
text-align: center;
}
footer,
aside,
article {
text-align: center;
}
img {
width: 100%;
max-width: max-content;
padding: 16px;
height: auto;
display: block;
}
.grid {
display: grid;
grid-template-columns: repeat(4, auto);
.span-2 {
grid-column: span 2;
}
}
table {
width: 100%;
border-collapse: collapse;
td,
th {
border: 1px solid;
padding: 0.25rem;
}
tbody td {
text-align: left;
}
}
@media only screen and (max-width: 767px) {
// [class*="col-"] {
// width: 100%;
// }
}
}

221
src/styles/global.scss Normal file
View file

@ -0,0 +1,221 @@
body {
margin: 0;
}
#body {
.fullscreen-asset {
position: fixed;
height: 100vh;
width: 100vw;
background-color: rgba(0, 0, 0, 0.8);
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&:not(.active) {
display: none;
}
img,
video {
max-width: 80vw;
transform-origin: center;
transform: scale(var(--zoom));
&.active {
opacity: 0;
}
}
img:not(.move),
video:not(.move) {
transition: transform-origin 1s;
}
img.move,
video.move {
transform-origin: var(--x) var(--y);
}
.controlls {
position: absolute;
top: 2rem;
right: 2rem;
display: flex;
flex-direction: column;
gap: 1rem;
button {
padding: 0.5rem 0.6rem;
border-radius: 10%;
svg {
height: 2rem;
width: 2rem;
@media (max-width: 1200px) {
height: 5vw;
width: 5vw;
}
}
}
}
}
.menu {
position: fixed;
top: 2rem;
left: 2rem;
padding: 0.5rem 0.6rem;
border-radius: 10%;
svg {
height: 2rem;
width: 2rem;
}
@media (max-width: 1200px) {
position: fixed;
top: 5vw;
left: 5vw;
padding: 2vw;
svg {
height: 5vw;
width: 5vw;
}
}
}
article > div {
clear: both;
}
.righties {
margin-top: -8px;
margin-left: 24px;
width: 33%;
float: right;
clear: both;
}
.lefties {
margin-top: -8px;
margin-right: 24px;
width: 33%;
float: left;
display: none;
}
#navbar {
z-index: 1;
overflow-y: auto;
overflow-x: hidden;
background-color: #121629;
position: fixed;
top: 0;
height: 100%;
margin-left: -8px;
padding: 1rem;
.modes {
margin: 1rem 0;
button {
border-radius: 16px;
scale: 0.9;
&:hover {
scale: 1.06;
}
}
}
a {
float: none;
display: block;
color: #eff0f3;
text-align: left;
padding: 8px 8px;
text-decoration: none;
font-size: 0.9em;
&:hover {
background: #eff0f3;
color: #121629;
cursor: pointer;
}
}
}
&.light-mode {
background-color: #eff0f3;
color: #2a2a2a;
.lefties,
.righties {
> * {
box-shadow: #eff0f3 0 0 1rem 1rem;
}
}
article p a {
text-align: justify;
color: #2a2a2a;
border-bottom: 1px solid #2a2a2a;
&:hover {
color: blue;
border-bottom: 1px solid blue;
.svg-inline--fa {
color: blue;
}
}
}
.svg-inline--fa {
color: #2a2a2a;
}
b {
color: #2a2a2a;
a {
color: #2a2a2a;
}
}
h3 {
color: #2a2a2a;
}
h1 {
color: #2a2a2a;
}
h2 {
color: #2a2a2a;
}
#navbar {
background-color: #b8c1ec;
a {
color: black;
}
}
button {
background-color: #b8c1ec;
color: black;
}
.raster > a {
background-color: #eff0f3;
}
a {
color: #2a2a2a;
}
}
article {
max-width: 80vw;
margin: auto;
}
}

180
src/styles/overview.scss Normal file
View file

@ -0,0 +1,180 @@
* {
scroll-margin-block-start: 60px;
scroll-margin-block-end: 60px;
box-sizing: border-box;
scroll-behavior: smooth;
max-width: 100%;
max-height: 100%;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #7f5af0;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
.overview {
background-color: #16161a;
color: #94a1b2;
text-align: center;
font-size: 1.4em;
.main {
height: 100%;
}
h1 {
font-size: 2.5em;
color: #fffffe;
}
h2 {
font-size: 2em;
color: #fffffe;
}
h3 {
font-size: 1.6em;
clear: both;
color: #fffffe;
}
p {
text-align: justify;
font-size: 0.875em;
}
header {
text-align: center;
}
footer,
aside,
article {
text-align: center;
}
> img {
width: 100%;
max-width: max-content;
height: auto;
}
button {
background-color: #121629;
color: #eff0f3;
text-align: left;
padding: 8px 8px;
text-decoration: none;
font-size: 0.9em;
}
p a {
display: inline-block;
text-align: justify;
text-decoration: none;
color: #91c4ff;
border-bottom: 1px solid navy;
&:hover {
border-bottom: 1px solid #91c4ff;
}
}
.svg-inline--fa,
b {
color: #91c4ff;
}
#vcutout {
width: 25%;
}
#vcutout:hover {
width: 30%;
}
.hidden {
/*position:absolute;
transform:translate(-50%,-50%);
height:200px;
width:200px; */
float: left;
padding: 2%;
padding-left: 0%;
display: none;
}
/*wenn hover über text, zeige bild*/
.imghover:hover + .hidden {
display: block;
}
a {
display: inline;
color: rgb(225, 223, 210);
svg.left {
margin-right: 2px;
}
svg.right {
margin-left: 6px;
}
div img,
div video {
border-radius: 10%;
max-width: 260px;
max-height: 290px;
padding-top: 8px;
bottom: 0;
}
div h3 {
margin: 0.5%;
}
}
.raster {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
> a {
border: #555;
padding: 2rem 1rem;
border-width: 2px;
border-style: solid;
border-radius: 2rem;
display: flex;
flex-direction: column;
gap: 1rem;
transition: scale 0.5s;
&:hover {
scale: 1.06;
}
h3 {
font-size: 1.5rem;
margin: 0;
}
img,
video {
height: 100%;
object-fit: cover;
border-radius: 1rem;
}
}
}
.logos {
height: 1.6em;
margin-bottom: -18px;
}
.table-half {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
}

119
src/styles/start.scss Normal file
View file

@ -0,0 +1,119 @@
* {
scroll-margin-block-start: 60px;
scroll-margin-block-end: 60px;
box-sizing: border-box;
scroll-behavior: smooth;
max-width: 100%;
max-height: 100%;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background: rgb(41, 41, 41);
}
::-webkit-scrollbar-thumb {
background: #ff8906;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
body {
background-color: #0f0e17;
}
#body.start {
color: #a7a9be;
text-align: left;
font-size: 1.4em;
max-width: 1200px;
margin: auto;
display: flex;
align-items: center;
flex-direction: column;
> img,
> video {
max-height: 60vh;
}
.row {
clear: both;
}
p {
padding: 10px;
}
#cover {
opacity: 60%;
}
.container {
position: relative;
text-align: center;
color: white;
}
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#gone {
display: none;
color: #fffffe;
text-align: center;
}
#MoreButton {
margin: auto;
position: relative;
height: auto;
max-height: max-content;
width: auto;
max-width: max-content;
background-color: #ff8906;
border-radius: 5px;
color: #fffffe;
font-size: 1.2em;
}
a {
text-decoration: none;
&:hover {
scale: 1.06;
}
div p {
text-align: center;
padding: 20px;
}
}
.righties {
padding-bottom: 30px;
padding-top: 20px;
width: 100%;
clear: both;
}
@media (max-width: 767px) /*unter handy größe*/ {
.centered {
display: none;
}
#gone {
display: block;
}
#cover {
opacity: 100%;
}
.righties {
width: 100%;
}
}
}

View file

@ -1,14 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "node", "moduleResolution": "node",
"jsxImportSource": "solid-js", "allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve", "jsx": "preserve",
"jsxImportSource": "solid-js",
"allowJs": true,
"strict": true, "strict": true,
"baseUrl": "./", "noEmit": true,
"types": ["vinxi/client"],
"isolatedModules": true,
"paths": { "paths": {
"~/*": ["./src/*"] "~/*": ["./src/*"]
} }

View file

@ -1,10 +0,0 @@
import solid from "solid-start/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [solid()],
server: {
host: "0.0.0.0",
strictPort: true,
},
});