Compare commits
141 commits
Author | SHA1 | Date | |
---|---|---|---|
|
2830fd9350 | ||
|
986126a2bb | ||
|
3d13c256e3 | ||
|
f67ba1e655 | ||
|
1553825719 | ||
|
f1961f5cef | ||
|
a67cddc74b | ||
|
68a43b6b9c | ||
|
f2b408fce5 | ||
|
35f5343149 | ||
|
b5eae39f89 | ||
|
39993112b7 | ||
|
d4dc47b1e1 | ||
|
25ee71b615 | ||
|
23a24c5842 | ||
|
29f549ddd9 | ||
|
223a32580c | ||
|
3723e4b036 | ||
|
b57c5a9be8 | ||
|
bb724f581b | ||
|
44d974a870 | ||
|
3c83d66bf5 | ||
|
79f1191e36 | ||
|
8f4c1fc7d9 | ||
|
cf4155784c | ||
|
0b952dd789 | ||
|
da0d919267 | ||
|
d7e3ae07b5 | ||
|
7fc87ea224 | ||
|
f5117882f8 | ||
|
7da03fc635 | ||
|
2382405651 | ||
|
20c7a512ed | ||
|
b3a288e281 | ||
|
21ed580988 | ||
|
dbb317e19a | ||
|
87dd1649b9 | ||
|
53c2987dcf | ||
|
d826d278a5 | ||
|
b87e84e5ce | ||
|
d72c3efeeb | ||
|
9757a3d076 | ||
|
eefc4cc8d4 | ||
|
7fe9cdeef3 | ||
|
9536a6fa77 | ||
|
8ea083c6d1 | ||
|
c258de84a2 | ||
|
8e04a3430a | ||
|
fb9cfd0783 | ||
|
65bd7bde60 | ||
|
69182778c9 | ||
|
1707b6f4af | ||
|
df3014e2a5 | ||
|
f7ae855221 | ||
|
35d5232575 | ||
|
065dc62cfb | ||
|
8f4a5f5c98 | ||
|
72cc7afe71 | ||
|
f881c1aac1 | ||
|
538d09f7be | ||
|
e4be1debf9 | ||
|
c646988dcf | ||
|
f7ceadfb83 | ||
|
7f89b30e63 | ||
|
2e12833d4b | ||
|
afe81f2bbb | ||
|
20de567e7e | ||
|
674784f219 | ||
|
4e26431fd6 | ||
|
b4437e542e | ||
|
9cb9bed431 | ||
|
782046efa6 | ||
|
d4b12bc9ba | ||
|
bfe0ca0719 | ||
|
04a3266a88 | ||
|
9b11da8ad7 | ||
|
9160677be6 | ||
|
b1b6deda44 | ||
|
86a04fa6eb | ||
|
e2b0dd0f0a | ||
|
e5c292ca1f | ||
|
c03612d195 | ||
|
688c636acd | ||
|
de992d86b2 | ||
|
54c39cc9b4 | ||
|
fc3680bd7a | ||
|
b90b674bf9 | ||
|
390d28cce7 | ||
|
de9281574d | ||
|
cb99059ef4 | ||
|
4f5e6c2df3 | ||
|
e29a98f06d | ||
|
5b16aae03c | ||
|
82d6d68d25 | ||
|
26645855ae | ||
|
b40b385d6e | ||
|
e85746ba7e | ||
|
28d76eed45 | ||
|
886708854a | ||
|
606269cbd4 | ||
|
d296e61362 | ||
|
bd4b36f8ae | ||
|
caca751b74 | ||
|
ccf9556f3b | ||
|
98de3bc095 | ||
|
f9d6c8e4dc | ||
|
3fd8929186 | ||
|
de35e0e333 | ||
|
c8213ca5a5 | ||
|
1eca8ae41e | ||
|
0683ff26c5 | ||
|
e7ffb63e43 | ||
|
a8a31bb7e4 | ||
|
ed40dc7e3a | ||
|
7cfac424e2 | ||
|
05682347c7 | ||
|
4370fbcd44 | ||
|
b7167f30e7 | ||
|
41f9bbd968 | ||
|
0a8467d92e | ||
|
b0e24ac141 | ||
|
852246e148 | ||
|
6548750aa2 | ||
|
4fdba3c7e5 | ||
|
0bf2fb9de2 | ||
|
936f3e7057 | ||
|
9d4f443363 | ||
|
368dfcec97 | ||
|
c68c432c8f | ||
|
9fe918136c | ||
|
46a7b2833d | ||
|
cae7c1778f | ||
|
fc56b3823a | ||
|
f54fbe7daa | ||
|
ee336f9abe | ||
|
0145c7f70c | ||
|
2bc11a85d8 | ||
|
eeb5ece970 | ||
|
7bd86d73e6 | ||
|
d643ce2646 | ||
|
33c4cc6c37 |
2
.browserslistrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
last 2 versions
|
||||
not dead
|
|
@ -1,15 +1,15 @@
|
|||
/* eslint-env node */
|
||||
require("@rushstack/eslint-patch/modern-module-resolution");
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/eslint-config-typescript",
|
||||
"@vue/eslint-config-prettier",
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier/skip-formatting'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
},
|
||||
};
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
{}
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
|
|
22
card/index.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="flex">
|
||||
<div class="image">
|
||||
<img src="../src/assets/viktor-avatar.png" alt="Sebin Smug Icon" />
|
||||
</div>
|
||||
<div class="headings">
|
||||
<h1>Viktor Kraastav</h1>
|
||||
<h2>Character Reference Page</h2>
|
||||
</div>
|
||||
</main>
|
||||
<!-- Open in browser and set mobile view to 2048x1072 with DPR: 2 and take screenshot -->
|
||||
</body>
|
||||
</html>
|
105
card/style.css
Normal file
|
@ -0,0 +1,105 @@
|
|||
@import "../src/assets/fonts/secular-one/secular-one.css";
|
||||
|
||||
:root {
|
||||
font-size: 20px;
|
||||
color: #f8ebdd;
|
||||
|
||||
--theme-c-walnut-brown: #422322;
|
||||
--theme-c-desert-sand-translucent: #e7c7b1bf;
|
||||
|
||||
--container-box-shadow: 1vw 1vw 4vw rgba(0, 0, 0, 0.7);
|
||||
--welcome-header-mainline-font-size: 7vw;
|
||||
--welcome-header-subline-font-size: 3.625vw;
|
||||
|
||||
--color-background: #2d4c5a;
|
||||
--page-background: url(../src/assets/layered-waves-dark.svg);
|
||||
--page-background-image-height: 100vw;
|
||||
--page-background-image-max-height: 80vh;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--color-background);
|
||||
}
|
||||
|
||||
body::after {
|
||||
background: var(--page-background);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center bottom;
|
||||
|
||||
display: block;
|
||||
|
||||
content: "";
|
||||
position: sticky;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
height: var(--page-background-image-height);
|
||||
max-height: var(--page-background-image-max-height);
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.flex > * {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.image {
|
||||
flex: 0 0 60vh;
|
||||
max-height: 100vh;
|
||||
|
||||
background-color: var(--theme-c-desert-sand-translucent);
|
||||
|
||||
border: 1vw solid var(--theme-c-walnut-brown);
|
||||
border-radius: 4.5vw;
|
||||
|
||||
transform: scale(0.84) translateX(15%) rotateZ(calc(-1 * (11 * 1deg)));
|
||||
transform-origin: 0 100%;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transform: scale(1.2) rotateZ(calc(11 * 1deg));
|
||||
}
|
||||
|
||||
.headings {
|
||||
flex: 0 0 55vw;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.headings :where(h1, h2) {
|
||||
font-family: "Secular One", sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.headings h1 {
|
||||
font-size: var(--welcome-header-mainline-font-size);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.headings h2 {
|
||||
font-size: var(--welcome-header-subline-font-size);
|
||||
font-weight: 300;
|
||||
}
|
10
env.d.ts
vendored
|
@ -1 +1,11 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
declare module "*&imagetools" {
|
||||
/**
|
||||
* actual types
|
||||
* - code https://github.com/JonasKruckenberg/imagetools/blob/main/packages/core/src/output-formats.ts
|
||||
* - docs https://github.com/JonasKruckenberg/imagetools/blob/main/docs/guide/getting-started.md#metadata
|
||||
*/
|
||||
const out;
|
||||
export default out;
|
||||
}
|
||||
|
|
26
index.html
|
@ -2,10 +2,30 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="favicon" href="/favicon.png" type="image/png" />
|
||||
<link rel="icon" href="/favicon.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<title>Viktor Kraastav – Reference Page</title>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f8ebdd" />
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#2d4c5a" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@SebinNyshkim" />
|
||||
<meta name="twitter:creator" content="@SebinNyshkim" />
|
||||
<meta name="twitter:title" content="Viktor Kraastav - Reference Page" />
|
||||
<meta name="twitter:description" content="The official reference page for Viktor Kraastav with picture references and in-depth character descriptions" />
|
||||
<meta name="twitter:image" content="https://ref.sebin-nyshkim.net/viktor/preview.png" />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Viktor Kraastav - Reference Page" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:locale:alternate" content="de_DE" />
|
||||
<meta property="og:url" content="https://ref.sebin-nyshkim.net/viktor/" />
|
||||
<meta property="og:image" content="https://ref.sebin-nyshkim.net/viktor/preview.png" />
|
||||
<meta property="og:description" content="The official reference page for Viktor Kraastav with picture references and in-depth character descriptions" />
|
||||
</head>
|
||||
<body></body>
|
||||
<body>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
6064
package-lock.json
generated
45
package.json
|
@ -1,35 +1,38 @@
|
|||
{
|
||||
"name": "viktor-reference",
|
||||
"version": "0.1.0",
|
||||
"version": "0.4.3",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "run-p type-check build-only",
|
||||
"preview": "vite preview --port 4173",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.2.38",
|
||||
"vue-router": "^4.1.5"
|
||||
"vue": "^3.3.4",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.1.4",
|
||||
"@types/node": "^16.11.56",
|
||||
"@types/vue-markdown": "^2.2.1",
|
||||
"@vitejs/plugin-vue": "^3.0.3",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.0",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-plugin-vue": "^9.3.0",
|
||||
"@rushstack/eslint-patch": "^1.3.3",
|
||||
"@tsconfig/node18": "^18.2.1",
|
||||
"@types/node": "^20.5.9",
|
||||
"@vitejs/plugin-vue": "^4.3.4",
|
||||
"@vue/eslint-config-prettier": "^8.0.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-plugin-vue": "^9.17.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.7.1",
|
||||
"sass": "^1.55.0",
|
||||
"typescript": "~4.7.4",
|
||||
"vite": "^3.0.9",
|
||||
"vite-imagetools": "^4.0.9",
|
||||
"vue-tsc": "^0.40.7"
|
||||
"prettier": "^3.0.3",
|
||||
"sass": "^1.66.1",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.9",
|
||||
"vite-imagetools": "^5.0.8",
|
||||
"vue-tsc": "^1.8.8"
|
||||
}
|
||||
}
|
||||
|
|
8
public/.htaccess
Normal file
|
@ -0,0 +1,8 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.html$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /viktor/index.html [L]
|
||||
</IfModule>
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
public/favicon.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
public/preview.png
Normal file
After Width: | Height: | Size: 654 KiB |
77
src/App.vue
|
@ -1,34 +1,69 @@
|
|||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
import { ref } from 'vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
import { version } from '../package.json'
|
||||
|
||||
import { RouterView } from "vue-router";
|
||||
import SiteNavigation from "@/components/SiteNavigation.vue";
|
||||
import NavToggle from "@/components/NavToggle.vue";
|
||||
import HeaderBar from "@/components/HeaderBar.vue";
|
||||
import ModalDialog from '@/components/ModalDialog.vue'
|
||||
import LocaleSwitcher from '@/components/LocaleSwitcher.vue'
|
||||
import LinkButton from '@/components/LinkButton.vue'
|
||||
import SiteNavigation from '@/components/SiteNavigation.vue'
|
||||
import NavigationItem from '@/components/NavigationItem.vue'
|
||||
import LanguageButton from '@/components/LanguageButton.vue'
|
||||
import SiteFooter from '@/components/SiteFooter.vue'
|
||||
|
||||
interface State {
|
||||
navActive: boolean;
|
||||
import LanguageIcon from '@/assets/icons/LanguageIcon.vue'
|
||||
|
||||
const locales = [
|
||||
{ code: 'en', name: 'English', flag: '🇬🇧' },
|
||||
{ code: 'de', name: 'Deutsch', flag: '🇩🇪' }
|
||||
]
|
||||
|
||||
const langswitcher = ref<InstanceType<typeof ModalDialog>>()
|
||||
|
||||
const showModal = () => {
|
||||
langswitcher.value?.showModal()
|
||||
}
|
||||
|
||||
const state: State = reactive({
|
||||
navActive: false,
|
||||
});
|
||||
|
||||
const toggleNav = (): void => {
|
||||
state.navActive = !state.navActive;
|
||||
document.body.classList.toggle("scroll-lock");
|
||||
};
|
||||
const close = () => {
|
||||
langswitcher.value?.close()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SiteNavigation :isActive="state.navActive" @selected="toggleNav" />
|
||||
<ModalDialog id="lang-select" ref="langswitcher">
|
||||
<template #heading>{{ $t('langswitcher.title') }}</template>
|
||||
<template #message>
|
||||
<p>{{ $t('langswitcher.prompt') }}</p>
|
||||
<LocaleSwitcher id="locale-switch" v-model="$i18n.locale" :locales="locales" />
|
||||
</template>
|
||||
<template #buttons>
|
||||
<LinkButton @click.prevent="close()">
|
||||
{{ $t('langswitcher.buttonClose') }}
|
||||
</LinkButton>
|
||||
</template>
|
||||
</ModalDialog>
|
||||
|
||||
<HeaderBar>
|
||||
<NavToggle @click.prevent="toggleNav" />
|
||||
<template #heading>{{ $route.meta.title }}</template>
|
||||
</HeaderBar>
|
||||
<SiteNavigation>
|
||||
<NavigationItem
|
||||
v-for="(route, idx) in $router.getRoutes()"
|
||||
:key="idx"
|
||||
:icon="route.meta?.icon"
|
||||
:href="route.path"
|
||||
>
|
||||
{{ $t(`${route.meta?.title}`) }}
|
||||
</NavigationItem>
|
||||
</SiteNavigation>
|
||||
|
||||
<main>
|
||||
<RouterView />
|
||||
<LanguageButton>
|
||||
<LanguageIcon @click.prevent="showModal()" />
|
||||
</LanguageButton>
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition name="fade" mode="out-in">
|
||||
<component :is="Component" :key="$route.path" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</main>
|
||||
|
||||
<SiteFooter>v{{ version }} © {{ new Date().getFullYear() }} Sebin Nyshkim</SiteFooter>
|
||||
</template>
|
||||
|
|
BIN
src/assets/fonts/arvo/arvo-bold-italic-latin-ext.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-bold-italic-latin.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-bold-latin-ext.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-bold-latin.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-greek.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-italic-greek.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-italic-latin-ext.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-italic-latin.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-latin-ext.woff2
Normal file
BIN
src/assets/fonts/arvo/arvo-latin.woff2
Normal file
91
src/assets/fonts/arvo/arvo.css
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* arvo-bold-latin */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local("Arvo Bold"), local("Arvo-Bold"), url(arvo-bold-latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-bold-latin-ext */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local("Arvo Bold"), local("Arvo-Bold"), url(arvo-bold-latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+20A0-20CF,U+2C60-2C7F,U+A720-A7FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-italic-latin */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local("Arvo-Italic"), url(arvo-italic-latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-italic-latin-ext */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local("Arvo-Italic"), url(arvo-italic-latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+20A0-20CF,U+2C60-2C7F,U+A720-A7FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-italic-greek */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local("Arvo-Italic"), url(arvo-italic-greek.woff2) format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-bold-italic-latin */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local("Arvo Bold Italic"), local("Arvo-BoldItalic"), url(arvo-bold-italic-latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-bold-italic-latin-ext */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local("Arvo Bold Italic"), local("Arvo-BoldItalic"), url(arvo-bold-italic-latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+20A0-20CF,U+2C60-2C7F,U+A720-A7FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-latin */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Arvo"), url(arvo-latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-latin-ext */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Arvo"), url(arvo-latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+20A0-20CF,U+2C60-2C7F,U+A720-A7FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* arvo-greek */
|
||||
@font-face {
|
||||
font-family: Arvo;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Arvo"), url(arvo-greek.woff2) format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
font-display: swap;
|
||||
}
|
||||
|
28
src/assets/fonts/secular-one/secular-one.css
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* secularone-regular-latin */
|
||||
@font-face {
|
||||
font-family: Secular One;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("SecularOne-Regular"), url(secularone-regular-latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215;
|
||||
font-display: swap;
|
||||
}
|
||||
/* secularone-regular-latin-ext */
|
||||
@font-face {
|
||||
font-family: Secular One;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("SecularOne-Regular"), url(secularone-regular-latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+20A0-20CF,U+2C60-2C7F,U+A720-A7FF;
|
||||
font-display: swap;
|
||||
}
|
||||
/* secularone-regular-greek */
|
||||
@font-face {
|
||||
font-family: Secular One;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("SecularOne-Regular"), url(secularone-regular-greek.woff2) format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
font-display: swap;
|
||||
}
|
||||
|
BIN
src/assets/fonts/secular-one/secularone-regular-greek.woff2
Normal file
BIN
src/assets/fonts/secular-one/secularone-regular-latin-ext.woff2
Normal file
BIN
src/assets/fonts/secular-one/secularone-regular-latin.woff2
Normal file
3
src/assets/icons/BoxesIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M160 48c0-26.5 21.5-48 48-48h48V80c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V0h48c26.5 0 48 21.5 48 48V176c0 26.5-21.5 48-48 48H208c-26.5 0-48-21.5-48-48V48zM48 288H96v80c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V288h48c26.5 0 48 21.5 48 48V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V336c0-26.5 21.5-48 48-48zm320 0h48v80c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V288h48c26.5 0 48 21.5 48 48V464c0 26.5-21.5 48-48 48H368c-26.5 0-48-21.5-48-48V336c0-26.5 21.5-48 48-48z"/></svg>
|
||||
</template>
|
3
src/assets/icons/BriefcaseIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M184 48H328c4.4 0 8 3.6 8 8V96H176V56c0-4.4 3.6-8 8-8zm-56 8V96H64C28.7 96 0 124.7 0 160v96H192 320 512V160c0-35.3-28.7-64-64-64H384V56c0-30.9-25.1-56-56-56H184c-30.9 0-56 25.1-56 56zM512 288H320v32c0 17.7-14.3 32-32 32H224c-17.7 0-32-14.3-32-32V288H0V416c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V288z"/></svg>
|
||||
</template>
|
3
src/assets/icons/CarIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M135.2 117.4L109.1 192H402.9l-26.1-74.6C372.3 104.6 360.2 96 346.6 96H165.4c-13.6 0-25.7 8.6-30.2 21.4zM39.6 196.8L74.8 96.3C88.3 57.8 124.6 32 165.4 32H346.6c40.8 0 77.1 25.8 90.6 64.3l35.2 100.5c23.2 9.6 39.6 32.5 39.6 59.2V400v48c0 17.7-14.3 32-32 32H448c-17.7 0-32-14.3-32-32V400H96v48c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32V400 256c0-26.7 16.4-49.6 39.6-59.2zM128 288c0-17.7-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32s32-14.3 32-32zm288 32c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32z"/></svg>
|
||||
</template>
|
3
src/assets/icons/CircleCheckIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-111 111-47-47c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l64 64c9.4 9.4 24.6 9.4 33.9 0L369 209z"/></svg>
|
||||
</template>
|
3
src/assets/icons/CircleIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256z"/></svg>
|
||||
</template>
|
3
src/assets/icons/CircleInfoIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-144c-17.7 0-32-14.3-32-32s14.3-32 32-32s32 14.3 32 32s-14.3 32-32 32z"/></svg>
|
||||
</template>
|
3
src/assets/icons/ClipboardIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M280 64h40c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128C0 92.7 28.7 64 64 64h40 9.6C121 27.5 153.3 0 192 0s71 27.5 78.4 64H280zM64 112c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16H320c8.8 0 16-7.2 16-16V128c0-8.8-7.2-16-16-16H304v24c0 13.3-10.7 24-24 24H192 104c-13.3 0-24-10.7-24-24V112H64zm128-8a24 24 0 1 0 0-48 24 24 0 1 0 0 48z"/></svg>
|
||||
</template>
|
3
src/assets/icons/FurAffinityIcon.vue
Normal file
3
src/assets/icons/HelmetSafetyIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M256 32c-17.7 0-32 14.3-32 32v2.3 99.6c0 5.6-4.5 10.1-10.1 10.1c-3.6 0-7-1.9-8.8-5.1L157.1 87C83 123.5 32 199.8 32 288v64H544l0-66.4c-.9-87.2-51.7-162.4-125.1-198.6l-48 83.9c-1.8 3.2-5.2 5.1-8.8 5.1c-5.6 0-10.1-4.5-10.1-10.1V66.3 64c0-17.7-14.3-32-32-32H256zM16.6 384C7.4 384 0 391.4 0 400.6c0 4.7 2 9.2 5.8 11.9C27.5 428.4 111.8 480 288 480s260.5-51.6 282.2-67.5c3.8-2.8 5.8-7.2 5.8-11.9c0-9.2-7.4-16.6-16.6-16.6H16.6z"/></svg>
|
||||
</template>
|
3
src/assets/icons/HomeIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M575.8 255.5c0 18-15 32.1-32 32.1h-32l.7 160.2c0 2.7-.2 5.4-.5 8.1V472c0 22.1-17.9 40-40 40H456c-1.1 0-2.2 0-3.3-.1c-1.4 .1-2.8 .1-4.2 .1H416 392c-22.1 0-40-17.9-40-40V448 384c0-17.7-14.3-32-32-32H256c-17.7 0-32 14.3-32 32v64 24c0 22.1-17.9 40-40 40H160 128.1c-1.5 0-3-.1-4.5-.2c-1.2 .1-2.4 .2-3.6 .2H104c-22.1 0-40-17.9-40-40V360c0-.9 0-1.9 .1-2.8V287.6H32c-18 0-32-14-32-32.1c0-9 3-17 10-24L266.4 8c7-7 15-8 22-8s15 2 21 7L564.8 231.5c8 7 12 15 11 24z"/></svg>
|
||||
</template>
|
3
src/assets/icons/IdCardIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M0 96l576 0c0-35.3-28.7-64-64-64H64C28.7 32 0 60.7 0 96zm0 32V416c0 35.3 28.7 64 64 64H512c35.3 0 64-28.7 64-64V128H0zM64 405.3c0-29.5 23.9-53.3 53.3-53.3H234.7c29.5 0 53.3 23.9 53.3 53.3c0 5.9-4.8 10.7-10.7 10.7H74.7c-5.9 0-10.7-4.8-10.7-10.7zM176 320c-35.3 0-64-28.7-64-64s28.7-64 64-64s64 28.7 64 64s-28.7 64-64 64zM352 208c0-8.8 7.2-16 16-16H496c8.8 0 16 7.2 16 16s-7.2 16-16 16H368c-8.8 0-16-7.2-16-16zm0 64c0-8.8 7.2-16 16-16H496c8.8 0 16 7.2 16 16s-7.2 16-16 16H368c-8.8 0-16-7.2-16-16zm0 64c0-8.8 7.2-16 16-16H496c8.8 0 16 7.2 16 16s-7.2 16-16 16H368c-8.8 0-16-7.2-16-16z"/></svg>
|
||||
</template>
|
3
src/assets/icons/IndustryIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M32 32C14.3 32 0 46.3 0 64V304v48 80c0 26.5 21.5 48 48 48H464c26.5 0 48-21.5 48-48V304 152.2c0-18.2-19.4-29.7-35.4-21.1L320 215.4V152.2c0-18.2-19.4-29.7-35.4-21.1L128 215.4V64c0-17.7-14.3-32-32-32H32z"/></svg>
|
||||
</template>
|
3
src/assets/icons/LanguageIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 128C0 92.7 28.7 64 64 64H256h48 16H576c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H320 304 256 64c-35.3 0-64-28.7-64-64V128zm320 0V384H576V128H320zM178.3 175.9c-3.2-7.2-10.4-11.9-18.3-11.9s-15.1 4.7-18.3 11.9l-64 144c-4.5 10.1 .1 21.9 10.2 26.4s21.9-.1 26.4-10.2l8.9-20.1h73.6l8.9 20.1c4.5 10.1 16.3 14.6 26.4 10.2s14.6-16.3 10.2-26.4l-64-144zM160 233.2L179 276H141l19-42.8zM448 164c11 0 20 9 20 20v4h44 16c11 0 20 9 20 20s-9 20-20 20h-2l-1.6 4.5c-8.9 24.4-22.4 46.6-39.6 65.4c.9 .6 1.8 1.1 2.7 1.6l18.9 11.3c9.5 5.7 12.5 18 6.9 27.4s-18 12.5-27.4 6.9l-18.9-11.3c-4.5-2.7-8.8-5.5-13.1-8.5c-10.6 7.5-21.9 14-34 19.4l-3.6 1.6c-10.1 4.5-21.9-.1-26.4-10.2s.1-21.9 10.2-26.4l3.6-1.6c6.4-2.9 12.6-6.1 18.5-9.8l-12.2-12.2c-7.8-7.8-7.8-20.5 0-28.3s20.5-7.8 28.3 0l14.6 14.6 .5 .5c12.4-13.1 22.5-28.3 29.8-45H448 376c-11 0-20-9-20-20s9-20 20-20h52v-4c0-11 9-20 20-20z"/></svg>
|
||||
</template>
|
3
src/assets/icons/PaletteIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M512 256c0 .9 0 1.8 0 2.7c-.4 36.5-33.6 61.3-70.1 61.3H344c-26.5 0-48 21.5-48 48c0 3.4 .4 6.7 1 9.9c2.1 10.2 6.5 20 10.8 29.9c6.1 13.8 12.1 27.5 12.1 42c0 31.8-21.6 60.7-53.4 62c-3.5 .1-7 .2-10.6 .2C114.6 512 0 397.4 0 256S114.6 0 256 0S512 114.6 512 256zM128 288c0-17.7-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32s32-14.3 32-32zm0-96c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32zM288 96c0-17.7-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32s32-14.3 32-32zm96 96c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32s14.3 32 32 32z"/></svg>
|
||||
</template>
|
3
src/assets/icons/TreeIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M210.6 5.9L62 169.4c-3.9 4.2-6 9.8-6 15.5C56 197.7 66.3 208 79.1 208H104L30.6 281.4c-4.2 4.2-6.6 10-6.6 16C24 309.9 34.1 320 46.6 320H80L5.4 409.5C1.9 413.7 0 419 0 424.5c0 13 10.5 23.5 23.5 23.5H192v32c0 17.7 14.3 32 32 32s32-14.3 32-32V448H424.5c13 0 23.5-10.5 23.5-23.5c0-5.5-1.9-10.8-5.4-15L368 320h33.4c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16L344 208h24.9c12.7 0 23.1-10.3 23.1-23.1c0-5.7-2.1-11.3-6-15.5L237.4 5.9C234 2.1 229.1 0 224 0s-10 2.1-13.4 5.9z"/></svg>
|
||||
</template>
|
3
src/assets/icons/TruckIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M48 0C21.5 0 0 21.5 0 48V368c0 26.5 21.5 48 48 48H64c0 53 43 96 96 96s96-43 96-96H384c0 53 43 96 96 96s96-43 96-96h32c17.7 0 32-14.3 32-32s-14.3-32-32-32V288 256 237.3c0-17-6.7-33.3-18.7-45.3L512 114.7c-12-12-28.3-18.7-45.3-18.7H416V48c0-26.5-21.5-48-48-48H48zM416 160h50.7L544 237.3V256H416V160zM112 416a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm368-48a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"/></svg>
|
||||
</template>
|
3
src/assets/icons/TwitterIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
||||
</template>
|
3
src/assets/icons/WhiskeyGlassIcon.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M32 32c-9.3 0-18.1 4-24.2 11.1S-1 59.4 .3 68.6l50 342.9c5.7 39.3 39.4 68.5 79.2 68.5h253c39.7 0 73.4-29.1 79.2-68.5l50-342.9c1.3-9.2-1.4-18.5-7.5-25.5S489.3 32 480 32H32zM87.7 224L69 96H443L424.3 224H87.7z"/></svg>
|
||||
</template>
|
6
src/assets/layered-waves-dark.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg id="visual" viewBox="0 340 960 200" width="960" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<path d="M0 344L22.8 346.5C45.7 349 91.3 354 137 358.2C182.7 362.3 228.3 365.7 274 365C319.7 364.3 365.3 359.7 411.2 364.5C457 369.3 503 383.7 548.8 384.7C594.7 385.7 640.3 373.3 686 362C731.7 350.7 777.3 340.3 823 344.8C868.7 349.3 914.3 368.7 937.2 378.3L960 388L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#343f53"></path>
|
||||
<path d="M0 402L22.8 402.2C45.7 402.3 91.3 402.7 137 405C182.7 407.3 228.3 411.7 274 412.7C319.7 413.7 365.3 411.3 411.2 410.2C457 409 503 409 548.8 411.8C594.7 414.7 640.3 420.3 686 419.5C731.7 418.7 777.3 411.3 823 401C868.7 390.7 914.3 377.3 937.2 370.7L960 364L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#3b3144"></path>
|
||||
<path d="M0 463L22.8 463.2C45.7 463.3 91.3 463.7 137 459C182.7 454.3 228.3 444.7 274 440.8C319.7 437 365.3 439 411.2 444.8C457 450.7 503 460.3 548.8 461C594.7 461.7 640.3 453.3 686 444.8C731.7 436.3 777.3 427.7 823 429C868.7 430.3 914.3 441.7 937.2 447.3L960 453L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#3c2530"></path>
|
||||
<path d="M0 505L22.8 502C45.7 499 91.3 493 137 493.2C182.7 493.3 228.3 499.7 274 503.2C319.7 506.7 365.3 507.3 411.2 500.2C457 493 503 478 548.8 474.3C594.7 470.7 640.3 478.3 686 483C731.7 487.7 777.3 489.3 823 491.7C868.7 494 914.3 497 937.2 498.5L960 500L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#341c1c"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
6
src/assets/layered-waves-light.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg id="visual" viewBox="0 340 960 200" width="960" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<path d="M0 344L22.8 346.5C45.7 349 91.3 354 137 358.2C182.7 362.3 228.3 365.7 274 365C319.7 364.3 365.3 359.7 411.2 364.5C457 369.3 503 383.7 548.8 384.7C594.7 385.7 640.3 373.3 686 362C731.7 350.7 777.3 340.3 823 344.8C868.7 349.3 914.3 368.7 937.2 378.3L960 388L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#f3e2d1"/>
|
||||
<path d="M0 402L22.8 402.2C45.7 402.3 91.3 402.7 137 405C182.7 407.3 228.3 411.7 274 412.7C319.7 413.7 365.3 411.3 411.2 410.2C457 409 503 409 548.8 411.8C594.7 414.7 640.3 420.3 686 419.5C731.7 418.7 777.3 411.3 823 401C868.7 390.7 914.3 377.3 937.2 370.7L960 364L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#efd9c6"/>
|
||||
<path d="M0 463L22.8 463.2C45.7 463.3 91.3 463.7 137 459C182.7 454.3 228.3 444.7 274 440.8C319.7 437 365.3 439 411.2 444.8C457 450.7 503 460.3 548.8 461C594.7 461.7 640.3 453.3 686 444.8C731.7 436.3 777.3 427.7 823 429C868.7 430.3 914.3 441.7 937.2 447.3L960 453L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#ebd0bb"/>
|
||||
<path d="M0 505L22.8 502C45.7 499 91.3 493 137 493.2C182.7 493.3 228.3 499.7 274 503.2C319.7 506.7 365.3 507.3 411.2 500.2C457 493 503 478 548.8 474.3C594.7 470.7 640.3 478.3 686 483C731.7 487.7 777.3 489.3 823 491.7C868.7 494 914.3 497 937.2 498.5L960 500L960 541L937.2 541C914.3 541 868.7 541 823 541C777.3 541 731.7 541 686 541C640.3 541 594.7 541 548.8 541C503 541 457 541 411.2 541C365.3 541 319.7 541 274 541C228.3 541 182.7 541 137 541C91.3 541 45.7 541 22.8 541L0 541Z" fill="#e7c7b1"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/assets/viktor-avatar.png
Normal file
After Width: | Height: | Size: 261 KiB |
BIN
src/assets/viktor-front-NSFW-alpha.png
Executable file
After Width: | Height: | Size: 1.5 MiB |
BIN
src/assets/viktor-front-SFW-alpha.png
Executable file
After Width: | Height: | Size: 1.5 MiB |
133
src/components/AttributionTable.vue
Normal file
|
@ -0,0 +1,133 @@
|
|||
<script setup lang="ts">
|
||||
import FAIcon from '@/assets/icons/FurAffinityIcon.vue'
|
||||
import TwitterIcon from '@/assets/icons/TwitterIcon.vue'
|
||||
|
||||
interface ArtistLink {
|
||||
furaffinity?: string
|
||||
twitter?: string
|
||||
}
|
||||
|
||||
interface Attribution {
|
||||
artwork: string
|
||||
artist: string
|
||||
links: ArtistLink
|
||||
}
|
||||
|
||||
interface Props {
|
||||
attributions: Attribution[]
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="attribution-table">
|
||||
<thead class="attribution-table__head">
|
||||
<tr class="attribution-table__row">
|
||||
<th class="attribution-table__heading artwork">
|
||||
{{ $t('attributions.artwork.headings[0]') }}
|
||||
</th>
|
||||
<th class="attribution-table__heading artist">
|
||||
{{ $t('attributions.artwork.headings[1]') }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="attribution-table__body">
|
||||
<tr class="attribution-table__row" v-for="(attrib, idx) in attributions" :key="idx">
|
||||
<td class="attribution-table__cell artwork">
|
||||
<img :src="attrib.artwork" alt="Image attribution" />
|
||||
</td>
|
||||
<td class="attribution-table__cell artist">
|
||||
<p>
|
||||
{{ attrib.artist }}
|
||||
</p>
|
||||
<ul>
|
||||
<li v-if="attrib.links.furaffinity">
|
||||
<a :href="attrib.links.furaffinity" title="Fur Affinity">
|
||||
<FAIcon />
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="attrib.links.twitter">
|
||||
<a :href="attrib.links.twitter" title="Twitter">
|
||||
<TwitterIcon />
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.attribution-table {
|
||||
&__cell {
|
||||
&.artwork {
|
||||
width: 10rem;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.artist {
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
flex: 0 0 2rem;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
background: var(--color-artist-link-background);
|
||||
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
margin: 0 0.25rem;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
flex: 1 1 auto;
|
||||
padding: 0.375rem;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: var(--color-artist-link-icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__row {
|
||||
&:hover {
|
||||
li {
|
||||
background: var(--color-artist-link-background-hover);
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: var(--color-artist-link-icon-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,33 +1,30 @@
|
|||
<script setup lang="ts">
|
||||
interface ColorDict {
|
||||
name: string;
|
||||
value: string;
|
||||
name: string
|
||||
value: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
colors: Array<ColorDict>;
|
||||
colors: ColorDict[]
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="color-table">
|
||||
<thead class="color-table__head">
|
||||
<tr class="color-table__row">
|
||||
<th class="color-table__heading name">Body part</th>
|
||||
<th class="color-table__heading value">Value</th>
|
||||
<th class="color-table__heading color">Color</th>
|
||||
<th class="color-table__heading name">{{ $t('data.colors.headings[0]') }}</th>
|
||||
<th class="color-table__heading value">{{ $t('data.colors.headings[1]') }}</th>
|
||||
<th class="color-table__heading color">{{ $t('data.colors.headings[2]') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="color-table__body">
|
||||
<tr class="color-table__row" v-for="(color, idx) in colors" :key="idx">
|
||||
<td class="color-table__cell name">{{ color.name }}</td>
|
||||
<td class="color-table__cell name">{{ $t(color.name) }}</td>
|
||||
<td class="color-table__cell value">{{ color.value }}</td>
|
||||
<td
|
||||
class="color-table__cell color"
|
||||
:style="{ 'background-color': color.value }"
|
||||
></td>
|
||||
<td class="color-table__cell color" :style="{ 'background-color': color.value }"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -35,67 +32,30 @@ defineProps<Props>();
|
|||
|
||||
<style lang="scss">
|
||||
.color-table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
max-width: var(--container-width-tables);
|
||||
margin: 2rem auto;
|
||||
padding: var(--color-table-spacing);
|
||||
|
||||
&__heading,
|
||||
&__cell {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
&__heading {
|
||||
font-weight: bold;
|
||||
background-color: var(--color-table-heading-background);
|
||||
color: var(--color-table-heading-text-color);
|
||||
|
||||
&:first-child {
|
||||
border-radius: var(--color-table-border-radius) 0 0 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 var(--color-table-border-radius) 0 0;
|
||||
}
|
||||
|
||||
&.name {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&__cell {
|
||||
background-color: var(--color-table-cell-background);
|
||||
color: var(--color-table-cell-text-color);
|
||||
|
||||
&.name {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&.value {
|
||||
font-family: monospace;
|
||||
font-family:
|
||||
Menlo,
|
||||
JetBrains Mono,
|
||||
Source Code Pro,
|
||||
Monaco,
|
||||
Ubuntu Mono,
|
||||
Roboto Mono,
|
||||
Cascadia Code,
|
||||
Consolas,
|
||||
monospace;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&.color {
|
||||
min-width: var(--color-table-color-cell-width);
|
||||
}
|
||||
}
|
||||
|
||||
&__row:hover &__cell {
|
||||
background-color: var(--color-table-row-hover);
|
||||
color: var(--color-table-cell-text-color-hover);
|
||||
}
|
||||
|
||||
&__row:last-child &__cell {
|
||||
&:first-child {
|
||||
border-radius: 0 0 0 var(--color-table-border-radius);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 0 var(--color-table-border-radius) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
37
src/components/DataTable.vue
Normal file
|
@ -0,0 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
interface Props {
|
||||
headings: string[]
|
||||
data: string[][]
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="data-table">
|
||||
<thead class="data-table__head">
|
||||
<tr class="data-table__row">
|
||||
<th class="data-table__heading" v-for="(heading, idx) in headings" :key="idx">
|
||||
{{ $t(heading) }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="data-table__body">
|
||||
<tr class="data-table__row" v-for="(row, idx) in data" :key="idx">
|
||||
<td class="data-table__cell" v-for="(cell, idx) in row" :key="idx">
|
||||
{{ $t(cell) }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.data-table {
|
||||
table-layout: fixed;
|
||||
|
||||
&__cell:first-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,30 +0,0 @@
|
|||
<template>
|
||||
<header class="header-bar">
|
||||
<slot></slot>
|
||||
|
||||
<h1 class="header-bar__title">
|
||||
<slot name="heading"></slot>
|
||||
</h1>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.header-bar {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
|
||||
background-color: var(--color-header-bar);
|
||||
backdrop-filter: blur(0.5rem);
|
||||
|
||||
&__title {
|
||||
color: var(--color-header-bar-title);
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
27
src/components/LanguageButton.vue
Normal file
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<div class="lang-button">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.lang-button {
|
||||
position: fixed;
|
||||
inset: 0.25rem 0.5rem auto auto;
|
||||
min-width: 3rem;
|
||||
z-index: 9001;
|
||||
cursor: pointer;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
inset: 0.325rem 0 0.7rem 0;
|
||||
content: '';
|
||||
background-color: var(--color-background);
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: var(--color-text);
|
||||
}
|
||||
}
|
||||
</style>
|
49
src/components/LinkButton.vue
Normal file
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
interface Props {
|
||||
href?: string
|
||||
download?: boolean | any
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a class="link-button" :href="href" :[download]="download">
|
||||
<slot></slot>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.link-button {
|
||||
display: block;
|
||||
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
||||
background-color: var(--color-button);
|
||||
color: var(--color-button-text);
|
||||
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
|
||||
margin: 0.5rem 0;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
box-shadow: 0 0.5rem 0 0 var(--color-button-box-shadow);
|
||||
|
||||
transition: all 0.1s ease-out;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
top: -0.25rem;
|
||||
box-shadow: 0 0.75rem 0 0 var(--color-button-box-shadow);
|
||||
}
|
||||
|
||||
&:active {
|
||||
top: 0.25rem;
|
||||
box-shadow: 0 0.25rem 0 0 var(--color-button-box-shadow);
|
||||
}
|
||||
}
|
||||
</style>
|
93
src/components/LocaleSwitcher.vue
Normal file
|
@ -0,0 +1,93 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import CircleCheckIcon from '@/assets/icons/CircleCheckIcon.vue'
|
||||
import CircleIcon from '@/assets/icons/CircleIcon.vue'
|
||||
|
||||
interface LocaleOption {
|
||||
code: string
|
||||
name: string
|
||||
flag: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
modelValue: string
|
||||
id: string
|
||||
locales: LocaleOption[]
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', value: string): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
const selectModel = computed({
|
||||
get() {
|
||||
return props.modelValue
|
||||
},
|
||||
set(value) {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="localeselect">
|
||||
<div v-for="locale in locales" class="localeselect__locale" :key="`locale-${locale.code}`">
|
||||
<input
|
||||
type="radio"
|
||||
name="lang"
|
||||
class="localeselect__input"
|
||||
:id="`lang-${locale.code}`"
|
||||
:value="locale.code"
|
||||
v-model="selectModel"
|
||||
/>
|
||||
<label class="localeselect__label" :for="`lang-${locale.code}`">
|
||||
<CircleCheckIcon v-if="$i18n.locale === locale.code" />
|
||||
<CircleIcon v-else />
|
||||
<span>{{ locale.name }} {{ locale.flag }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.localeselect {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
|
||||
margin: var(--paragraph-margin) 0;
|
||||
|
||||
&__locale {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
flex: 1 0 1.25rem;
|
||||
fill: var(--color-text);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
span {
|
||||
flex: 1 0 auto;
|
||||
margin: 0 0 0 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
95
src/components/ModalDialog.vue
Normal file
|
@ -0,0 +1,95 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface Props {
|
||||
id: string
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const modal = ref<HTMLDialogElement>()
|
||||
|
||||
const showModal = () => {
|
||||
modal.value?.showModal()
|
||||
document.body.inert = true
|
||||
document.body.classList.add('scroll-lock')
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
modal.value?.close()
|
||||
document.body.inert = false
|
||||
document.body.classList.remove('scroll-lock')
|
||||
}
|
||||
|
||||
defineExpose({ showModal, close })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<dialog :id="id" class="modal" ref="modal">
|
||||
<form method="dialog" class="modal__content">
|
||||
<h2 class="modal__heading">
|
||||
<slot name="heading"></slot>
|
||||
</h2>
|
||||
|
||||
<div class="modal__message">
|
||||
<slot name="message"></slot>
|
||||
</div>
|
||||
|
||||
<div class="modal__buttons">
|
||||
<slot name="buttons"></slot>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.modal {
|
||||
position: fixed;
|
||||
|
||||
background: var(--color-modal-background);
|
||||
|
||||
color: var(--color-text);
|
||||
|
||||
width: var(--modal-width);
|
||||
|
||||
margin: auto;
|
||||
border: var(--modal-border);
|
||||
border-radius: 1rem;
|
||||
padding: 1rem;
|
||||
|
||||
animation: fade-in 1s;
|
||||
|
||||
&::backdrop {
|
||||
backdrop-filter: blur(1rem);
|
||||
animation: fade-in 1s;
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
> * {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
&__buttons .link-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,27 +0,0 @@
|
|||
<template>
|
||||
<div class="nav-toggle">
|
||||
<div class="nav-toggle__line"></div>
|
||||
<div class="nav-toggle__line"></div>
|
||||
<div class="nav-toggle__line"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.nav-toggle {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: space-around;
|
||||
cursor: pointer;
|
||||
|
||||
height: 1.75rem;
|
||||
margin: var(--container-spacing-top-safe) 1rem 1rem
|
||||
var(--container-spacing-left-safe);
|
||||
width: 2rem;
|
||||
|
||||
&__line {
|
||||
flex: 0 0 0.25rem;
|
||||
background-color: var(--color-navigation-toggle);
|
||||
border-radius: 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
86
src/components/NavigationItem.vue
Normal file
|
@ -0,0 +1,86 @@
|
|||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
interface Props {
|
||||
icon: unknown | object
|
||||
href: string
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterLink class="navigation__link" :to="href">
|
||||
<component class="navigation__link-icon" :is="icon" />
|
||||
<span class="navigation__link-text">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.navigation {
|
||||
&__link {
|
||||
flex: var(--navigation-link-flex);
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: var(--navigation-link-justify);
|
||||
align-items: center;
|
||||
|
||||
height: var(--navigation-link-height);
|
||||
|
||||
padding: var(--navigation-link-padding);
|
||||
|
||||
color: var(--color-router-link);
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--navigation-link-box-shadow);
|
||||
|
||||
svg {
|
||||
fill: var(--color-router-link-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &-text {
|
||||
color: var(--color-router-link-hover);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin: var(--navigation-link-last-child-margin);
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
&.router-link-exact-active {
|
||||
color: var(--color-router-link-hover);
|
||||
background-color: var(--color-router-link);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-router-link-hover);
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: var(--color-router-link-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__link-icon {
|
||||
width: var(--navigation-link-icon-size);
|
||||
min-width: var(--navigation-link-icon-size);
|
||||
max-width: var(--navigation-link-icon-size);
|
||||
margin: 0 var(--navigation-link-icon-spacing);
|
||||
fill: var(--color-router-link);
|
||||
}
|
||||
|
||||
&__link-text {
|
||||
display: var(--navigation-link-display);
|
||||
font-size: var(--navigation-link-text-font-size);
|
||||
margin: 0 0 0 1rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
interface Props {
|
||||
dropshadow?: boolean
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<figure class="figure">
|
||||
<picture class="figure__image">
|
||||
<picture class="figure__image" :class="{ 'figure__image--dropshadow': dropshadow }">
|
||||
<slot></slot>
|
||||
</picture>
|
||||
|
||||
|
@ -12,19 +20,30 @@
|
|||
|
||||
<style lang="scss">
|
||||
.figure {
|
||||
max-width: var(--container-width-images);
|
||||
max-width: var(--refimage-max-width);
|
||||
margin: 0 auto;
|
||||
|
||||
&__image,
|
||||
&__caption {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
&__image {
|
||||
filter: drop-shadow(0.5rem 0.25rem 0.375rem #000);
|
||||
&--dropshadow {
|
||||
filter: drop-shadow(0.5rem 0.25rem 0.375rem #000);
|
||||
}
|
||||
}
|
||||
|
||||
&__caption {
|
||||
text-align: center;
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 35rem;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
22
src/components/SiteFooter.vue
Normal file
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<footer class="footer">
|
||||
<div class="footer__content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.footer {
|
||||
background-color: var(--color-footer-background);
|
||||
margin: var(--navigation-cutout);
|
||||
padding: 1px 0;
|
||||
|
||||
&__content {
|
||||
text-align: center;
|
||||
max-width: var(--textblock-max-width);
|
||||
margin: var(--paragraph-margin) auto;
|
||||
padding: var(--textblock-padding);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,131 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
import { RouterLink } from "vue-router";
|
||||
import NavToggle from "@/components/NavToggle.vue";
|
||||
|
||||
interface Props {
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
interface Route {
|
||||
href: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const routerLinks: Array<Route> = [
|
||||
{ href: "/", title: "Home" },
|
||||
{ href: "/anatomy", title: "Anatomy" },
|
||||
{ href: "/career-path", title: "Career Path" },
|
||||
];
|
||||
|
||||
const props = defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="navigation" :class="{ open: props.isActive }">
|
||||
<div class="navigation__background" @click="$emit('selected')"></div>
|
||||
|
||||
<NavToggle class="navigation__toggle" @click="$emit('selected')" />
|
||||
|
||||
<ul class="navigation__list">
|
||||
<li
|
||||
class="navigation__item"
|
||||
v-for="(route, idx) in routerLinks"
|
||||
:key="idx"
|
||||
>
|
||||
<RouterLink :to="route.href" @click="$emit('selected')">
|
||||
{{ route.title }}
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
<nav class="navigation">
|
||||
<div class="navigation__list">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.navigation {
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
inset: var(--navigation-position);
|
||||
overflow: hidden;
|
||||
|
||||
&__background {
|
||||
position: fixed;
|
||||
width: var(--navigation-width);
|
||||
height: var(--navigation-height);
|
||||
|
||||
background-color: rgba(#000, 0);
|
||||
backdrop-filter: blur(0rem);
|
||||
background-color: var(--color-navigation-background);
|
||||
|
||||
transition: 1s;
|
||||
}
|
||||
transition: 0.4s;
|
||||
z-index: 1;
|
||||
|
||||
&.open &__background {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
background-color: rgba(#000, 0.75);
|
||||
backdrop-filter: blur(0.25rem);
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
&.open &__toggle {
|
||||
display: flex;
|
||||
top: 0;
|
||||
left: 0;
|
||||
&:hover {
|
||||
width: var(--navigation-width-expanded);
|
||||
}
|
||||
|
||||
&__list {
|
||||
background-color: var(--color-navigation-background);
|
||||
width: var(--navigation-width);
|
||||
display: flex;
|
||||
flex-flow: var(--navigation-flow);
|
||||
justify-content: var(--navigation-justify);
|
||||
align-items: var(--navigation-align);
|
||||
|
||||
list-style: none;
|
||||
|
||||
margin: 0;
|
||||
padding: 3.5rem 0 0 0;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: -100vw;
|
||||
|
||||
transition: left ease-in-out 0.4s;
|
||||
}
|
||||
|
||||
&.open &__list {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&__item {
|
||||
font-size: var(--navigation-item-font-size);
|
||||
line-height: var(--navigation-item-line-height);
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
color: var(--color-router-link);
|
||||
padding: 0 var(--container-spacing-right-safe) 0
|
||||
var(--container-spacing-left-safe);
|
||||
|
||||
box-shadow: inset 0 0 0 0 var(--color-link-text-underline);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-router-link-hover);
|
||||
box-shadow: inset var(--navigation-width) 0 0 0 var(--color-router-link);
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "👉";
|
||||
font-size: 2rem;
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
|
||||
&.router-link-exact-active {
|
||||
color: var(--color-router-link-active);
|
||||
}
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<template>
|
||||
<div class="textblock">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.textblock {
|
||||
max-width: var(--container-width-text);
|
||||
margin: var(--content-spacing);
|
||||
}
|
||||
</style>
|
|
@ -1,37 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
|
||||
interface Props {
|
||||
datetime: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const dateLabels = computed<Record<string, string>>(() => {
|
||||
const date = new Date(props.datetime);
|
||||
const locale = "de-DE";
|
||||
|
||||
const dates = {
|
||||
year: date.toLocaleDateString(locale, { year: "numeric" }),
|
||||
month: date.toLocaleDateString(locale, { month: "short" }),
|
||||
day: date.toLocaleDateString(locale, { day: "numeric" }),
|
||||
};
|
||||
|
||||
return dates;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li class="timeline-item">
|
||||
<time class="timeline-item__datetime" :datetime="datetime">
|
||||
<div class="timeline-item__label">{{ dateLabels.day }}</div>
|
||||
<div class="timeline-item__label">{{ dateLabels.month }}</div>
|
||||
<div class="timeline-item__label">{{ dateLabels.year }}</div>
|
||||
</time>
|
||||
<div class="timeline-item__icon">
|
||||
<slot name="icon"></slot>
|
||||
</div>
|
||||
<section class="timeline-item__content">
|
||||
<h1 class="timeline-item__headline">
|
||||
<h2 class="timeline-item__headline">
|
||||
<slot name="headline"></slot>
|
||||
</h1>
|
||||
</h2>
|
||||
|
||||
<div class="timeline-item__text">
|
||||
<slot name="content"></slot>
|
||||
|
@ -51,61 +26,60 @@ const dateLabels = computed<Record<string, string>>(() => {
|
|||
position: relative;
|
||||
|
||||
&:not(:last-child):before {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: var(--timeline-position-top);
|
||||
left: var(--timeline-stroke-position);
|
||||
inset: var(--timeline-stroke-position-odd);
|
||||
height: var(--timeline-stroke-length);
|
||||
border-left: var(--timeline-stroke-border);
|
||||
border-left: var(--timeline-stroke-thickness) solid var(--timeline-stroke-color);
|
||||
}
|
||||
|
||||
@media (min-width: 64em) {
|
||||
&:nth-child(odd) {
|
||||
margin: var(--timeline-item-margin-odd);
|
||||
}
|
||||
&:nth-child(odd) {
|
||||
margin: var(--timeline-item-margin-odd);
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
margin: var(--timeline-item-margin-even);
|
||||
&:nth-child(even) {
|
||||
margin: var(--timeline-item-margin-even);
|
||||
|
||||
&:before {
|
||||
left: auto;
|
||||
right: var(--timeline-stroke-position);
|
||||
}
|
||||
|
||||
.timeline-item__datetime {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.timeline-item__content {
|
||||
text-align: right;
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
&:before {
|
||||
inset: var(--timeline-stroke-position-even);
|
||||
}
|
||||
}
|
||||
|
||||
&__datetime {
|
||||
font-size: var(--timeline-circle-font-size);
|
||||
text-align: center;
|
||||
line-height: 1.1;
|
||||
|
||||
background-color: var(--timeline-circle-background-color);
|
||||
|
||||
&__icon {
|
||||
flex: 0 0 var(--timeline-circle-size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: var(--timeline-circle-size);
|
||||
height: var(--timeline-circle-size);
|
||||
|
||||
background-color: var(--timeline-circle-background);
|
||||
|
||||
margin: 0;
|
||||
border: var(--timeline-stroke-border);
|
||||
border: var(--timeline-stroke-thickness) solid var(--timeline-stroke-color);
|
||||
border-radius: 100%;
|
||||
padding: var(--timeline-circle-padding);
|
||||
|
||||
svg {
|
||||
fill: var(--timeline-icon-color);
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
&:nth-child(even) &__icon {
|
||||
order: var(--timeline-item-flex-order);
|
||||
}
|
||||
|
||||
&__content {
|
||||
flex: 1 0 0;
|
||||
margin: 0 0 0 1rem;
|
||||
margin: 0;
|
||||
padding: var(--timeline-item-content-padding-odd);
|
||||
}
|
||||
|
||||
&:nth-child(even) &__content {
|
||||
text-align: var(--timeline-item-text-align-even);
|
||||
padding: var(--timeline-item-content-padding-even);
|
||||
}
|
||||
|
||||
&__headline {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<style lang="scss">
|
||||
.timeline {
|
||||
max-width: calc(var(--timeline-circle-size) * 15);
|
||||
max-width: var(--timeline-max-width);
|
||||
position: relative;
|
||||
|
||||
margin: 0 auto;
|
||||
|
|
70
src/components/WelcomeHeader.vue
Normal file
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<header class="welcome">
|
||||
<div class="welcome__image">
|
||||
<picture>
|
||||
<source srcset="@/assets/viktor-avatar.png?w=400;800&format=avif&quality=75&as=srcset" />
|
||||
<source srcset="@/assets/viktor-avatar.png?w=400;800&format=webp&quality=100&as=srcset" />
|
||||
<img src="@/assets/viktor-avatar.png?w=400&format=png" alt="Viktor Avatar" />
|
||||
</picture>
|
||||
</div>
|
||||
|
||||
<div class="welcome__heading">
|
||||
<h1 class="welcome__mainline">
|
||||
<slot name="main"></slot>
|
||||
</h1>
|
||||
<h2 class="welcome__subline">
|
||||
<slot name="sub"></slot>
|
||||
</h2>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.welcome {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-evenly;
|
||||
align-items: var(--welcome-headings-align-items);
|
||||
|
||||
width: 100%;
|
||||
max-width: 50rem;
|
||||
|
||||
margin: 0 auto;
|
||||
padding: var(--welcome-padding);
|
||||
transition: 0.2s ease-out;
|
||||
|
||||
&__image {
|
||||
flex: 0 1 15rem;
|
||||
|
||||
background-color: var(--theme-c-desert-sand-translucent);
|
||||
|
||||
border: 0.5rem solid var(--theme-c-walnut-brown);
|
||||
border-radius: 2rem;
|
||||
|
||||
transform: scale(0.84) translateX(15%) rotateZ(calc(-1 * (11 * 1deg)));
|
||||
transform-origin: 0 100%;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transform: scale(1.2) rotateZ(calc(11 * 1deg));
|
||||
}
|
||||
}
|
||||
|
||||
&__heading {
|
||||
flex: 0 1 auto;
|
||||
text-align: var(--welcome-headings-text-align);
|
||||
line-height: 1.6;
|
||||
transition: 0.2s ease-out;
|
||||
}
|
||||
|
||||
&__mainline {
|
||||
margin: 1rem 0;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
7
src/lang/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import en from './translations/en.json'
|
||||
import de from './translations/de.json'
|
||||
|
||||
export default {
|
||||
en,
|
||||
de
|
||||
}
|
138
src/lang/translations/de.json
Normal file
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"welcomeHeader": {
|
||||
"mainTitle": "Viktor Kraastav",
|
||||
"subTitle": "Charakter-Referenzseite"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Startseite",
|
||||
"general": "Allgemein",
|
||||
"anatomy": "Anatomie",
|
||||
"careerPath": "Lebenslauf",
|
||||
"attributions": "Zuteilung"
|
||||
},
|
||||
"langswitcher": {
|
||||
"title": "Sprache",
|
||||
"prompt": "Diese Seite anzeigen in:",
|
||||
"buttonClose": "Schließen"
|
||||
},
|
||||
"data": {
|
||||
"general": {
|
||||
"heading": ["Schlüssel", "Wert"],
|
||||
"fullName": ["Vollständiger Name", "Viktor Kraastav"],
|
||||
"dob": ["Geboren am"],
|
||||
"gender": ["Geschlecht", "männlich ♂️"],
|
||||
"height": ["Größe"],
|
||||
"weight": ["Gewicht"]
|
||||
},
|
||||
"sexuality": {
|
||||
"heading": ["Schlüssel", "Wert"],
|
||||
"identifiesAs": ["Identifiziert sich als", "Schwul"],
|
||||
"preferredRole": ["Bevorzugte Rolle", "Passiv"]
|
||||
},
|
||||
"colors": {
|
||||
"headings": ["Körperteil", "Wert", "Farbe"],
|
||||
"front": "Front",
|
||||
"limbs": "Arme, Beine",
|
||||
"back": "Rücken",
|
||||
"spine": "Wirbelsäule, Schweif",
|
||||
"tissue": "Frecklinge, Gewebe",
|
||||
"spikes": "Stacheln, Keule",
|
||||
"eyesPrimary": "Augen (Hauptfarbe)",
|
||||
"eyesSecondary": "Augen (Highlights)"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"heading": "Willkommen auf Viktors Referenzseite",
|
||||
"paragraphs": [
|
||||
"Hier erfährst du alles über den Ankylosaurus namens Viktor.",
|
||||
"Wähle einen Punkt aus der Navigation, um einzusteigen!"
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"personality": {
|
||||
"heading": "Persönlichkeit",
|
||||
"paragraphs": [
|
||||
"Viktor ist kein Mann vieler Worte, seine Ausdrucksweise ist einfach und direkt und manchmal auch etwas unverblümt. Diese forsche Art kommt nicht bei jedem gut an und bringt ihn regelmäßig in Schwierigkeiten.",
|
||||
"Gleichzeitig ist das aber auch Ausdruck seines überschwänglichen Selbstbewusstseins. Er lässt sich von niemandem etwas gefallen und zögert nicht, jemandem die Meinung zu geigen. Wenn das zu Handgreiflichkeiten führt, nimmt er diese in Kauf.",
|
||||
"All das lässt ihn vielleicht wie einen wirklich unangenehmen Zeitgenossen erscheinen, aber er schätzt die Gesellschaft von Leuten denen er vertraut sehr. Allerdings ist er sehr wählerisch, wen er zu diesem Personenkreis zählt. Er schätzt den persönlichen Kontakt, am liebsten bei ein paar Bier in seiner Lieblingsbar.",
|
||||
"Er mag es einfach, deshalb ist er auch kein großer Fan von Hightech. Er hat zwar ein Smartphone, aber er hasst es genauso sehr wie die Tatsache, dass er darauf angewiesen ist, eines zu besitzen."
|
||||
]
|
||||
},
|
||||
"sexuality": {
|
||||
"heading": "Sexualität",
|
||||
"paragraphs": [
|
||||
"Als Teenager bemerkte Viktor, dass er über die Jungs in seiner Klasse ein bisschen anders dachte. Vor allem im Sportunterricht neigte er dazu, seine Klassenkameraden länger zu beobachten, wenn sie sich in der Umkleidekabine rauften, wie es pubertierende Jungs eben tun. Er konnte sich jedoch nie ganz mit dem Gedanken anfreunden, dass er vielleicht ein bisschen anders ist als seine Freunde, die sich alle für Mädchen zu interessieren begannen, im Gegensatz zu ihm, der sich mehr für seine Kumpels interessierte.",
|
||||
"Als er älter wurde, lernte er langsam, sich mit der Tatsache abzufinden, dass er in seinen Kumpels mehr sah als nur Freunde. Trotzdem hielt er sich weiterhin bedeckt.",
|
||||
"Bis zu einem Abend auf einer Party, als sich einer seiner Freunde darüber beschwerte, dass ihn seine Freundin nicht mehr ranlassen würde. Die beiden waren schon gut angetrunken und Viktor machte ihm lallend den Vorschlag, dass er ihm als sein Kumpel aushelfen würde. Zuerst war sein Freund von dem Angebot irritiert, stimmte aber schließlich zu. Die beiden schlichen sich in ein Schlafzimmer in der Wohnung des Gastgebers, wo er seinen Freund den ganzen aufgestauten Druck in ihm ablassen ließ. Er erinnerte sich nicht mehr an viel von der Party, aber er vergaß nicht, wie gut es sich anfühlte, sich einem anderen Mann hinzugeben."
|
||||
]
|
||||
}
|
||||
},
|
||||
"anatomy": {
|
||||
"images": {
|
||||
"back": { "caption": "Viktor Referenz" },
|
||||
"front": { "caption": "Viktor Vorderseite" }
|
||||
},
|
||||
"paragraphs": [
|
||||
[
|
||||
"Viktor ist ein zweibeiniger, plantigrader Ankylosaurus. Seine Haut ist größtenteils zweifarbig, mit verschiedenen Brauntönen.",
|
||||
"Seine Stirn, Nase, Brust, sein Bauch und sein Schritt haben eine helle Wüstensandfarbe, die sich entlang der Unterseite seines Schwanzes fortsetzt.",
|
||||
"Seine Wangen, Schultern, Oberschenkel und sein Rücken sind dagegen in einem satten Walnussbraun gehalten, das sich auch an den Seiten seines Schwanzes wiederfindet. Vom Hinterkopf über die Wirbelsäule bis zur Schwanzspitze verläuft ein durchgehender Streifen in tiefdunklem Zedernbraun. Arme und Beine zeichnen sich durch ein helles, erdiges Braun aus."
|
||||
],
|
||||
[
|
||||
"Sein ganzer Körper ist mit aquamarinfarbenen Flecken gesprenkelt, die sich paarweise aus einem großen und einem kleinen Fleck zusammensetzen. Einzige Ausnahmen sind die Flecken auf den Wangen und hinter den unteren Wangenhörnern, die in Dreiergruppen auftreten, und die Oberseite seiner Schnauze, die einen großen einzelnen Fleck aufweist. Auch Maul, Zunge, Nasenlöcher und alle anderen Gewebe seines Körpers weisen diese Farbe auf.",
|
||||
"Seine Augen leuchten in einer Mischung aus hellem Meeresgrün und elektrisierendem Blau.",
|
||||
"Die Hörner und Krallen sind von einem typischen Knochenweiß. Angefangen mit dem Doppelhornpaar auf seinem Kopf zieht sich eine parallele Linie von Hörnern über seinen Rücken, mit zusätzlichen Hörnern an den Schultern und Oberschenkeln. Auch sein Schwanz ist auf beiden Seiten über die gesamte Länge mit Hörnern versehen. An der Spitze des Schwanzes befindet sich eine keulenartige Verknöcherung, mit der er Angreifer abwehren kann.",
|
||||
"Seinen starken, stämmigen Körperbau verdankt er jahrelanger harter körperlicher Arbeit."
|
||||
]
|
||||
]
|
||||
},
|
||||
"career": {
|
||||
"paragraphs": [
|
||||
"Viktor hatte in der Vergangenheit viele verschiedene Jobs, von denen einige sehr prägend waren, während andere nur die Rechnungen bezahlten."
|
||||
],
|
||||
"jobs": [
|
||||
{
|
||||
"title": "Kneipenwirt",
|
||||
"desc": "Viktors berufliche Laufbahn begann als Barkeeper in einer Kneipe in seiner Heimatstadt. Dort fungierte er oft auch als Türsteher, wenn ein paar Gäste einen über den Durst getrunken hatten und einen Aufstand machten. Ein entscheidender Moment in diesem Job war, als einer von ihnen über den Tresen kletterte und ihn mit einer zerbrochenen Flasche bedrohte. Als er zu Boden gerungen wurde und eine zerbrochene Flasche vor seinem Gesicht hatte, musste er in Sekundenbruchteilen eine Entscheidung treffen. Mit einem kräftigen Schwung seines Schwanzknochens schlug er den Angreifer nieder. Diese Erfahrung lehrte ihn, wie wichtig es ist, sich effektiv gegen unangenehme Gesellen zu verteidigen und Bedrohungen auszuräumen, bevor sie entstehen."
|
||||
},
|
||||
{
|
||||
"title": "Holzfäller",
|
||||
"desc": "Nachdem er seine Heimatstadt verlassen hatte, begann Viktor sich als Holzfäller zu verdienen. Die Keule am Ende seines Schwanzes erwies sich dabei als sehr nützlich, denn sie diente ihm als Gegengewicht und ermöglichte es ihm, effizient und kraftvoll mit seiner Axt zuzuschlagen und selbst die größten Bäume mit Leichtigkeit zu fällen. Seine von Natur aus zähen Schuppen schützten ihn vor Splittern aus dem gefällten Holz. Die jahrelange harte körperliche Arbeit hat seinen Körper im Laufe der Jahre gestählt. Bevor er die gefällten Stämme zum Sägewerk brachte, machte Viktor immer eine Pause, um sich in der Stille des Waldes auszuruhen. Obwohl er die Abgeschiedenheit des Landlebens eine Zeit lang genoss, sehnte er sich wieder nach der Geselligkeit des Stadtlebens."
|
||||
},
|
||||
{
|
||||
"title": "Automachaniker",
|
||||
"desc": "Nach seinem Umzug in eine Vorstadt bewarb sich Viktor in einer Autowerkstatt, wo er lernte, wie man Autos repariert. Er wurde richtig gut darin und hatte Spaß daran, kaputten Fahrzeugen neues mechanisches Leben einzuhauchen. Mit der Zeit geriet die Werkstatt jedoch in finanzielle Schwierigkeiten, da es immer schwieriger wurde, an Ersatzteile zu kommen, da die Autohersteller diese nur an zertifizierte Reparaturpartner abgaben und die Zertifizierungen dafür unbezahlbar waren. Viktor musste zusehen, wie sich das Geschäft langsam verschlechterte, da immer mehr qualifizierte Mitarbeiter entlassen wurden, bis die Werkstatt schließlich für immer geschlossen wurde."
|
||||
},
|
||||
{
|
||||
"title": "Bauarbeiter",
|
||||
"desc": "Da er Gefallen an körperlich anstrengender Arbeit gefunden hatte, nahm Viktor einen Job als Bauarbeiter an. Mit einem Schutzhelm auf dem Kopf und einem Werkzeuggürtel um die Hüfte war er immer bereit, mit anzupacken (oder zuzuschlagen, wenn Mauern oder Felsbrocken abgetragen werden mussten). Da er durch seine früheren Jobs mehr als genug Krafttraining hatte, wurde er oft mit Tragearbeiten beauftragt, um die Baustelle zu räumen und Baumaterial zu transportieren. Nach getaner Arbeit genoss Viktor die Gesellschaft seiner Kollegen bei einem Feierabendbier bis spät in die Nacht. An einem dieser Abende wurde er im Schutze der Nacht mit einem Kollegen etwas leichtsinnig und beide wurden in flagranti erwischt, als sie auf der Baustelle miteinander rummachten. In den folgenden Wochen hielten die Kollegen Abstand zu Viktor und auch die gemeinsamen Abende lösten sich sehr schnell auf, als er sich zu ihnen gesellen wollte. Die anhaltende Ausgrenzung veranlasste ihn schließlich, sich etwas Neues zu suchen."
|
||||
},
|
||||
{
|
||||
"title": "Schweißer",
|
||||
"desc": "In seinem Beruf als Schweißer verbrachte Viktor seine Tage im Schichtbetrieb in einer Werkstatt. Neben Spezialwerkzeugen und Plasmaschweißgeräten benutzte er auch seinen kräftigen Schwanzknüppel, um Metallteile in Form zu hämmern. Er eignete sich eine Vielzahl von Schweißtechniken an, um Metallstrukturen zu verbinden oder zu reparieren. Er arbeitete mit einer Vielzahl von Legierungen wie Stahl, Aluminium und Titan. Viktor zeigte bei seiner Arbeit extreme Geschicklichkeit, große Präzision und Liebe zum Detail. Diese Hingabe war jedoch einem eifersüchtigen Kollegen ein Dorn im Auge, der Viktor als Konkurrenten ansah und gegen ihn intrigierte, indem er seine Arbeit sabotierte, was schließlich in seiner Kündigung endete, nachdem ein Kunde die Schweißerei wegen Pfusch verklagt hatte. Viktor hat nie herausgefunden, wer der Schuldige war, und der Verlust dieses Jobs lastet immer noch auf ihm."
|
||||
},
|
||||
{
|
||||
"title": "Lieferant",
|
||||
"desc": "Als Viktor knapp bei Kasse war, nahm er einen Job in der Gig-Economy als Fahrer an, der Pakete für einen großen Online-Lieferdienst ausfuhr. Durch seine früheren körperlich anstrengenden Jobs konnte er selbst sperrige Lieferungen relativ leicht an ihr Ziel bringen. Hätten ihm die Manager des Versandzentrums nicht ständig im Nacken gesessen, hätte er diesen Job vielleicht sogar noch länger behalten können. Aber als einer der Manager versuchte, ihn vor dem ganzen Team bloßzustellen, platzte ihm der Kragen und er brach ihm mit seiner Keule das Bein. Am nächsten Tag musste er sich natürlich nicht mehr zum Dienst melden."
|
||||
},
|
||||
{
|
||||
"title": "Hafenarbeiter",
|
||||
"desc": "Derzeit arbeitet Viktor an den Docks in der Hafenstadt, in die er gezogen ist. Zu seinen Hauptaufgaben gehören das Be- und Entladen von Schiffen und der Transport der Ladung zu und von den Lagerhäusern. Das geschäftige Treiben im Hafen geht ihm manchmal auf die Nerven. Vor allem, wenn die Besatzungen der anlegenden Schiffe nach langer Zeit wieder an Land kommen und deutlich machen, dass sie mit \"Landratten\" nicht viel Umgang haben. Viktor lässt sich davon allerdings nicht sonderlich beeindrucken und mault zurück, wenn er den Eindruck bekommt, dass sie auf Ärger aus sind."
|
||||
}
|
||||
]
|
||||
},
|
||||
"attributions": {
|
||||
"artwork": {
|
||||
"heading": "Kunstwerke",
|
||||
"headings": ["Kunstwerk", "Künstler"]
|
||||
},
|
||||
"other": {
|
||||
"heading": "Sonstiges",
|
||||
"headings": ["Typ", "Quelle"],
|
||||
"icons": ["Symbole"],
|
||||
"headingFont": ["Überschriften", "von"],
|
||||
"copyFont": ["Fließtext", "von"],
|
||||
"background": ["Hintergrund", ["Layered Waves aus", "von"]]
|
||||
}
|
||||
}
|
||||
}
|
138
src/lang/translations/en.json
Normal file
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"welcomeHeader": {
|
||||
"mainTitle": "Viktor Kraastav",
|
||||
"subTitle": "Character Reference Page"
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
"general": "General",
|
||||
"anatomy": "Anatomy",
|
||||
"careerPath": "Career Path",
|
||||
"attributions": "Attributions"
|
||||
},
|
||||
"langswitcher": {
|
||||
"title": "Language",
|
||||
"prompt": "View this page in:",
|
||||
"buttonClose": "Close"
|
||||
},
|
||||
"data": {
|
||||
"general": {
|
||||
"heading": ["Key", "Value"],
|
||||
"fullName": ["Full Name", "Viktor Kraastav"],
|
||||
"dob": ["Date of Birth"],
|
||||
"gender": ["Sex/Gender", "male ♂️"],
|
||||
"height": ["Height"],
|
||||
"weight": ["Weight"]
|
||||
},
|
||||
"sexuality": {
|
||||
"heading": ["Key", "Value"],
|
||||
"identifiesAs": ["Identifies as", "Gay"],
|
||||
"preferredRole": ["Preferred role", "Bottom"]
|
||||
},
|
||||
"colors": {
|
||||
"headings": ["Body part", "Value", "Color"],
|
||||
"front": "Front",
|
||||
"limbs": "Arms, legs",
|
||||
"back": "Back Main",
|
||||
"spine": "Back Spine",
|
||||
"tissue": "Highlight scales, tissue",
|
||||
"spikes": "Spikes, tail club",
|
||||
"eyesPrimary": "Eyes primary",
|
||||
"eyesSecondary": "Eyes secondary"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"heading": "Welcome to Viktor's Ref Page",
|
||||
"paragraphs": [
|
||||
"Here you can learn all about the ankylosaurus named Viktor.",
|
||||
"Pick an item from the navigation to dive in!"
|
||||
]
|
||||
},
|
||||
"general": {
|
||||
"personality": {
|
||||
"heading": "Personality",
|
||||
"paragraphs": [
|
||||
"Viktor is not a man of many words, his manner of expression is simple and direct, and sometimes a little blunt. This brash manner doesn't go down well with everyone and regularly gets him into trouble.",
|
||||
"At the same time, this is also an expression of his exuberant self-confidence. He won't take any crap from anyone and doesn't hesitate to give someone a piece of his mind. If that results in fisticuffs, he'll deal with them.",
|
||||
"All this may make him look like a really unpleasant fellow, but he greatly appreciates the company of people he trusts. He is very selective about whom he counts among this group of people, though. He appreciates personal contact, preferably over a few beers at his favorite bar.",
|
||||
"He likes things to be simple, which is why he is not a big fan of high-tech. He does have a smartphone, but he hates using it as much as he dislikes the fact he's dependent on owning one."
|
||||
]
|
||||
},
|
||||
"sexuality": {
|
||||
"heading": "Sexuality",
|
||||
"paragraphs": [
|
||||
"As a teenager, Viktor noticed that he felt a bit differently about the boys in his class. Especially in gym class, his eyes tended to linger longer on his classmates as they rough-housed in the locker room, as pubescent boys do. However, he could never quite come to terms with the idea that he might be a little different from his friends, who were all beginning to take an interest in girls, unlike him, who was more interested in his buddies.",
|
||||
"As he got older, he slowly learned to come to terms with the fact that he saw more in his buddies than just friends. However, he still kept a low profile.",
|
||||
"Until one evening at a party, when one of his friends complained that he wouldn't get any from his girlfriend. Both of them were already well intoxicated and Viktor made him the slurred proposal that he would help him out as his bro. At first his buddy was irritated by the offer, but eventually agreed. The two snuck into a bedroom at the host's place, where Viktor would let his buddy unload all the pent-up pressure inside him. He wouldn't remember much of the party, but what he didn't forget how good it felt to give himself to another man."
|
||||
]
|
||||
}
|
||||
},
|
||||
"anatomy": {
|
||||
"images": {
|
||||
"back": { "caption": "Viktor Ref" },
|
||||
"front": { "caption": "Viktor Frontal Shot" }
|
||||
},
|
||||
"paragraphs": [
|
||||
[
|
||||
"Viktor is a bipedal plantigrade Ankylosaurus. His skin is mostly bicolored, with several shades of brown.",
|
||||
"His forehead, nose, chest, belly and crotch are of light desert sand colors that run through the underside of his tail.",
|
||||
"His cheeks, shoulders, back and thighs, in contrast, stand out with a rich walnut brown, which is also found on the sides of his tail. From the back of his head, down his spine and across the top of his tail is a continuous strip of deep dark cedar brown. Arms and legs are distinguished by a light earthy brown."
|
||||
],
|
||||
[
|
||||
"His entire body is speckled with scattered aquamarine spots, which come in pairs of one large and one small spot. The only exceptions are the spots on his cheeks and behind his lower cheek horns, which come in threes and his the top side of his snout, which sports a big single spot. Mouth, tongue, nostrils and any other tissue of his body also feature this color.",
|
||||
"His eyes shine with a mixture of light sea green and electric blue.",
|
||||
"Horns and claws are of a typical bone white. Starting with the double pair of horns on his head, a parallel line of horns continues down his back, with additional horns adorning his shoulders and thighs. His tail is also armed with horns on both sides along its entire length. At the tip of the tail is a club-like ossification that he can use for fending off foes.",
|
||||
"He owes his strong, stocky physique to years of hard physical labor."
|
||||
]
|
||||
]
|
||||
},
|
||||
"career": {
|
||||
"paragraphs": [
|
||||
"Viktor's had many different jobs in the past, some of which where very formative, other's just paid the bills."
|
||||
],
|
||||
"jobs": [
|
||||
{
|
||||
"title": "Bartender",
|
||||
"desc": "Viktor's professional career began as a bartender at a pub in his hometown. There he often doubled as a bouncer when a few guests got too drunk and started making a fuss. A defining moment of that job was when someone climbed over the counter and threatened him with a broken bottle. Wrestled to the ground and with a broken bottle in front of his face, he had to make a split-second decision. With a powerful swing of his tail bone, he knocked the attacker down. This experience taught him the importance of effectively defending himself against unpleasant fellows and to eliminate threats before they get close to him ever again."
|
||||
},
|
||||
{
|
||||
"title": "Lumberjack",
|
||||
"desc": "After leaving his hometown, Viktor started working as a lumberjack. The club at the end of his tail came very much in handy as a counterweight for each swing of his axe, allowing him to strike efficiently and powerfully, felling even the largest trees with relative ease. His naturally tough scales protected him from splinters from the felled wood. The long-lasting hard physical work toughened his body over the years. Before taking the cut logs to the sawmill, Viktor always took a break to rest in the peace and quiet of the forest. Although he enjoyed the seclusion of the country life for a while, he was longing for the sociability of city life again."
|
||||
},
|
||||
{
|
||||
"title": "Car Mechanic",
|
||||
"desc": "Moving into a suburban town, Viktor applied at an auto repair shop, where he learned the ins and outs of fixing cars. He became really good at it and enjoyed breathing new mechanical life into broken down vehicles. However, as time went on, the repair shop faced financial troubles, as it became increasingly difficult to come by spare parts as auto makers would only deal them to certified repair partners and certifications were prohibitively expensive. Viktor had to watch business slowly deteriorate, as skilled coworkers kept getting laid off, until the repair shop closed down for good."
|
||||
},
|
||||
{
|
||||
"title": "Construction Worker",
|
||||
"desc": "Having taken a liking in physically demanding work, Viktor took on a job as a construction worker. Hard hat perched atop his head and belt tool slung around his waist, he was always ready to lend a hand (or tail if walls or boulders needed a good teardown). Since he had more than enough strength training from his previous jobs, he was often assigned carrying jobs to clear the site and haul building materials. After work was done, Viktor enjoyed the company of his colleagues over an after-work beer until late in the evenings. On one of these evenings, he got a little reckless with a colleague under the veil of the night and both were caught in the act of fooling around with each other on the construction site. In the following weeks, the colleagues kept their distance from Viktor and the evenings together also dissolved very quickly when he joined them. The continued ostracization ultimately prompted him to look for something new."
|
||||
},
|
||||
{
|
||||
"title": "Welder",
|
||||
"desc": "In his job as a welder, Viktor spent his days working shifts in a workshop. In addition to special tools and plasma welders, he also used his powerful tail club to hammer metal parts into shape. He acquired a wide variety of welding techniques to join or repair metal structures. He worked with a wide variety of alloys such as steel, aluminum and titanium. Viktor showed extreme skill in his work with great precision and attention to detail. However, this dedication was a thorn in the side of a jealous colleague who saw Viktor as a rival and schemed against him, sabotaging his work, which ultimately ended in his termination after a customer sued the welding shop for botching the job. Viktor never found out who the culprit was, and the loss of that job still hangs over him."
|
||||
},
|
||||
{
|
||||
"title": "Delivery Driver",
|
||||
"desc": "When Viktor was strapped for cash, he took on a job in the gig economy as a driver delivering packages for a large online delivery service. His previous physically demanding jobs allowed him to haul even bulky deliveries to their destination with relative ease. If the shipping center managers hadn't been breathing down his neck constantly, he might have held this job even longer. But after one of the managers tried to show him up in front of the whole team, he snapped and broke their leg with his tail club. Of course, he didn't have to report for duty the next day."
|
||||
},
|
||||
{
|
||||
"title": "Docks Werehouse Worker",
|
||||
"desc": "Currently Viktor works at the docks in the port town he moved to. His main responsibilities include loading and unloading cargo from ships and transporting it to and from warehousing. The hustle and bustle of the port sometimes gets on his nerves. Especially when the crew of docking ships come ashore again after a long time and make it clear that they don't have much contact with \"landlubbers\". Viktor doesn't get particularly impressed by this and foul mouths them right back if he gets the impression they're looking for trouble."
|
||||
}
|
||||
]
|
||||
},
|
||||
"attributions": {
|
||||
"artwork": {
|
||||
"heading": "Artworks",
|
||||
"headings": ["Artwork", "Artist"]
|
||||
},
|
||||
"other": {
|
||||
"heading": "Other",
|
||||
"headings": ["Type", "Source"],
|
||||
"icons": ["Icons"],
|
||||
"headingFont": ["Heading Font", "by"],
|
||||
"copyFont": ["Copy Font", "by"],
|
||||
"background": ["Background", ["Layered Waves aus", "von"]]
|
||||
}
|
||||
}
|
||||
}
|
28
src/main.ts
|
@ -1,12 +1,24 @@
|
|||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import messages from './lang'
|
||||
|
||||
import "normalize.css";
|
||||
import "@/scss/main.scss";
|
||||
import 'normalize.css'
|
||||
import '@/scss/main.scss'
|
||||
|
||||
const app = createApp(App);
|
||||
type MessageSchema = typeof messages.en
|
||||
|
||||
app.use(router);
|
||||
const i18n = createI18n<[MessageSchema], 'en' | 'de'>({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
fallbackLocale: 'en',
|
||||
messages
|
||||
})
|
||||
|
||||
app.mount("body");
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
app.use(i18n)
|
||||
|
||||
app.mount('body')
|
||||
|
|
|
@ -1,34 +1,68 @@
|
|||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import HomeView from "../views/HomeView.vue";
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '@/views/HomeView.vue'
|
||||
|
||||
import HomeIcon from '@/assets/icons/HomeIcon.vue'
|
||||
import IdCardIcon from '@/assets/icons/IdCardIcon.vue'
|
||||
import PaletteIcon from '@/assets/icons/PaletteIcon.vue'
|
||||
import BriefcaseIcon from '@/assets/icons/BriefcaseIcon.vue'
|
||||
import CircleInfoIcon from '@/assets/icons/CircleInfoIcon.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
scrollBehavior: () => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({ top: 0 })
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
routes: [
|
||||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView,
|
||||
meta: {
|
||||
title: "Home",
|
||||
},
|
||||
title: 'nav.home',
|
||||
icon: HomeIcon
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/anatomy",
|
||||
name: "anatomy",
|
||||
component: () => import("@/views/AnatomyView.vue"),
|
||||
path: '/general',
|
||||
name: 'general',
|
||||
component: () => import('@/views/GeneralView.vue'),
|
||||
meta: {
|
||||
title: "Anatomy",
|
||||
},
|
||||
title: 'nav.general',
|
||||
icon: IdCardIcon
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/career-path",
|
||||
name: "career-path",
|
||||
component: () => import("@/views/CareerPathView.vue"),
|
||||
path: '/anatomy',
|
||||
name: 'anatomy',
|
||||
component: () => import('@/views/AnatomyView.vue'),
|
||||
meta: {
|
||||
title: "Career Path",
|
||||
},
|
||||
title: 'nav.anatomy',
|
||||
icon: PaletteIcon
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
{
|
||||
path: '/career-path',
|
||||
name: 'career-path',
|
||||
component: () => import('@/views/CareerPathView.vue'),
|
||||
meta: {
|
||||
title: 'nav.careerPath',
|
||||
icon: BriefcaseIcon
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/attributions',
|
||||
name: 'attributions',
|
||||
component: () => import('@/views/AttributionsView.vue'),
|
||||
meta: {
|
||||
title: 'nav.attributions',
|
||||
icon: CircleInfoIcon
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default router;
|
||||
export default router
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import 'fontfaces';
|
||||
|
||||
/* theme colors */
|
||||
:root {
|
||||
--theme-c-desert-sand: #e7c7b1;
|
||||
|
@ -31,62 +33,105 @@
|
|||
|
||||
/* general purpose variables */
|
||||
:root {
|
||||
--font-family-copy: sans-serif;
|
||||
--font-family-headings: serif;
|
||||
--font-family-copy: 'Arvo', sans-serif;
|
||||
--font-family-headings: 'Secular One', serif;
|
||||
|
||||
--font-size: 18px;
|
||||
--text-line-height: 1.5em;
|
||||
--text-line-height: 1.5;
|
||||
--link-inset-box-shadow: 1.5rem;
|
||||
|
||||
--margin-paragraph: 1rem;
|
||||
--page-background-image: url(@/assets/layered-waves-light.svg);
|
||||
--page-background-image-height: 100vw;
|
||||
--page-background-image-max-height: 50vh;
|
||||
--page-transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
||||
--page-transform: translateY(5em);
|
||||
|
||||
--container-width-text: 40rem;
|
||||
--container-width-images: 40rem;
|
||||
--container-width-tables: 40rem;
|
||||
--container-width-timeline: calc(var(--timeline-circle-size) * 15);
|
||||
--paragraph-margin: 1rem;
|
||||
|
||||
--textblock-max-width: 34rem;
|
||||
--refimage-max-width: 50rem;
|
||||
|
||||
--container-spacing-top-safe: max(1rem, env(safe-area-inset-top));
|
||||
--container-spacing-right-safe: max(1rem, env(safe-area-inset-right));
|
||||
--container-spacing-bottom-safe: max(1rem, env(safe-area-inset-bottom));
|
||||
--container-spacing-left-safe: max(1rem, env(safe-area-inset-left));
|
||||
|
||||
--content-spacing: 0 var(--container-spacing-right-safe) 0
|
||||
--textblock-padding: 0 var(--container-spacing-right-safe) 0 var(--container-spacing-left-safe);
|
||||
|
||||
--welcome-padding: 2rem var(--container-spacing-right-safe) 2rem
|
||||
var(--container-spacing-left-safe);
|
||||
--welcome-headings-text-align: center;
|
||||
|
||||
--navigation-item-font-size: 1.75rem;
|
||||
--navigation-item-line-height: 3.25rem;
|
||||
--navigation-width: 100vw;
|
||||
--modal-width: 100%;
|
||||
--modal-border: 0.25rem solid var(--color-modal-border);
|
||||
|
||||
--timeline-circle-size: 4rem;
|
||||
--navigation-flow: row nowrap;
|
||||
--navigation-justify: space-evenly;
|
||||
--navigation-align: center;
|
||||
--navigation-position: auto 0 0 0;
|
||||
|
||||
--navigation-size: 4rem;
|
||||
--navigation-width: 100%;
|
||||
--navigation-width-expanded: auto;
|
||||
--navigation-height: auto;
|
||||
--navigation-padding: 0 0 0 env(safe-area-inset-left);
|
||||
|
||||
--navigation-cutout: 0 0 calc(var(--navigation-size) + env(safe-area-inset-bottom)) 0;
|
||||
--navigation-cutout-page-background: calc(var(--navigation-size) + env(safe-area-inset-bottom));
|
||||
--navigation-cutout-main: 0;
|
||||
|
||||
--navigation-link-display: none;
|
||||
--navigation-link-flex: 1 0 var(--navigation-size);
|
||||
--navigation-link-justify: center;
|
||||
--navigation-link-height: calc(var(--navigation-size) + env(safe-area-inset-bottom));
|
||||
--navigation-link-padding: 0 0 env(safe-area-inset-bottom) 0;
|
||||
--navigation-link-icon-size: calc(var(--navigation-size) / 2);
|
||||
--navigation-link-icon-spacing: calc(var(--navigation-size) * 0.25);
|
||||
--navigation-link-text-font-size: 1.5rem;
|
||||
--navigation-link-box-shadow: inset 0 calc(var(--navigation-size) * -1) 0 0
|
||||
var(--color-router-link);
|
||||
--navigation-link-last-child-margin: 0;
|
||||
|
||||
--timeline-max-width: calc(var(--timeline-circle-size) * 10);
|
||||
--timeline-circle-size: 3rem;
|
||||
--timeline-circle-font-size: calc(var(--timeline-circle-size) * 0.2);
|
||||
--timeline-circle-background-color: rgba(107, 185, 219, 0.5);
|
||||
--timeline-circle-padding: calc(var(--timeline-circle-font-size) * 0.5);
|
||||
|
||||
--timeline-position-top: var(--timeline-circle-size);
|
||||
--timeline-circle-background-color: var(--theme-c-woody-brown);
|
||||
--timeline-circle-padding: calc(var(--timeline-circle-font-size));
|
||||
|
||||
--timeline-stroke-thickness: calc(var(--timeline-circle-size) / 16);
|
||||
--timeline-stroke-color: var(--theme-c-crystal-blue);
|
||||
--timeline-stroke-border: var(--timeline-stroke-thickness) solid
|
||||
var(--timeline-stroke-color);
|
||||
--timeline-stroke-length: calc(100% - var(--timeline-circle-size) + 1.5rem);
|
||||
--timeline-stroke-position: calc(
|
||||
--timeline-stroke-position-top: var(--timeline-circle-size);
|
||||
--timeline-stroke-position-horizontal: calc(
|
||||
var(--timeline-circle-size) / 2 - var(--timeline-stroke-thickness) / 2
|
||||
);
|
||||
|
||||
--timeline-item-margin: 1.5rem 0;
|
||||
--timeline-item-margin-odd: 0 0 0 calc(50% - var(--timeline-circle-size) / 2);
|
||||
--timeline-item-margin-even: 0 calc(50% - var(--timeline-circle-size) / 2) 0 0;
|
||||
--timeline-stroke-position-odd: var(--timeline-stroke-position-top) auto auto
|
||||
var(--timeline-stroke-position-horizontal);
|
||||
--timeline-stroke-position-even: var(--timeline-stroke-position-odd);
|
||||
|
||||
--color-table-border-radius: 1rem;
|
||||
--color-table-color-cell-width: 10vw;
|
||||
--color-table-spacing: 0 var(--container-spacing-right-safe) 0
|
||||
var(--container-spacing-left-safe);
|
||||
--timeline-item-margin: 1.5rem 0;
|
||||
--timeline-item-margin-odd: var(--timeline-item-margin);
|
||||
--timeline-item-margin-even: var(--timeline-item-margin);
|
||||
--timeline-item-text-align-even: left;
|
||||
--timeline-item-content-padding-odd: 0 0 0 var(--container-spacing-left-safe);
|
||||
--timeline-item-content-padding-even: var(--timeline-item-content-padding-odd);
|
||||
|
||||
--table-border-radius: 1rem;
|
||||
--table-outer-spacing: 0 var(--container-spacing-right-safe) 0 var(--container-spacing-left-safe);
|
||||
--table-cell-padding: 0.25rem 0.5rem;
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--theme-c-antique-white);
|
||||
--color-background-body: var(--theme-c-desert-sand);
|
||||
|
||||
--color-border: var(--theme-c-crystal-blue);
|
||||
--color-modal-background: var(--theme-c-desert-sand);
|
||||
--color-modal-border: var(--theme-c-walnut-brown);
|
||||
|
||||
--color-button: var(--theme-c-walnut-brown);
|
||||
--color-button-box-shadow: var(--theme-c-deep-oak);
|
||||
--color-button-text: var(--theme-c-text-dark);
|
||||
|
||||
--color-heading: var(--theme-c-text-light);
|
||||
--color-text: var(--theme-c-text-light);
|
||||
|
@ -94,8 +139,7 @@
|
|||
--color-link-text-hover: var(--theme-c-text-dark);
|
||||
--color-link-text-underline: var(--theme-c-text-light);
|
||||
|
||||
--color-header-bar: var(--theme-c-deep-oak-translucent);
|
||||
--color-header-bar-title: var(--theme-c-white);
|
||||
--color-footer-background: var(--theme-c-desert-sand);
|
||||
|
||||
--color-navigation-toggle: var(--theme-c-antique-white);
|
||||
--color-navigation-background: var(--theme-c-walnut-brown);
|
||||
|
@ -103,19 +147,35 @@
|
|||
--color-router-link-hover: var(--theme-c-walnut-brown);
|
||||
--color-router-link-active: var(--theme-c-crystal-blue);
|
||||
|
||||
--color-table-row-hover: var(--theme-c-walnut-brown);
|
||||
--color-table-heading-background: var(--theme-c-dark-grey-blue);
|
||||
--color-table-heading-text-color: var(--theme-c-text-dark);
|
||||
--color-table-cell-background: var(--theme-c-desert-sand);
|
||||
--color-table-cell-text-color: var(--theme-c-text-light);
|
||||
--color-table-cell-text-color-hover: var(--theme-c-text-dark);
|
||||
--table-row-background-hover: var(--theme-c-walnut-brown);
|
||||
--table-heading-background: var(--theme-c-dark-grey-blue);
|
||||
--table-heading-text-color: var(--theme-c-text-dark);
|
||||
--table-cell-background: var(--theme-c-desert-sand);
|
||||
--table-cell-text-color: var(--theme-c-text-light);
|
||||
--table-cell-text-color-hover: var(--theme-c-text-dark);
|
||||
|
||||
--color-artist-link-background: var(--theme-c-text-light);
|
||||
--color-artist-link-background-hover: var(--theme-c-text-dark);
|
||||
--color-artist-link-icon: var(--theme-c-text-dark);
|
||||
--color-artist-link-icon-hover: var(--theme-c-text-light);
|
||||
|
||||
--timeline-stroke-color: var(--theme-c-dark-grey-blue);
|
||||
--timeline-circle-background: var(--theme-c-dark-grey-blue-translucent);
|
||||
--timeline-icon-color: var(--theme-c-antique-white);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--page-background-image: url(@/assets/layered-waves-dark.svg);
|
||||
--color-background: var(--theme-c-dark-grey-blue);
|
||||
--color-background-body: var(--theme-c-deep-oak);
|
||||
|
||||
--color-border: var(--theme-c-desert-sand);
|
||||
--color-modal-background: var(--theme-c-deep-oak);
|
||||
--color-modal-border: var(--theme-c-antique-white);
|
||||
|
||||
--color-button: var(--theme-c-antique-white);
|
||||
--color-button-box-shadow: var(--theme-c-desert-sand);
|
||||
--color-button-text: var(--theme-c-text-light);
|
||||
|
||||
--color-heading: var(--theme-c-text-dark);
|
||||
--color-text: var(--theme-c-text-dark);
|
||||
|
@ -123,34 +183,115 @@
|
|||
--color-link-text-hover: var(--theme-c-text-light);
|
||||
--color-link-text-underline: var(--theme-c-text-dark);
|
||||
|
||||
--color-table-row-hover: var(--theme-c-walnut-brown);
|
||||
--color-table-heading-background: var(--theme-c-deep-oak);
|
||||
--color-table-heading-text-color: var(--theme-c-text-dark);
|
||||
--color-table-cell-background: var(--theme-c-woody-brown);
|
||||
--color-table-cell-text-color: var(--theme-c-text-dark);
|
||||
--color-table-cell-text-color-hover: var(--theme-c-text-dark);
|
||||
--color-footer-background: var(--theme-c-deep-oak);
|
||||
|
||||
--table-row-background-hover: var(--theme-c-walnut-brown);
|
||||
--table-heading-background: var(--theme-c-deep-oak);
|
||||
--table-heading-text-color: var(--theme-c-text-dark);
|
||||
--table-cell-background: var(--theme-c-woody-brown);
|
||||
--table-cell-text-color: var(--theme-c-text-dark);
|
||||
--table-cell-text-color-hover: var(--theme-c-text-dark);
|
||||
|
||||
--color-artist-link-background: var(--theme-c-text-dark);
|
||||
--color-artist-link-background-hover: var(--theme-c-text-dark);
|
||||
--color-artist-link-icon: var(--theme-c-text-light);
|
||||
--color-artist-link-icon-hover: var(--theme-c-text-light);
|
||||
|
||||
--timeline-stroke-color: var(--theme-c-crystal-blue);
|
||||
--timeline-circle-background: var(--theme-c-crystal-blue-translucent);
|
||||
--timeline-icon-color: var(--theme-c-antique-white);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 45em) {
|
||||
@media (min-width: 35em) {
|
||||
:root {
|
||||
--table-cell-padding: 0.5rem 1rem;
|
||||
--font-size: 20px;
|
||||
--navigation-width: 20rem;
|
||||
--timeline-circle-size: 4rem;
|
||||
--modal-width: 30rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
:root {
|
||||
--page-background-image-height: 20vw;
|
||||
--page-background-image-max-height: 100vh;
|
||||
|
||||
--color-table-color-cell-width: 10rem;
|
||||
--content-spacing: auto;
|
||||
--color-table-spacing: 0;
|
||||
--textblock-padding: 0 var(--container-spacing-right-safe) 0 var(--container-spacing-left-safe);
|
||||
|
||||
--navigation-cutout: 0 0 0 calc(var(--navigation-size) + env(safe-area-inset-left));
|
||||
--navigation-cutout-page-background: 0;
|
||||
--navigation-cutout-main: var(--navigation-cutout);
|
||||
|
||||
--navigation-flow: column nowrap;
|
||||
--navigation-justify: flex-start;
|
||||
--navigation-align: stretch;
|
||||
--navigation-position: 0 auto 0 0;
|
||||
|
||||
--navigation-width: calc(var(--navigation-size) + env(safe-area-inset-left));
|
||||
--navigation-width-expanded: var(--navigation-width);
|
||||
|
||||
--navigation-link-display: block;
|
||||
--navigation-link-flex: 0 0 --navigation-size;
|
||||
--navigation-link-justify: flex-start;
|
||||
--navigation-link-height: var(--navigation-size);
|
||||
--navigation-link-padding: 0 0 0 env(safe-area-inset-left);
|
||||
--navigation-link-box-shadow: inset var(--navigation-width-expanded) 0 0 0
|
||||
var(--color-router-link);
|
||||
--navigation-link-last-child-margin: auto 0 0 0;
|
||||
|
||||
--table-cell-padding: 0.5rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 55em) {
|
||||
:root {
|
||||
--welcome-padding: 2rem var(--container-spacing-right-safe) 2rem
|
||||
var(--container-spacing-left-safe);
|
||||
--welcome-headings-align-items: center;
|
||||
--welcome-headings-text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 64em) {
|
||||
:root {
|
||||
--font-size: 24px;
|
||||
--timeline-max-width: calc(var(--timeline-circle-size) * 15);
|
||||
--timeline-stroke-length: calc(100% - var(--timeline-circle-size));
|
||||
--timeline-stroke-position-even: var(--timeline-stroke-position-top)
|
||||
var(--timeline-stroke-position-horizontal) auto auto;
|
||||
--timeline-item-margin-odd: 0 0 0 calc(50% - var(--timeline-circle-size) / 2);
|
||||
--timeline-item-margin-even: 0 calc(50% - var(--timeline-circle-size) / 2) 0 0;
|
||||
--timeline-item-flex-order: 1;
|
||||
--timeline-item-content-margin-odd: 0 0 0 1rem;
|
||||
--timeline-item-content-margin-even: 0 1rem 0 0;
|
||||
--timeline-item-text-align-even: right;
|
||||
--timeline-item-content-padding-odd: var(--textblock-padding);
|
||||
--timeline-item-content-padding-even: var(--textblock-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 125em) {
|
||||
@media (min-width: 80em) {
|
||||
:root {
|
||||
--font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 120em) {
|
||||
:root {
|
||||
--font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (hover: hover) and (min-width: 50em) {
|
||||
:root {
|
||||
--navigation-width-expanded: calc(var(--navigation-size) * 3.75 + env(safe-area-inset-left));
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
:root {
|
||||
--page-transition: opacity 0.5s ease;
|
||||
--page-transform: none;
|
||||
}
|
||||
}
|
||||
|
|
2
src/scss/fontfaces.scss
Normal file
|
@ -0,0 +1,2 @@
|
|||
@import '@/assets/fonts/arvo/arvo';
|
||||
@import '@/assets/fonts/secular-one/secular-one';
|
|
@ -1,4 +1,4 @@
|
|||
@import "@/scss/base";
|
||||
@import '@/scss/base';
|
||||
|
||||
:root {
|
||||
font-family: var(--font-family-copy);
|
||||
|
@ -18,8 +18,10 @@
|
|||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
background: var(--color-background-body);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
line-height: var(--text-line-height);
|
||||
|
||||
text-rendering: optimizeLegibility;
|
||||
|
@ -31,6 +33,38 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
main {
|
||||
background: var(--color-background);
|
||||
margin: var(--navigation-cutout-main);
|
||||
padding: 0.0625rem 0 0 0;
|
||||
transition: 0.4s;
|
||||
z-index: 0;
|
||||
|
||||
&:after {
|
||||
display: block;
|
||||
|
||||
content: '';
|
||||
position: sticky;
|
||||
inset: auto 0 var(--navigation-cutout-page-background) 0;
|
||||
|
||||
height: var(--page-background-image-height);
|
||||
max-height: var(--page-background-image-max-height);
|
||||
|
||||
background: var(--page-background-image);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center bottom;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
max-width: var(--textblock-max-width);
|
||||
margin: 0 auto;
|
||||
padding: var(--textblock-padding);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
|
@ -43,8 +77,14 @@ h6 {
|
|||
font-optical-sizing: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: var(--margin-paragraph) 0;
|
||||
text-align: justify;
|
||||
margin: var(--paragraph-margin) 0;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -52,10 +92,93 @@ a {
|
|||
color: var(--color-link-text);
|
||||
transition: 0.4s;
|
||||
|
||||
box-shadow: inset 0 calc(var(--text-line-height) * -0.125) 0 0 var(--color-link-text-underline);
|
||||
box-shadow: inset 0 calc(var(--link-inset-box-shadow) * -0.125) 0 0
|
||||
var(--color-link-text-underline);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-link-text-hover);
|
||||
box-shadow: inset 0 calc(var(--text-line-height) * -1) 0 0 var(--color-link-text-underline);
|
||||
box-shadow: inset 0 calc(var(--link-inset-box-shadow) * -1) 0 0 var(--color-link-text-underline);
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
max-width: 34rem;
|
||||
margin: 2rem auto;
|
||||
padding: var(--table-outer-spacing);
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: var(--table-cell-padding);
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: bold;
|
||||
background-color: var(--table-heading-background);
|
||||
color: var(--table-heading-text-color);
|
||||
|
||||
&:first-child {
|
||||
border-radius: var(--table-border-radius) 0 0 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 var(--table-border-radius) 0 0;
|
||||
}
|
||||
|
||||
&.name {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: var(--table-cell-background);
|
||||
color: var(--table-cell-text-color);
|
||||
|
||||
svg {
|
||||
fill: var(--table-cell-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
tr:hover td {
|
||||
background-color: var(--table-row-background-hover);
|
||||
color: var(--table-cell-text-color-hover);
|
||||
|
||||
a {
|
||||
color: var(--theme-c-text-dark);
|
||||
box-shadow: inset 0 calc(var(--link-inset-box-shadow) * -0.125) 0 0
|
||||
var(--table-cell-text-color-hover);
|
||||
|
||||
&:hover {
|
||||
color: var(--theme-c-text-light);
|
||||
box-shadow: inset 0 calc(var(--link-inset-box-shadow) * -1) 0 0
|
||||
var(--table-cell-text-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: var(--table-cell-text-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
tr:last-child td {
|
||||
&:first-child {
|
||||
border-radius: 0 0 0 var(--table-border-radius);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 0 var(--table-border-radius) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: var(--page-transition);
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: var(--page-transform);
|
||||
}
|
||||
|
|
|
@ -1,80 +1,165 @@
|
|||
<script setup lang="ts">
|
||||
import RefImage from "@/components/RefImage.vue";
|
||||
import ColorTable from "@/components/ColorTable.vue";
|
||||
import TextBlock from "@/components/TextBlock.vue";
|
||||
import RefImage from '@/components/RefImage.vue'
|
||||
import ColorTable from '@/components/ColorTable.vue'
|
||||
|
||||
const colors = [
|
||||
{ name: "Front", value: "#e7c7b1" },
|
||||
{ name: "Arms, legs", value: "#493428" },
|
||||
{ name: "Back Main", value: "#422322" },
|
||||
{ name: "Back Spine", value: "#341c1c" },
|
||||
{ name: "Highlight scales, tissue", value: "#6bb9db" },
|
||||
{ name: "Spikes, tail club", value: "#f8ebdd" },
|
||||
{ name: "Eyes primary", value: "#a7eef1" },
|
||||
{ name: "Eyes secondary", value: "#6dabd1" },
|
||||
];
|
||||
{ name: 'data.colors.front', value: '#e7c7b1' },
|
||||
{ name: 'data.colors.limbs', value: '#493428' },
|
||||
{ name: 'data.colors.back', value: '#422322' },
|
||||
{ name: 'data.colors.spine', value: '#341c1c' },
|
||||
{ name: 'data.colors.tissue', value: '#6bb9db' },
|
||||
{ name: 'data.colors.spikes', value: '#f8ebdd' },
|
||||
{ name: 'data.colors.eyesPrimary', value: '#a7eef1' },
|
||||
{ name: 'data.colors.eyesSecondary', value: '#6dabd1' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RefImage>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-SFW-alpha.png?w=400;700;1000&avif&quality=75&srcset
|
||||
"
|
||||
type="image/avif"
|
||||
/>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-SFW-alpha.png?w=400;700;1000&webp&quality=100&srcset
|
||||
"
|
||||
type="image/webp"
|
||||
/>
|
||||
<img src="@/assets/viktor-ref-SFW-alpha.png?w=700&png" alt="" />
|
||||
<article>
|
||||
<section>
|
||||
<h1>{{ $t(`${$route.meta.title}`) }}</h1>
|
||||
</section>
|
||||
|
||||
<template #caption>
|
||||
Viktor Ref © <a href="http://twitter.com/sabertoofs">sabertoofs</a>
|
||||
</template>
|
||||
</RefImage>
|
||||
<RefImage dropshadow>
|
||||
<template v-if="$route.query.nsfw">
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-NSFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=avif&quality=75&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
type="image/avif"
|
||||
/>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-NSFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=webp&quality=100&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
type="image/webp"
|
||||
/>
|
||||
<img
|
||||
srcset="
|
||||
@/assets/viktor-ref-NSFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=png&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
alt="Viktor Ref by sabertoofs"
|
||||
loading="lazy"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<ColorTable :colors="colors"></ColorTable>
|
||||
<template v-else>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-SFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=avif&quality=75&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
type="image/avif"
|
||||
/>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-ref-SFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=webp&quality=100&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
type="image/webp"
|
||||
/>
|
||||
<img
|
||||
srcset="
|
||||
@/assets/viktor-ref-SFW-alpha.png?w=375;420;500;750;840;1000;1125;1260;1500&format=png&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 500px, (min-width: 50em) 420px, 375px"
|
||||
:alt="`${$t('anatomy.images.back.caption')} by sabertoofs`"
|
||||
loading="lazy"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<TextBlock>
|
||||
<p>
|
||||
Viktor is a bipedal plantigrade Ankylosaurus. His skin is mostly
|
||||
bicolored, with several shades of brown.
|
||||
</p>
|
||||
<template #caption>
|
||||
{{ $t('anatomy.images.back.caption') }} ©
|
||||
<a href="http://twitter.com/sabertoofs">sabertoofs</a>
|
||||
</template>
|
||||
</RefImage>
|
||||
|
||||
<p>
|
||||
His forehead, nose, chest, belly and crotch are of light desert sand
|
||||
colors that run through the underside of his tail.
|
||||
</p>
|
||||
<ColorTable :colors="colors"></ColorTable>
|
||||
|
||||
<p>
|
||||
His cheeks, shoulders, back and thighs, in contrast, stand out with a rich
|
||||
walnut brown, which is also found on the sides of his tail. From the back
|
||||
of his head, down his spine and across the top of his tail is a continuous
|
||||
strip of deep dark cedar brown. Arms and legs are distinguished by a light
|
||||
earthy brown.
|
||||
</p>
|
||||
<section>
|
||||
<p v-for="(p, i) in $tm('anatomy.paragraphs[0]')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
|
||||
<p>
|
||||
His entire body is speckled with scattered aquamarine spots, which come in
|
||||
pairs of one large and one small spot. The only exceptions are the spots
|
||||
on his cheeks and behind his lower cheek horns, which come in threes and
|
||||
his the top side of his snout, which sports a big single spot. Mouth,
|
||||
tongue, nostrils and any other tissue of his body also feature this color.
|
||||
</p>
|
||||
<RefImage dropshadow>
|
||||
<template v-if="$route.query.nsfw">
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-front-NSFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=avif&quality=75&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
type="image/avif"
|
||||
/>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-front-NSFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=webp&quality=100&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
type="image/webp"
|
||||
/>
|
||||
<img
|
||||
srcset="
|
||||
@/assets/viktor-front-NSFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=png&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
alt="Viktor frontal shot by sabertoofs"
|
||||
loading="lazy"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<p>His eyes shine with a mixture of light sea green and electric blue.</p>
|
||||
<template v-else>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-front-SFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=avif&quality=75&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
type="image/avif"
|
||||
/>
|
||||
<source
|
||||
srcset="
|
||||
@/assets/viktor-front-SFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=webp&quality=100&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
type="image/webp"
|
||||
/>
|
||||
<img
|
||||
srcset="
|
||||
@/assets/viktor-front-SFW-alpha.png?w=430;530;590;710;860;1060;1180;1420;1290;1590;1770;2130&format=png&withoutEnlargement&as=srcset
|
||||
"
|
||||
sizes="(min-width: 64em) 710px,
|
||||
(min-width: 50em) 590px,
|
||||
(min-width: 27em) 530px,
|
||||
430px"
|
||||
:alt="`${$t('anatomy.images.front.caption')} by sabertoofs`"
|
||||
loading="lazy"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<p>
|
||||
Horns and claws are of a typical bone white. Starting with the double pair
|
||||
of horns on his head, a parallel line of horns continues down his back,
|
||||
with additional horns adorning his shoulders and thighs. His tail is also
|
||||
armed with horns on both sides along its entire length. At the tip of the
|
||||
tail is a club-like ossification that he can use for fending off foes.
|
||||
</p>
|
||||
<template #caption>
|
||||
{{ $t('anatomy.images.front.caption') }} ©
|
||||
<a href="http://twitter.com/sabertoofs">sabertoofs</a>
|
||||
</template>
|
||||
</RefImage>
|
||||
|
||||
<p>He owes his strong, stocky physique to years of hard physical labor.</p>
|
||||
</TextBlock>
|
||||
<section>
|
||||
<p v-for="(p, i) in $tm('anatomy.paragraphs[1]')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
</article>
|
||||
</template>
|
||||
|
|
103
src/views/AttributionsView.vue
Normal file
|
@ -0,0 +1,103 @@
|
|||
<script setup lang="ts">
|
||||
import AttributionTable from '@/components/AttributionTable.vue'
|
||||
|
||||
import ViktorRefAlpha from '@/assets/viktor-ref-SFW-alpha.png?w=400&format=webp&quality=100&imagetools'
|
||||
import ViktorFront from '@/assets/viktor-front-SFW-alpha.png?w=400&format=webp&quality=100&imagetools'
|
||||
|
||||
const attributions = [
|
||||
{
|
||||
artwork: ViktorRefAlpha,
|
||||
artist: 'sabertoofs',
|
||||
links: {
|
||||
furaffinity: 'https://www.furaffinity.net/user/sabertoofs',
|
||||
twitter: 'https://twitter.com/sabertoofs'
|
||||
}
|
||||
},
|
||||
{
|
||||
artwork: ViktorFront,
|
||||
artist: 'sabertoofs',
|
||||
links: {
|
||||
furaffinity: 'https://www.furaffinity.net/user/sabertoofs',
|
||||
twitter: 'https://twitter.com/sabertoofs'
|
||||
}
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article>
|
||||
<section>
|
||||
<h1>{{ $t(`${$route.meta.title}`) }}</h1>
|
||||
<h2>{{ $t('attributions.artwork.heading') }}</h2>
|
||||
</section>
|
||||
<AttributionTable :attributions="attributions" />
|
||||
<section>
|
||||
<h2>{{ $t('attributions.other.heading') }}</h2>
|
||||
</section>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ $t('attributions.other.headings[0]') }}</th>
|
||||
<th>{{ $t('attributions.other.headings[1]') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $t('attributions.other.icons[0]') }}</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://fontawesome.com/license/free"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Font Awesome
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('attributions.other.headingFont[0]') }}</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://github.com/MichalSahar/Secular"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Secular One
|
||||
</a>
|
||||
{{ $t('attributions.other.headingFont[1]') }}
|
||||
<a href="https://github.com/MichalSahar" target="_blank" rel="noopener noreferrer">
|
||||
Michal Sahar
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('attributions.other.copyFont[0]') }}</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://antonkoovit.com/typefaces/arvo"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Arvo
|
||||
</a>
|
||||
{{ $t('attributions.other.copyFont[1]') }}
|
||||
<a href="https://antonkoovit.com/" target="_blank" rel="noopener noreferrer">
|
||||
Anton Koovit
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('attributions.other.background[0]') }}</td>
|
||||
<td>
|
||||
{{ $t('attributions.other.background[1][0]') }}
|
||||
<a href="https://haikei.app/" target="_blank" rel="noopener noreferrer">Haikei</a>
|
||||
{{ $t('attributions.other.background[1][1]') }}
|
||||
<a href="https://zcreativelabs.com/" target="_blank" rel="noopener noreferrer">
|
||||
z creative labs
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</article>
|
||||
</template>
|
|
@ -1,61 +1,47 @@
|
|||
<script setup lang="ts">
|
||||
import TimelineList from "@/components/TimelineList.vue";
|
||||
import TimelineItem from "@/components/TimelineItem.vue";
|
||||
import TimelineList from '@/components/TimelineList.vue'
|
||||
import TimelineItem from '@/components/TimelineItem.vue'
|
||||
import WhiskeyGlassIcon from '@/assets/icons/WhiskeyGlassIcon.vue'
|
||||
import TreeIcon from '@/assets/icons/TreeIcon.vue'
|
||||
import CarIcon from '@/assets/icons/CarIcon.vue'
|
||||
import HelmetSafetyIcon from '@/assets/icons/HelmetSafetyIcon.vue'
|
||||
import IndustryIcon from '@/assets/icons/IndustryIcon.vue'
|
||||
import TruckIcon from '@/assets/icons/TruckIcon.vue'
|
||||
import BoxesIcon from '@/assets/icons/BoxesIcon.vue'
|
||||
|
||||
interface Job {
|
||||
title: string
|
||||
desc: string
|
||||
}
|
||||
|
||||
const jobIcons = [
|
||||
WhiskeyGlassIcon,
|
||||
TreeIcon,
|
||||
CarIcon,
|
||||
HelmetSafetyIcon,
|
||||
IndustryIcon,
|
||||
TruckIcon,
|
||||
BoxesIcon
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TimelineList>
|
||||
<TimelineItem datetime="2011-11-11">
|
||||
<template #headline>Bartender</template>
|
||||
<template #content>
|
||||
<p>
|
||||
Viktor's professional career began as a bartender at a pub in his
|
||||
hometown. There he often doubled as a bouncer when a few guests got
|
||||
too drunk and started making a fuss. A defining moment of that job was
|
||||
when someone climbed over the counter and threatened him with a broken
|
||||
bottle. Wrestled to the ground and with a broken bottle in front of
|
||||
his face, he had to make a split-second decision. With a powerful
|
||||
swing of his tail bone, he knocked the attacker down. This experience
|
||||
taught him the importance of effectively defending himself against
|
||||
unpleasant fellows and to eliminate threats before they get close to
|
||||
him ever again.
|
||||
</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
<TimelineItem datetime="2012-12-12">
|
||||
<template #headline>Lumberjack</template>
|
||||
<template #content>
|
||||
<p>
|
||||
After that he earned his living as a lumberjack in a remote sawmill.
|
||||
For a while he enjoyed the peace and quiet of country life, but soon
|
||||
he was drawn back into more urban surroundings.
|
||||
</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
<TimelineItem datetime="2012-12-12">
|
||||
<template #headline>Car Mechanic</template>
|
||||
<template #content>
|
||||
<p>
|
||||
For a while, he made ends meet at an auto repair shop in a suburb, but
|
||||
it was shut down after suffering persistent financial problems.
|
||||
</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
<TimelineItem datetime="2012-12-12">
|
||||
<template #headline>Construction Worker</template>
|
||||
<template #content>
|
||||
<p>Later, he worked as a construction worker.</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
<TimelineItem datetime="2012-12-12">
|
||||
<template #headline>Werehouse Worker</template>
|
||||
<template #content>
|
||||
<p>
|
||||
he eventually moved to a port town and started working as a warehouse
|
||||
worker at the local post, where he mainly loads goods and ensures that
|
||||
they are properly stored.
|
||||
</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
</TimelineList>
|
||||
<article>
|
||||
<section>
|
||||
<h1>{{ $t(`${$route.meta.title}`) }}</h1>
|
||||
<p v-for="(p, i) in $tm('career.paragraphs')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
|
||||
<TimelineList>
|
||||
<TimelineItem v-for="(job, idx) in ($tm('career.jobs') as Job[])" :key="idx">
|
||||
<template #icon>
|
||||
<component :is="jobIcons[idx as number]"></component>
|
||||
</template>
|
||||
<template #headline>{{ job.title }}</template>
|
||||
<template #content>
|
||||
<p>{{ job.desc }}</p>
|
||||
</template>
|
||||
</TimelineItem>
|
||||
</TimelineList>
|
||||
</article>
|
||||
</template>
|
||||
|
|
73
src/views/GeneralView.vue
Normal file
|
@ -0,0 +1,73 @@
|
|||
<script setup lang="ts">
|
||||
import DataTable from '@/components/DataTable.vue'
|
||||
|
||||
const dob = new Date('1987-12-08')
|
||||
const locale = 'en-US'
|
||||
const dateFormat = new Intl.DateTimeFormat(locale, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit'
|
||||
})
|
||||
|
||||
const height = 227
|
||||
const weight = 175
|
||||
|
||||
const toImperial = (cm: number): string => {
|
||||
const realFeet = (cm * 0.3937) / 12
|
||||
const feet = Math.floor(realFeet)
|
||||
const inches = Math.round((realFeet - feet) * 12)
|
||||
|
||||
return `${feet}'${inches}"`
|
||||
}
|
||||
|
||||
const toInch = (cm: number): string => {
|
||||
return `${Math.round(cm / 2.45)} in`
|
||||
}
|
||||
|
||||
const toLbs = (kg: number): number => {
|
||||
const nearExact = kg / 0.45359237
|
||||
const lbs = Math.floor(nearExact)
|
||||
|
||||
return lbs
|
||||
}
|
||||
|
||||
const heads = ['data.general.heading[0]', 'data.general.heading[1]']
|
||||
const data = [
|
||||
['data.general.fullName[0]', 'data.general.fullName[1]'],
|
||||
['data.general.dob[0]', dateFormat.format(dob)],
|
||||
['data.general.gender[0]', 'data.general.gender[1]'],
|
||||
['data.general.height[0]', `${height} cm (${toImperial(height)})`],
|
||||
['data.general.weight[0]', `${weight} kg (${toLbs(weight)} lbs)`]
|
||||
]
|
||||
|
||||
const sexHeads = ['data.sexuality.heading[0]', 'data.sexuality.heading[1]']
|
||||
const sexData = [
|
||||
['data.sexuality.identifiesAs[0]', 'data.sexuality.identifiesAs[1]'],
|
||||
['data.sexuality.preferredRole[0]', 'data.sexuality.preferredRole[1]']
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article>
|
||||
<section>
|
||||
<h1>{{ $t(`${$route.meta.title}`) }}</h1>
|
||||
</section>
|
||||
|
||||
<DataTable :headings="heads" :data="data"></DataTable>
|
||||
|
||||
<section>
|
||||
<h2>{{ $t('general.personality.heading') }}</h2>
|
||||
<p v-for="(p, i) in $tm('general.personality.paragraphs')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>{{ $t('general.sexuality.heading') }}</h2>
|
||||
</section>
|
||||
|
||||
<DataTable :headings="sexHeads" :data="sexData"></DataTable>
|
||||
|
||||
<section>
|
||||
<p v-for="(p, i) in $tm('general.sexuality.paragraphs')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
</article>
|
||||
</template>
|
|
@ -1,13 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import TextBlock from "@/components/TextBlock.vue";</script>
|
||||
import WelcomeHeader from '@/components/WelcomeHeader.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TextBlock>
|
||||
<h1>Viktor Kraastav</h1>
|
||||
<h2>Character Reference Page</h2>
|
||||
<h3>Welcome to Viktor's Ref Page</h3>
|
||||
<article>
|
||||
<WelcomeHeader>
|
||||
<template #main>{{ $t('welcomeHeader.mainTitle') }}</template>
|
||||
<template #sub>{{ $t('welcomeHeader.subTitle') }}</template>
|
||||
</WelcomeHeader>
|
||||
|
||||
<p>Here you can learn all about the ankylosaurus named Viktor.</p>
|
||||
<p>Pick an item from the navigation to dive in!</p>
|
||||
</TextBlock>
|
||||
<section>
|
||||
<h3>{{ $t('home.heading') }}</h3>
|
||||
|
||||
<p v-for="(p, i) in $tm('home.paragraphs')" :key="i">{{ p }}</p>
|
||||
</section>
|
||||
</article>
|
||||
</template>
|
||||
|
|
12
tsconfig.app.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["globals.d.ts", "env.d.ts", "src/**/*", "src/**/*.json", "src/**/*.vue", "package.json"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
|
@ -1,16 +1,11 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.config.json"
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
17
tsconfig.node.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "@tsconfig/node18/tsconfig.json",
|
||||
"include": [
|
||||
"globals.d.ts",
|
||||
"vite.config.*",
|
||||
"vitest.config.*",
|
||||
"cypress.config.*",
|
||||
"nightwatch.conf.*",
|
||||
"playwright.config.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
23
vite.config.mts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import { imagetools } from 'vite-imagetools'
|
||||
import autoprefixer from 'autoprefixer'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
base: "/viktor/",
|
||||
plugins: [vue(), imagetools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
css: {
|
||||
devSourcemap: true,
|
||||
postcss: {
|
||||
plugins: [autoprefixer({})]
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,19 +0,0 @@
|
|||
import { fileURLToPath, URL } from "node:url";
|
||||
|
||||
import { defineConfig } from "vite";
|
||||
import { imagetools } from "vite-imagetools";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
base: "./",
|
||||
plugins: [vue(), imagetools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||
},
|
||||
},
|
||||
css: {
|
||||
devSourcemap: true,
|
||||
},
|
||||
});
|