Compare commits

..

No commits in common. "master" and "0.7.0" have entirely different histories.

135 changed files with 35354 additions and 7906 deletions

View file

@ -1,3 +1,3 @@
defaults
>1% and not dead
> 1%
last 2 versions
not dead

View file

@ -1,15 +0,0 @@
/* eslint-env node */
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'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

14
.eslintrc.js Normal file
View file

@ -0,0 +1,14 @@
module.exports = {
root: true,
env: {
node: true,
},
extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
parserOptions: {
parser: "babel-eslint",
},
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
},
};

29
.gitignore vendored
View file

@ -1,30 +1,23 @@
# Logs
logs
*.log
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

3
.jshintrc Normal file
View file

@ -0,0 +1,3 @@
{
"esversion": 9
}

View file

@ -1,8 +0,0 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

View file

@ -1,7 +0,0 @@
{
"recommendations": [
"Vue.volar",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

15
.vscode/sftp.json vendored Normal file
View file

@ -0,0 +1,15 @@
{
"name": "sebin-reference",
"protocol": "sftp",
"port": 22,
"host": "sebin-ref",
"username": "sebin",
"privateKeyPath": "~/.ssh/id_sebin",
"passphrase": "HeyImGrump20!6",
"remotePath": "sebin-ref",
"watcher": {
"files": "dist/**",
"autoUpload": true,
"autoDelete": true
}
}

View file

@ -1,55 +1,24 @@
# Sebin Reference Page
# vue3-test
The official reference page of Sebin Nyshkim, the anthro dragon.
This page is primarily targeted at artists commissioned to draw Sebin. The idea is to have a single point of truth to easily point to.
The benefit of this is two-fold:
* Lack of attachments in Fur Affinity notes
* Participating in art raffles on Twitter without cluttering up the media tab with the same image over and over again
Furthermore, this page serves both for the development of Sebin as an independent character as well as a training ground for learning various new web technologies fitting such a project.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
## Project setup
```
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
### Compiles and hot-reloads for development
```
npm run serve
```
### Type-Check, Compile and Minify for Production
```sh
### Compiles and minifies for production
```
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

3
babel.config.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
};

View file

@ -1,44 +0,0 @@
<!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/sebin-smug-icon.png" alt="Sebin Smug Icon" />
</div>
<div class="headings">
<h1>Sebin Nyshkim</h1>
<h2>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M503.5 204.6L502.8 202.8L433.1 21.02C431.7 17.45 429.2 14.43 425.9 12.38C423.5 10.83 420.8 9.865 417.9 9.57C415 9.275 412.2 9.653 409.5 10.68C406.8 11.7 404.4 13.34 402.4 15.46C400.5 17.58 399.1 20.13 398.3 22.9L351.3 166.9H160.8L113.7 22.9C112.9 20.13 111.5 17.59 109.6 15.47C107.6 13.35 105.2 11.72 102.5 10.7C99.86 9.675 96.98 9.295 94.12 9.587C91.26 9.878 88.51 10.83 86.08 12.38C82.84 14.43 80.33 17.45 78.92 21.02L9.267 202.8L8.543 204.6C-1.484 230.8-2.72 259.6 5.023 286.6C12.77 313.5 29.07 337.3 51.47 354.2L51.74 354.4L52.33 354.8L158.3 434.3L210.9 474L242.9 498.2C246.6 500.1 251.2 502.5 255.9 502.5C260.6 502.5 265.2 500.1 268.9 498.2L300.9 474L353.5 434.3L460.2 354.4L460.5 354.1C482.9 337.2 499.2 313.5 506.1 286.6C514.7 259.6 513.5 230.8 503.5 204.6z"/></svg>
<span class="handle">SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="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>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M248,8C111.033,8,0,119.033,0,256S111.033,504,248,504,496,392.967,496,256,384.967,8,248,8ZM362.952,176.66c-3.732,39.215-19.881,134.378-28.1,178.3-3.476,18.584-10.322,24.816-16.948,25.425-14.4,1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25,5.342-39.5,3.652-3.793,67.107-61.51,68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608,69.142-14.845,10.194-26.894,9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7,18.45-13.7,108.446-47.248,144.628-62.3c68.872-28.647,83.183-33.623,92.511-33.789,2.052-.034,6.639.474,9.61,2.885a10.452,10.452,0,0,1,3.53,6.716A43.765,43.765,0,0,1,362.952,176.66Z"/></svg>
<span class="handle">@SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 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="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48 0 0 0-63.72 28.5-63.72 125.7 0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54 0 0 1-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"/></svg>
<span class="handle">@SebinNyshkim@meow.social</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 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="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/></svg>
<span class="handle">Sebin Nyshkim#8877</span>
</span>
</h2>
</div>
</main>
<!-- Open in browser and set mobile view to 2048x1072 with DPR: 2 and take screenshot -->
</body>
</html>

View file

@ -1,139 +0,0 @@
@import "../../../src/assets/fonts/exo/exo.css";
:root {
font-size: 20px;
color: #fff;
--theme-c-muted-blue: #22759d;
--theme-c-amaranth: #e93f3f;
--theme-c-deep-purple: #33124a;
--theme-c-charcoal: #303030;
--container-box-shadow: 1vw 1vw 4vw rgba(0, 0, 0, 0.7);
--welcome-header-mainline-font-size: 25vh;
--welcome-header-subline-font-size: 10vh;
--icon-size: calc(var(--welcome-header-subline-font-size) * 1.25);
--page-background: radial-gradient(circle at bottom right,
var(--theme-c-amaranth) 5%,
transparent 50%),
radial-gradient(circle at top left,
var(--theme-c-muted-blue) 5%,
var(--theme-c-deep-purple) 100%);
}
*,
*::before,
*::after {
margin: 0;
box-sizing: border-box;
/* line-height: 1.5; */
}
body {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
min-height: 100vh;
}
main::before,
main::after {
content: "";
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
main::before {
background: url(../../../src/assets/subtle-prism.svg);
mix-blend-mode: multiply;
z-index: -1;
transform: scale(1.5);
}
main::after {
background: var(--page-background);
z-index: -2;
}
.flex {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
flex: 0 0 50vw;
padding: 0 2vw;
}
.flex > * {
flex: 0 0 auto;
}
.image {
flex: 0 0 60vh;
max-height: 100vh;
}
.image img {
display: block;
width: 100%;
border-radius: 100%;
border: 3vh solid #fff; box-shadow: var(--container-box-shadow);
}
.headings {
flex: 0 1 45vw;
margin: 0;
padding: 0 1vw;
}
.headings :where(h1, h2) {
font-family: "Exo", sans-serif;
text-align: center;
font-style: italic;
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;
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
line-height: 1.75;
}
.headings .contact {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
}
.headings .icon,
.headings .handle {
flex: 0 0 auto;
}
.headings .icon {
flex: 0 0 var(--icon-size);
width: var(--icon-size);
height: var(--icon-size);
margin: 0 0.375em 0 0;
}
.headings .icon {
fill: #fff;
}

View file

@ -1,44 +0,0 @@
<!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/sebin-smug-icon.png" alt="Sebin Smug Icon" />
</div>
<div class="headings">
<h1>Sebin Nyshkim</h1>
<h2>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M503.5 204.6L502.8 202.8L433.1 21.02C431.7 17.45 429.2 14.43 425.9 12.38C423.5 10.83 420.8 9.865 417.9 9.57C415 9.275 412.2 9.653 409.5 10.68C406.8 11.7 404.4 13.34 402.4 15.46C400.5 17.58 399.1 20.13 398.3 22.9L351.3 166.9H160.8L113.7 22.9C112.9 20.13 111.5 17.59 109.6 15.47C107.6 13.35 105.2 11.72 102.5 10.7C99.86 9.675 96.98 9.295 94.12 9.587C91.26 9.878 88.51 10.83 86.08 12.38C82.84 14.43 80.33 17.45 78.92 21.02L9.267 202.8L8.543 204.6C-1.484 230.8-2.72 259.6 5.023 286.6C12.77 313.5 29.07 337.3 51.47 354.2L51.74 354.4L52.33 354.8L158.3 434.3L210.9 474L242.9 498.2C246.6 500.1 251.2 502.5 255.9 502.5C260.6 502.5 265.2 500.1 268.9 498.2L300.9 474L353.5 434.3L460.2 354.4L460.5 354.1C482.9 337.2 499.2 313.5 506.1 286.6C514.7 259.6 513.5 230.8 503.5 204.6z"/></svg>
<span class="handle">SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="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>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M248,8C111.033,8,0,119.033,0,256S111.033,504,248,504,496,392.967,496,256,384.967,8,248,8ZM362.952,176.66c-3.732,39.215-19.881,134.378-28.1,178.3-3.476,18.584-10.322,24.816-16.948,25.425-14.4,1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25,5.342-39.5,3.652-3.793,67.107-61.51,68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608,69.142-14.845,10.194-26.894,9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7,18.45-13.7,108.446-47.248,144.628-62.3c68.872-28.647,83.183-33.623,92.511-33.789,2.052-.034,6.639.474,9.61,2.885a10.452,10.452,0,0,1,3.53,6.716A43.765,43.765,0,0,1,362.952,176.66Z"/></svg>
<span class="handle">@SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 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="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48 0 0 0-63.72 28.5-63.72 125.7 0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54 0 0 1-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"/></svg>
<span class="handle">@SebinNyshkim@meow.social</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 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="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/></svg>
<span class="handle">Sebin Nyshkim#8877</span>
</span>
</h2>
</div>
</main>
<!-- Open in browser and set mobile view to 2048x1072 with DPR: 2 and take screenshot -->
</body>
</html>

View file

@ -1,139 +0,0 @@
@import "../../../src/assets/fonts/exo/exo.css";
:root {
font-size: 20px;
color: #fff;
--theme-c-muted-blue: #22759d;
--theme-c-amaranth: #e93f3f;
--theme-c-deep-purple: #33124a;
--theme-c-charcoal: #303030;
--container-box-shadow: 1vw 1vw 4vw rgba(0, 0, 0, 0.7);
--welcome-header-mainline-font-size: 6vw;
--welcome-header-subline-font-size: 2vw;
--icon-size: calc(var(--welcome-header-subline-font-size) * 1.25);
--page-background: radial-gradient(circle at bottom right,
var(--theme-c-amaranth) 5%,
transparent 50%),
radial-gradient(circle at top left,
var(--theme-c-muted-blue) 5%,
var(--theme-c-deep-purple) 100%);
}
*,
*::before,
*::after {
margin: 0;
box-sizing: border-box;
/* line-height: 1.5; */
}
body {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
min-height: 100vh;
}
main::before,
main::after {
content: "";
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
main::before {
background: url(../../../src/assets/subtle-prism.svg);
mix-blend-mode: multiply;
z-index: -1;
transform: scale(1.5);
}
main::after {
background: var(--page-background);
z-index: -2;
}
.flex {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
flex: 0 0 72vw;
}
.flex>* {
flex: 0 0 auto;
}
.image {
flex: 0 0 60vh;
max-height: 100vh;
}
.image img {
display: block;
width: 100%;
border-radius: 100%;
border: 1vw solid #fff;
box-shadow: var(--container-box-shadow);
}
.headings {
flex: 0 0 50vw;
margin: 0;
}
.headings :where(h1, h2) {
font-family: "Exo", sans-serif;
text-align: center;
font-style: italic;
margin: 0;
}
.headings h1 {
font-size: var(--welcome-header-mainline-font-size);
font-weight: 900;
line-height: 1.75;
}
.headings h2 {
font-size: var(--welcome-header-subline-font-size);
font-weight: 300;
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
line-height: 1.75;
}
.headings .contact {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
}
.headings .icon,
.headings .handle {
flex: 0 0 auto;
}
.headings .icon {
flex: 0 0 var(--icon-size);
width: var(--icon-size);
height: var(--icon-size);
margin: 0 0.375em 0 0;
}
.headings .icon {
fill: #fff;
}

View file

@ -1,44 +0,0 @@
<!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/sebin-smug-icon.png" alt="Sebin Smug Icon" />
</div>
<div class="headings">
<h1>Sebin Nyshkim</h1>
<h2>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M503.5 204.6L502.8 202.8L433.1 21.02C431.7 17.45 429.2 14.43 425.9 12.38C423.5 10.83 420.8 9.865 417.9 9.57C415 9.275 412.2 9.653 409.5 10.68C406.8 11.7 404.4 13.34 402.4 15.46C400.5 17.58 399.1 20.13 398.3 22.9L351.3 166.9H160.8L113.7 22.9C112.9 20.13 111.5 17.59 109.6 15.47C107.6 13.35 105.2 11.72 102.5 10.7C99.86 9.675 96.98 9.295 94.12 9.587C91.26 9.878 88.51 10.83 86.08 12.38C82.84 14.43 80.33 17.45 78.92 21.02L9.267 202.8L8.543 204.6C-1.484 230.8-2.72 259.6 5.023 286.6C12.77 313.5 29.07 337.3 51.47 354.2L51.74 354.4L52.33 354.8L158.3 434.3L210.9 474L242.9 498.2C246.6 500.1 251.2 502.5 255.9 502.5C260.6 502.5 265.2 500.1 268.9 498.2L300.9 474L353.5 434.3L460.2 354.4L460.5 354.1C482.9 337.2 499.2 313.5 506.1 286.6C514.7 259.6 513.5 230.8 503.5 204.6z"/></svg>
<span class="handle">SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="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>
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 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="M248,8C111.033,8,0,119.033,0,256S111.033,504,248,504,496,392.967,496,256,384.967,8,248,8ZM362.952,176.66c-3.732,39.215-19.881,134.378-28.1,178.3-3.476,18.584-10.322,24.816-16.948,25.425-14.4,1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25,5.342-39.5,3.652-3.793,67.107-61.51,68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608,69.142-14.845,10.194-26.894,9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7,18.45-13.7,108.446-47.248,144.628-62.3c68.872-28.647,83.183-33.623,92.511-33.789,2.052-.034,6.639.474,9.61,2.885a10.452,10.452,0,0,1,3.53,6.716A43.765,43.765,0,0,1,362.952,176.66Z"/></svg>
<span class="handle">@SebinNyshkim</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 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="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48 0 0 0-63.72 28.5-63.72 125.7 0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54 0 0 1-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"/></svg>
<span class="handle">@SebinNyshkim@meow.social</span>
</span>
<span class="contact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 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="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/></svg>
<span class="handle">Sebin Nyshkim#8877</span>
</span>
</h2>
</div>
</main>
<!-- Open in browser and set mobile view to 2048x1072 with DPR: 2 and take screenshot -->
</body>
</html>

View file

@ -1,143 +0,0 @@
@import "../../../src/assets/fonts/exo/exo.css";
:root {
font-size: 20px;
color: #fff;
--theme-c-muted-blue: #22759d;
--theme-c-amaranth: #e93f3f;
--theme-c-deep-purple: #33124a;
--theme-c-charcoal: #303030;
--container-box-shadow: 1vw 1vw 4vw rgba(0, 0, 0, 0.7);
--welcome-header-mainline-font-size: 8vw;
--welcome-header-subline-font-size: 2.5vw;
--icon-size: calc(var(--welcome-header-subline-font-size) * 1.25);
--page-background: radial-gradient(
circle at bottom right,
var(--theme-c-amaranth) 5%,
transparent 50%
),
radial-gradient(
circle at top left,
var(--theme-c-muted-blue) 5%,
var(--theme-c-deep-purple) 100%
);
}
*,
*::before,
*::after {
margin: 0;
box-sizing: border-box;
/* line-height: 1.5; */
}
body {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
min-height: 100vh;
}
main::before,
main::after {
content: "";
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
main::before {
background: url(../../../src/assets/subtle-prism.svg);
mix-blend-mode: multiply;
z-index: -1;
transform: scale(1.5);
}
main::after {
background: var(--page-background);
z-index: -2;
}
.flex {
display: flex;
flex-flow: row nowrap;
justify-content: space-evenly;
align-items: center;
flex: 0 0 100%;
}
.flex > * {
flex: 0 0 auto;
}
.image {
flex: 0 0 60vh;
max-height: 100vh;
}
.image img {
display: block;
width: 100%;
border-radius: 100%;
border: 1vw solid #fff;
box-shadow: var(--container-box-shadow);
}
.headings {
flex: 0 0 60vw;
margin: 0;
}
.headings :where(h1, h2) {
font-family: "Exo", sans-serif;
text-align: center;
font-style: italic;
margin: 0;
}
.headings h1 {
font-size: var(--welcome-header-mainline-font-size);
font-weight: 900;
line-height: 1.75;
}
.headings h2 {
font-size: var(--welcome-header-subline-font-size);
font-weight: 300;
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
line-height: 1.75;
}
.headings .contact {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
}
.headings .icon,
.headings .handle {
flex: 0 0 auto;
}
.headings .icon {
flex: 0 0 var(--icon-size);
width: var(--icon-size);
height: var(--icon-size);
margin: 0 0.375em 0 0;
}
.headings .icon {
fill: #fff;
}

View file

@ -1,22 +0,0 @@
<!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/sebin-smug-icon.png" alt="Sebin Smug Icon" />
</div>
<div class="headings">
<h1>Sebin Nyshkim</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>

View file

@ -1,112 +0,0 @@
@import "../src/assets/fonts/exo/exo.css";
:root {
font-size: 20px;
color: #fff;
--theme-c-muted-blue: #22759d;
--theme-c-amaranth: #e93f3f;
--theme-c-deep-purple: #33124a;
--theme-c-charcoal: #303030;
--container-box-shadow: 1vw 1vw 4vw rgba(0, 0, 0, 0.7);
--welcome-header-mainline-font-size: 8vw;
--welcome-header-subline-font-size: 3.5vw;
--page-background: radial-gradient(
circle at bottom right,
var(--theme-c-amaranth) 5%,
transparent 50%
),
radial-gradient(
circle at top left,
var(--theme-c-muted-blue) 5%,
var(--theme-c-deep-purple) 100%
);
}
*,
*::before,
*::after {
margin: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
min-height: 100vh;
}
main::before,
main::after {
content: "";
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
main::before {
background: url(../src/assets/subtle-prism.svg);
mix-blend-mode: multiply;
z-index: -1;
transform: scale(1.5);
}
main::after {
background: var(--page-background);
z-index: -2;
}
.flex {
display: flex;
flex-flow: row nowrap;
justify-content: space-evenly;
align-items: center;
flex: 0 0 100%;
}
.flex > * {
flex: 0 0 auto;
}
.image {
flex: 0 0 60vh;
max-height: 100vh;
}
.image img {
display: block;
width: 100%;
border-radius: 100%;
border: 1vw solid #fff;
box-shadow: var(--container-box-shadow);
}
.headings {
flex: 0 0 60vw;
margin: 0;
}
.headings :where(h1, h2) {
font-family: "Exo", sans-serif;
text-align: center;
font-style: italic;
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;
}

1
env.d.ts vendored
View file

@ -1 +0,0 @@
/// <reference types="vite/client" />

View file

@ -1,30 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<link rel="favicon" href="favicon.png" type="image/png" />
<link rel="icon" href="favicon.png" type="image/png" />
<title>Sebin Nyshkim - Reference Page</title>
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#22759d" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#195673" />
<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="Sebin Nyshkim - Reference Page" />
<meta name="twitter:description" content="The official reference page for Sebin Nyshkim with picture references and in-depth character descriptions" />
<meta name="twitter:image" content="https://ref.sebin-nyshkim.net/sebin/preview.png" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Sebin Nyshkim - Reference Page" />
<meta property="og:locale" content="en_US" />
<meta property="og:url" content="https://ref.sebin-nyshkim.net/sebin/" />
<meta property="og:image" content="https://ref.sebin-nyshkim.net/sebin/preview.png" />
<meta property="og:description" content="The official reference page for Sebin Nyshkim with picture references and in-depth character descriptions" />
</head>
<body>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

0
jsconfig.json Normal file
View file

35366
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,38 +1,32 @@
{
"name": "sebin-reference",
"version": "0.10.7",
"version": "0.7.0",
"private": true,
"scripts": {
"dev": "vite --host",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"vue": "^3.4.38",
"vue-router": "^4.4.3"
"core-js": "^3.6.5",
"normalize.css": "^8.0.1",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.10.4",
"@tsconfig/node20": "^20.1.4",
"@types/node": "^20.16.3",
"@vitejs/plugin-vue": "^5.1.3",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.28.0",
"normalize.css": "^8.0.1",
"npm-run-all2": "^6.2.2",
"prettier": "^3.3.3",
"sass": "^1.77.8",
"typescript": "~5.5.0",
"vite": "^5.4.2",
"vite-imagetools": "^6.2.9",
"vue-tsc": "^2.1.4"
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"image-webpack-loader": "^8.0.1",
"prettier": "^2.2.1",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
}
}

View file

@ -1,8 +0,0 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /sebin/index.html [L]
</IfModule>

19
public/index.html Normal file
View file

@ -0,0 +1,19 @@
<!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,viewport-fit=cover">
<link rel="<%= htmlWebpackPlugin.options.links.favicon.rel %>" href="<%= htmlWebpackPlugin.options.links.favicon.href %>" type="<%= htmlWebpackPlugin.options.links.favicon.type %>">
<link rel="<%= htmlWebpackPlugin.options.links.icon.rel %>" href="<%= htmlWebpackPlugin.options.links.icon.href %>" type="<%= htmlWebpackPlugin.options.links.icon.type %>">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>Sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div class="bubbles"></div>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

BIN
public/preview.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

View file

@ -1,99 +1,163 @@
<script setup lang="ts">
import { ref, provide } from 'vue'
import { RouterView } from 'vue-router'
import { modalResultKey, nsfwKey, showModalKey } from '@/keys'
import { version } from '../package.json'
import RefModal from '@/components/RefModal.vue'
import ButtonGroup from '@/components/ButtonGroup.vue'
import Button from '@/components/RefButton.vue'
import SiteHeader from '@/components/SiteHeader.vue'
import SiteFooter from '@/components/SiteFooter.vue'
import SiteNavigation from '@/components/SiteNavigation.vue'
<template>
<header>
<img
class="nav-logo"
src="@/assets/sebin-smug-icon.png"
alt="Sebin Avatar"
/>
const isNsfw = ref(false)
const isConfirmedHorny = ref(false)
<navigation :routes="routes" />
</header>
const nsfwmodal = ref<InstanceType<typeof RefModal>>()
<router-view />
const showModal = (): void => {
if (!isConfirmedHorny.value) {
nsfwmodal.value?.showModal()
<footer class="footer">
<div class="footer__copyright">
v{{ version }} © {{ new Date().getFullYear() }} Sebin Nyshkim
</div>
<ul class="footer__linklist">
<li class="footer__linkitem" v-for="(link, idx) in links" :key="idx">
<a :href="link.href" class="footer__link">
{{ link.text }}
</a>
</li>
</ul>
</footer>
</template>
<script>
import Navigation from "@/components/Navigation.vue";
export default {
components: { Navigation },
data() {
return {
nsfw: false,
isConfirmedHorny: false,
isWarn: false,
version: require("../package.json").version,
routes: [
{ path: "/", name: "Home" },
{ path: "/general", name: "General" },
{ path: "/anatomy", name: "Anatomy" },
{ path: "/clothing", name: "Clothing" },
{ path: "/abilities", name: "Abilities" },
{ path: "/overdrive", name: "Overdrive" },
],
links: [
{ href: "https://twitter.com/SebinNyshkim", text: "Twitter" },
{ href: "https://t.me/SebinNyshkim", text: "Telegram" },
{
href: "https://www.furaffinity.net/user/sonofdragons",
text: "Fur Affinity",
},
],
};
},
methods: {
showWarning() {
if (!this.isConfirmedHorny) {
this.isWarn = true;
setTimeout(() => {
isNsfw.value = false
}, 1)
} else {
isNsfw.value = !isNsfw.value
this.nsfw = false;
}, 1);
}
},
},
};
</script>
<style lang="scss">
@import "@/scss/base.scss";
@import "~normalize.css";
#app {
padding: 5em 0 0 0;
color: $copy-color;
font-size: 1.125em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transition: all ease-in-out 0.25s;
@media (min-width: 50em) {
font-size: 1.25em;
}
@media (min-width: 125em) {
font-size: 1.5em;
}
}
const modalResult = (value: boolean): void => {
isNsfw.value = value
isConfirmedHorny.value = value
nsfwmodal.value?.close()
header {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: env(safe-area-inset-top);
right: env(safe-area-inset-right);
left: env(safe-area-inset-left);
z-index: 2;
max-width: 70em;
margin: 1em;
padding: 0.5em;
border-radius: 0.5em;
box-shadow: 0.125em 0.125em 0.5em rgba(0, 0, 0, 0.7);
background-color: darken($bg-color-dark, 5%);
@media (min-width: 90em) {
margin: 1em auto;
}
}
provide(modalResultKey, modalResult)
provide(nsfwKey, isNsfw)
provide(showModalKey, showModal)
</script>
.nav-logo {
display: block;
margin: 0 0 0 0.25em;
height: 2em;
border: 0.125em solid #fff;
border-radius: 100%;
box-shadow: 0.125em 0.125em 0.5em rgba(0, 0, 0, 0.7);
}
<template>
<RefModal id="nsfw-warning" ref="nsfwmodal">
<template #heading>
<br />
Whoa, Nelly!
</template>
.footer {
margin: 2em 0 0 0;
padding: 0.75em 0;
background-color: $bg-color-light;
text-align: center;
<template #message>
By enabling NSFW mode you confirm that you are of legal age to view adult content.
</template>
@media (orientation: landscape) {
padding: env(safe-area-inset-bottom) 0;
}
<template #buttons>
<ButtonGroup col>
<Button positive @click.prevent="modalResult(true)"> Yes, show me the goods 👀 </Button>
<Button negative @click.prevent="modalResult(false)"> NO, STAHP 😱 </Button>
</ButtonGroup>
</template>
</RefModal>
@include mq-desktop {
padding: 0.75em 0;
}
<SiteHeader>
<!-- max 500px -->
<picture>
<source
srcset="
@/assets/sebin-smug-icon.png?w=36;40;48;56;72;80;96;112;108;120;144;168&format=avif&quality=75&as=srcset
"
sizes="(min-width: 120em) 56px, (min-width: 80em) 48px, (min-width: 35em) 40px, 36px"
type="image/avif"
/>
<source
srcset="
@/assets/sebin-smug-icon.png?w=36;40;48;56;72;80;96;112;108;120;144;168&format=webp&quality=100&as=srcset
"
sizes="(min-width: 120em) 56px, (min-width: 80em) 48px, (min-width: 35em) 40px, 36px"
type="image/webp"
/>
<img
class="nav-logo"
srcset="@/assets/sebin-smug-icon.png?w=36;40;48;56;72;80;96;112;108;120;144;168&format=png&as=srcset"
sizes="(min-width: 120em) 56px, (min-width: 80em) 48px, (min-width: 35em) 40px, 36px"
alt="Sebin Avatar"
/>
</picture>
&__copyright {
margin: 0;
}
<SiteNavigation />
</SiteHeader>
&__linklist {
margin: 0;
padding: 0;
list-style: none;
<main>
<RouterView />
</main>
display: flex;
flex-flow: row wrap;
justify-content: center;
}
<SiteFooter>
<p>v{{ version }} &copy; {{ new Date().getFullYear() }} Sebin Nyshkim</p>
<p>
Background Pattern &copy;
<a href="https://www.svgbackgrounds.com/">SVG Backgrounds</a>
</p>
</SiteFooter>
</template>
&__linkitem {
}
&__link {
color: $copy-color;
padding: 0.5em 0.75em;
}
}
</style>

View file

@ -1,19 +0,0 @@
/* dosis-regular-latin */
@font-face {
font-family: Dosis;
font-style: normal;
font-weight: 400;
src: local("Dosis Regular"), local("Dosis-Regular"), url(dosis-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;
}
/* dosis-bold-latin */
@font-face {
font-family: Dosis;
font-style: normal;
font-weight: 700;
src: local("Dosis Bold"), local("Dosis-Bold"), url(dosis-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;
}

View file

@ -1,37 +0,0 @@
/* exo-light-latin */
@font-face {
font-family: Exo;
font-style: normal;
font-weight: 300;
src: local("Exo Light"), local("Exo-Light"), url(exo-light-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;
}
/* exo-black-latin */
@font-face {
font-family: Exo;
font-style: normal;
font-weight: 900;
src: local("Exo Black"), local("Exo-Black"), url(exo-black-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;
}
/* exo-light-italic-latin */
@font-face {
font-family: Exo;
font-style: italic;
font-weight: 300;
src: local("Exo Light Italic"), local("Exo-LightItalic"), url(exo-light-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;
}
/* exo-black-italic-latin */
@font-face {
font-family: Exo;
font-style: italic;
font-weight: 900;
src: local("Exo Black Italic"), local("Exo-BlackItalic"), url(exo-black-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;
}

View file

@ -1,10 +0,0 @@
/* permanent-marker-regular-latin */
@font-face {
font-family: Permanent Marker;
font-style: normal;
font-weight: 400;
src: local("Permanent Marker Regular"), local("PermanentMarker-Regular"), url(permanent-marker-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;
}

View file

@ -1,10 +0,0 @@
/* zilla-slab-bold-latin */
@font-face {
font-family: Zilla Slab;
font-style: normal;
font-weight: 700;
src: local("Zilla Slab Bold"), local("ZillaSlab-Bold"), url(zilla-slab-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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 218 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Before After
Before After

0
src/assets/refs/clothes/casual/fullbody.png Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 784 KiB

After

Width:  |  Height:  |  Size: 784 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 MiB

After

Width:  |  Height:  |  Size: 432 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 589 KiB

After

Width:  |  Height:  |  Size: 393 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 619 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 MiB

View file

@ -1,78 +0,0 @@
<svg xmlns='http://www.w3.org/2000/svg' width='100%'>
<defs>
<pattern patternUnits='userSpaceOnUse' id='b' width='540' height='450' x='0' y='0' viewBox='0 0 1080 900'>
<g fill-opacity='0.1'>
<polygon fill='#444' points='90 150 0 300 180 300'/>
<polygon points='90 150 180 0 0 0'/>
<polygon fill='#AAA' points='270 150 360 0 180 0'/>
<polygon fill='#DDD' points='450 150 360 300 540 300'/>
<polygon fill='#999' points='450 150 540 0 360 0'/>
<polygon points='630 150 540 300 720 300'/>
<polygon fill='#DDD' points='630 150 720 0 540 0'/>
<polygon fill='#444' points='810 150 720 300 900 300'/>
<polygon fill='#FFF' points='810 150 900 0 720 0'/>
<polygon fill='#DDD' points='990 150 900 300 1080 300'/>
<polygon fill='#444' points='990 150 1080 0 900 0'/>
<polygon fill='#DDD' points='90 450 0 600 180 600'/>
<polygon points='90 450 180 300 0 300'/>
<polygon fill='#666' points='270 450 180 600 360 600'/>
<polygon fill='#AAA' points='270 450 360 300 180 300'/>
<polygon fill='#DDD' points='450 450 360 600 540 600'/>
<polygon fill='#999' points='450 450 540 300 360 300'/>
<polygon fill='#999' points='630 450 540 600 720 600'/>
<polygon fill='#FFF' points='630 450 720 300 540 300'/>
<polygon points='810 450 720 600 900 600'/>
<polygon fill='#DDD' points='810 450 900 300 720 300'/>
<polygon fill='#AAA' points='990 450 900 600 1080 600'/>
<polygon fill='#444' points='990 450 1080 300 900 300'/>
<polygon fill='#222' points='90 750 0 900 180 900'/>
<polygon points='270 750 180 900 360 900'/>
<polygon fill='#DDD' points='270 750 360 600 180 600'/>
<polygon points='450 750 540 600 360 600'/>
<polygon points='630 750 540 900 720 900'/>
<polygon fill='#444' points='630 750 720 600 540 600'/>
<polygon fill='#AAA' points='810 750 720 900 900 900'/>
<polygon fill='#666' points='810 750 900 600 720 600'/>
<polygon fill='#999' points='990 750 900 900 1080 900'/>
<polygon fill='#999' points='180 0 90 150 270 150'/>
<polygon fill='#444' points='360 0 270 150 450 150'/>
<polygon fill='#FFF' points='540 0 450 150 630 150'/>
<polygon points='900 0 810 150 990 150'/>
<polygon fill='#222' points='0 300 -90 450 90 450'/>
<polygon fill='#FFF' points='0 300 90 150 -90 150'/>
<polygon fill='#FFF' points='180 300 90 450 270 450'/>
<polygon fill='#666' points='180 300 270 150 90 150'/>
<polygon fill='#222' points='360 300 270 450 450 450'/>
<polygon fill='#FFF' points='360 300 450 150 270 150'/>
<polygon fill='#444' points='540 300 450 450 630 450'/>
<polygon fill='#222' points='540 300 630 150 450 150'/>
<polygon fill='#AAA' points='720 300 630 450 810 450'/>
<polygon fill='#666' points='720 300 810 150 630 150'/>
<polygon fill='#FFF' points='900 300 810 450 990 450'/>
<polygon fill='#999' points='900 300 990 150 810 150'/>
<polygon points='0 600 -90 750 90 750'/>
<polygon fill='#666' points='0 600 90 450 -90 450'/>
<polygon fill='#AAA' points='180 600 90 750 270 750'/>
<polygon fill='#444' points='180 600 270 450 90 450'/>
<polygon fill='#444' points='360 600 270 750 450 750'/>
<polygon fill='#999' points='360 600 450 450 270 450'/>
<polygon fill='#666' points='540 600 630 450 450 450'/>
<polygon fill='#222' points='720 600 630 750 810 750'/>
<polygon fill='#FFF' points='900 600 810 750 990 750'/>
<polygon fill='#222' points='900 600 990 450 810 450'/>
<polygon fill='#DDD' points='0 900 90 750 -90 750'/>
<polygon fill='#444' points='180 900 270 750 90 750'/>
<polygon fill='#FFF' points='360 900 450 750 270 750'/>
<polygon fill='#AAA' points='540 900 630 750 450 750'/>
<polygon fill='#FFF' points='720 900 810 750 630 750'/>
<polygon fill='#222' points='900 900 990 750 810 750'/>
<polygon fill='#222' points='1080 300 990 450 1170 450'/>
<polygon fill='#FFF' points='1080 300 1170 150 990 150'/>
<polygon points='1080 600 990 750 1170 750'/>
<polygon fill='#666' points='1080 600 1170 450 990 450'/>
<polygon fill='#DDD' points='1080 900 1170 750 990 750'/>
</g>
</pattern>
</defs>
<rect x='0' y='0' fill='url(#b)' width='100%' height='100%'/>
</svg>

View file

@ -1,67 +0,0 @@
<template>
<figure class="attack">
<div class="attack__illustration">
<slot name="image"></slot>
</div>
<figcaption class="attack__text">
<div class="attack__name">
<slot name="name"></slot>
</div>
<div class="attack__description">
<slot name="desc"></slot>
</div>
</figcaption>
</figure>
</template>
<style lang="scss">
.attack {
flex: var(--attack-item-flex);
display: flex;
flex-flow: var(--attack-item-flex-flow);
align-items: center;
margin: 0;
padding: 0.375em 0;
&:nth-child(even) {
text-align: var(--attack-item-nth-child-even-text-align);
}
&:nth-child(even) &__illustration,
&:nth-child(even) &__text {
&:first-child {
order: var(--attack-item-first-child-order);
}
}
&__illustration {
flex: var(--attack-item-illustration-flex);
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
text-align: center;
img {
max-width: 100%;
max-height: 100%;
}
}
&__text {
flex: 1 1 auto;
padding: var(--attack-item-text-padding);
}
&__name {
font-weight: bold;
margin: 0 0 1em 0;
}
}
</style>

View file

@ -1,18 +0,0 @@
<template>
<div class="attacks">
<slot></slot>
</div>
</template>
<style lang="scss">
.attacks {
display: flex;
flex-flow: row wrap;
align-items: center;
width: 100%;
max-width: var(--attack-list-max-width);
margin: auto;
padding: 0 var(--container-spacing-right-safe) 0 var(--container-spacing-left-safe);
}
</style>

View file

@ -1,48 +0,0 @@
<script setup lang="ts">
interface Props {
col?: boolean
grid?: boolean
}
defineProps<Props>()
</script>
<template>
<div class="btn-group" :class="{ col: col, grid: grid }">
<slot></slot>
</div>
</template>
<style lang="scss">
.btn-group {
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
&.col {
flex-flow: column nowrap;
gap: 1.5rem;
margin: 1rem 0;
> * {
margin: 0;
}
}
&.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin: 1rem 0;
> * {
margin: 0;
}
}
> * {
flex: var(--button-group-flex);
margin: 1rem 0;
}
}
</style>

View file

@ -1,53 +0,0 @@
<script setup lang="ts">
import type { ColorDict } from '@/interfaces'
interface Props {
colors: ColorDict[]
}
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>
</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 value">{{ color.value }}</td>
<td class="color-table__cell color" :style="{ 'background-color': color.value }"></td>
</tr>
</tbody>
</table>
</template>
<style lang="scss">
.color-table {
&__heading {
&.name {
text-align: right;
}
}
&__cell {
&.name {
text-align: right;
}
&.value {
font-family: monospace;
text-align: center;
}
&.color {
min-width: 10vw;
}
}
}
</style>

View file

@ -1,37 +1,97 @@
<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">
{{ heading }}
<table class="datatable">
<thead class="datatable__head">
<tr class="datatable__row datatable__row--head">
<th
class="datatable__heading"
v-for="(header, idx) in dataset.headers"
:key="idx"
>
{{ header }}
</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">
<tbody class="datatable__body">
<tr class="datatable__row" v-for="(row, idx) in dataset.data" :key="idx">
<td
class="datatable__cell"
v-for="(cell, idx) in row"
:key="idx"
:colspan="idx === 1 && !isHexValue(row[1]) ? 2 : 1"
>
{{ cell }}
</td>
<td
v-if="isHexValue(row[1])"
class="datatable__cell--colorpick"
:style="`background-color: ${row[1]}`"
></td>
</tr>
</tbody>
</table>
</template>
<style lang="scss">
.data-table {
table-layout: fixed;
<script>
export default {
name: "DataTable",
props: {
dataset: {
type: Object,
required: true,
},
},
methods: {
isHexValue(value) {
return /^#[0-9a-f]{6}$/i.test(value) ? value : false;
},
},
};
</script>
&__cell:first-child {
<style lang="scss">
@import "@/scss/_variables.scss";
.datatable {
border-collapse: collapse;
width: 100%;
max-width: 55rem;
margin: auto;
&__heading,
&__cell {
padding: 0.25em 0.5em;
@media (min-width: 35em) {
padding: 0.5em 1em;
}
}
&__body {
.datatable__row {
background-color: rgba($bg-color-dark, 0.7);
&:nth-child(odd) {
background-color: rgba(lighten($bg-color-dark, 15%), 0.7);
}
}
}
&__row {
&--head {
background-color: $bg-color-light;
color: $copy-color;
}
}
&__cell {
&:first-child {
text-align: right;
}
&--colorpick {
margin-top: 0.1em;
border: 0.1em solid #fff;
}
}
}
</style>

166
src/components/Figure.vue Normal file
View file

@ -0,0 +1,166 @@
<template>
<figure class="figure">
<div
class="figure__border"
:class="{ 'figure__border--polaroid': polaroidBorder }"
>
<template v-if="!nsfw || $root.nsfw">
<slot name="img"></slot>
</template>
<template v-else>
<div class="figure__cencor">
<div class="hazard-tape"></div>
<div class="hazard-tape"></div>
<div class="hazard-tape"></div>
<div class="hazard-tape"></div>
<p>🔥 Here be spicy dragons 🌶</p>
<nsfw-switch
:id="id"
v-model="$root.nsfw"
@change="$root.showWarning()"
/>
</div>
</template>
<figcaption class="figure__meta">
<template v-if="!nsfw || $root.nsfw">
<div class="caption">
<slot name="caption"></slot>
</div>
<div class="copyright">
<slot name="copyright"></slot>
</div>
</template>
<template v-else>
<p>😳 2 hot 4 u 🍆</p>
</template>
</figcaption>
</div>
</figure>
</template>
<script>
import NsfwSwitch from "@/components/NsfwSwitch.vue";
export default {
props: {
polaroidBorder: Boolean,
nsfw: Boolean,
id: String,
},
components: {
NsfwSwitch,
},
};
</script>
<style lang="scss">
@import "@/scss/_variables.scss";
@import "@/scss/_mixins.scss";
.figure {
display: flex;
flex-flow: row nowrap;
margin: 1em auto;
padding: 0 1em;
text-align: center;
&__border {
display: flex;
flex-flow: column nowrap;
justify-content: center;
margin: auto;
&--polaroid {
margin: 1em auto;
padding: 1em;
background-color: #fff;
box-shadow: inset 0 0 1em rgba(#000, 0.7), 0 0 1em rgba(#000, 0.7);
border-radius: 0.325em;
.figure__meta {
margin: 0.5em 0;
font-family: "Permanent Marker", fantasy;
color: $copy-color-darkgrey;
* {
color: inherit;
}
}
}
}
&__cencor {
position: relative;
padding: 6em 0;
background-color: $bg-color-light;
overflow: hidden;
@include mq-desktop {
padding: 9em 7em;
}
.figure__border & .nsfw-switch {
position: relative;
padding: 0;
}
.hazard-tape {
position: absolute;
left: -1em;
right: -1em;
top: 0;
transform: rotate(0deg);
height: 1em;
background-image: repeating-linear-gradient(
-55deg,
#000,
#000 0.75em,
#ffb101 0.75em,
#ffb101 1.5em
);
&:nth-child(1) {
top: 5%;
transform: rotate(5deg);
}
&:nth-child(2) {
top: 10%;
transform: rotate(-10deg);
}
&:nth-child(3) {
top: 75%;
transform: rotate(-15deg);
}
&:nth-child(4) {
top: 85%;
transform: translate(-3em, -2em) rotate(40deg);
}
}
}
img {
max-width: 100%;
object-fit: contain;
@include mq-desktop {
max-height: 60vh;
}
}
a:before {
display: inline;
content: "©";
}
}
</style>

View file

@ -1,161 +0,0 @@
<script setup lang="ts">
import { computed } from 'vue'
import { Ratings } from '@/interfaces'
interface Props {
modelValue: number[]
name?: string
value: Ratings
}
interface Emits {
(e: 'update:modelValue', value: number[]): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const checked = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>
<template>
<div class="filter-button">
<input
class="filter-button__input"
type="checkbox"
:name="name"
:id="Ratings[value].toLowerCase()"
:value="value"
v-model="checked"
/>
<label
:for="Ratings[value].toLowerCase()"
class="filter-button__label"
:class="[Ratings[value].toLowerCase()]"
>
{{ Ratings[value] }}
</label>
</div>
</template>
<style lang="scss">
.filter-button {
flex: 1 1 0;
&__input {
display: none;
}
&__input:checked + &__label {
top: 0.25rem;
box-shadow: 0 0.25rem 0 0 var(--color-button-box-shadow);
&.love {
box-shadow: 0 0.25rem 0 0 var(--theme-c-love-dark);
}
&.yes {
box-shadow: 0 0.25rem 0 0 var(--theme-c-yes-dark);
}
&.maybe {
box-shadow: 0 0.25rem 0 0 var(--theme-c-maybe-dark);
}
&.no {
box-shadow: 0 0.25rem 0 0 var(--theme-c-no-dark);
}
}
&__label {
display: block;
position: relative;
top: 0;
background-color: var(--color-button);
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);
}
&.love {
background-color: var(--theme-c-love);
box-shadow: 0 0.5rem 0 0 var(--theme-c-love-dark);
&:hover {
box-shadow: 0 0.75rem 0 0 var(--theme-c-love-dark);
}
&:active {
box-shadow: 0 0.25rem 0 0 var(--theme-c-love-dark);
}
}
&.yes {
background-color: var(--theme-c-yes);
box-shadow: 0 0.5rem 0 0 var(--theme-c-yes-dark);
&:hover {
box-shadow: 0 0.75rem 0 0 var(--theme-c-yes-dark);
}
&:active {
box-shadow: 0 0.25rem 0 0 var(--theme-c-yes-dark);
}
}
&.maybe {
background-color: var(--theme-c-maybe);
box-shadow: 0 0.5rem 0 0 var(--theme-c-maybe-dark);
&:hover {
box-shadow: 0 0.75rem 0 0 var(--theme-c-maybe-dark);
}
&:active {
box-shadow: 0 0.25rem 0 0 var(--theme-c-maybe-dark);
}
}
&.no {
background-color: var(--theme-c-no);
box-shadow: 0 0.5rem 0 0 var(--theme-c-no-dark);
&:hover {
box-shadow: 0 0.75rem 0 0 var(--theme-c-no-dark);
}
&:active {
box-shadow: 0 0.25rem 0 0 var(--theme-c-no-dark);
}
}
}
}
</style>

View file

@ -1,77 +0,0 @@
<script setup lang="ts">
interface Props {
type: string
}
defineProps<Props>()
</script>
<template>
<span class="filter-list__tag" :class="type.toLowerCase()">
<span>{{ type }}</span>
</span>
</template>
<style lang="scss">
.filter-list {
&__tag {
flex: 0 0 0;
span {
display: block;
font-size: 0.75rem;
font-weight: bold;
text-align: center;
background: rgba(#f5f5f5, 0.7);
border: 1px solid #f5f5f5;
border-radius: 1em;
padding: 0 0.5em;
}
&.love span {
background: var(--theme-c-love);
border: 1px solid var(--theme-c-love-dark);
}
&.yes span {
background: var(--theme-c-yes);
border: 1px solid var(--theme-c-yes-dark);
}
&.maybe span {
background: var(--theme-c-maybe);
border: 1px solid var(--theme-c-maybe-dark);
}
&.no span {
background: var(--theme-c-no);
border: 1px solid var(--theme-c-no-dark);
}
&.category {
flex: 0 0 3rem;
}
&.receive {
flex: 0 0 3.125rem;
span {
background: var(--theme-c-receive);
border: 1px solid var(--theme-c-receive);
}
}
&.give {
flex: 0 0 2.125rem;
span {
background: var(--theme-c-give);
border: 1px solid var(--theme-c-give);
}
}
}
}
</style>

View file

@ -1,127 +0,0 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Ratings, Role } from '@/interfaces'
import type { Kink } from '@/interfaces'
import FilterButton from '@/components/FilterButton.vue'
import FilterListTag from '@/components/FilterListTag.vue'
interface Props {
data: Kink[]
}
const props = defineProps<Props>()
const filterOptions = ref<number[]>([])
const filteredItems = computed(() =>
[...props.data]
.sort((a, b) => a.rating - b.rating)
.filter((kink) => filterOptions.value.some((filterNum) => kink.rating === filterNum))
)
</script>
<template>
<div class="filter-list">
<div class="filter-list__filters">
<FilterButton name="rating" :value="Ratings.Love" v-model="filterOptions" />
<FilterButton name="rating" :value="Ratings.Yes" v-model="filterOptions" />
<FilterButton name="rating" :value="Ratings.Maybe" v-model="filterOptions" />
<FilterButton name="rating" :value="Ratings.No" v-model="filterOptions" />
</div>
<div class="filter-list__list-container">
<template v-if="filterOptions.length > 0">
<ul class="filter-list__list">
<li v-for="(item, idx) in filteredItems" :key="idx" class="filter-list__item">
<FilterListTag
v-if="filterOptions.length > 1"
class="category"
:type="Ratings[item.rating]"
/>
<span class="filter-list__item-name">
<span>{{ item.name }}</span>
</span>
<FilterListTag
v-if="((item.role ?? 0) & Role.Receive) === Role.Receive"
:type="Role[Role.Receive]"
/>
<FilterListTag
v-if="((item.role ?? 0) & Role.Give) === Role.Give"
:type="Role[Role.Give]"
/>
</li>
</ul>
</template>
<template v-else>
<p class="filter-list__intro-msg">Select one of the categories above</p>
</template>
</div>
</div>
</template>
<style lang="scss">
.filter-list {
background: var(--quickfacts-background);
border-radius: 1rem;
box-shadow: var(--container-box-shadow);
overflow: hidden;
&__options {
display: flex;
gap: 1rem;
margin: 0;
padding: 0;
list-style: none;
}
&__filters {
display: flex;
gap: 0.75rem;
border-collapse: collapse;
padding: 0.5rem 0.75rem;
}
&__intro-msg {
font-size: 2rem;
font-weight: bold;
font-style: italic;
text-align: center;
hyphens: none;
}
&__list-container {
border-top: 0.125rem solid var(--color-quickfacts-border);
border-collapse: collapse;
}
&__list {
max-height: 30rem;
margin: 0;
padding: 0;
overflow: scroll;
}
&__item {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.875rem;
&:hover {
background: rgba(#000, 0.3);
}
}
&__item-name {
flex: 1 0 0;
line-height: 2;
}
}
</style>

63
src/components/Footer.vue Normal file
View file

@ -0,0 +1,63 @@
<template>
<footer class="footer">
<div class="footer__copyright">
v{{ $parent.version }} © {{ new Date().getFullYear() }} Sebin Nyshkim
</div>
<ul class="footer__linklist">
<li class="footer__linkitem" v-for="(link, idx) in links" :key="idx">
<a :href="link.href" class="footer__link">
{{ link.text }}
</a>
</li>
</ul>
</footer>
</template>
<script>
export default {
data() {
return {
links: [
{ href: "https://twitter.com/SebinNyshkim", text: "Twitter" },
{ href: "https://t.me/SebinNyshkim", text: "Telegram" },
{
href: "https://www.furaffinity.net/user/sonofdragons",
text: "Fur Affinity",
},
],
};
},
};
</script>
<style lang="scss">
@import "@scss/_variables.scss";
.footer {
background-color: $bg-color-light;
padding: 0.5em 0;
text-align: center;
&__copyright {
margin: 0;
}
&__linklist {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-flow: row wrap;
justify-content: center;
}
&__linkitem {
}
&__link {
color: $copy-color;
padding: 0.5em 0.75em;
}
}
</style>

194
src/components/Gallery.vue Normal file
View file

@ -0,0 +1,194 @@
<template>
<div class="gallery">
<div class="gallery__images">
<a
href="#"
class="gallery__prev"
@click.prevent="prev()"
v-show="activeImage > 0"
></a>
<a
href="#"
class="gallery__next"
@click.prevent="next()"
v-show="activeImage < images.length - 1"
></a>
<div class="gallery__viewport" :style="offset">
<slot></slot>
</div>
</div>
<nav class="gallery__navigation">
<ul>
<li v-for="(image, idx) in images" :key="idx">
<a
href="#"
:class="{ active: activeImage === idx }"
@click.prevent="setActive(idx)"
></a>
</li>
</ul>
</nav>
</div>
</template>
<script>
export default {
name: "gallery",
data() {
return {
activeImage: 0,
images: [],
};
},
computed: {
offset() {
return `margin-left: -${this.activeImage * 100}%`;
},
},
methods: {
setActive(index) {
this.activeImage = index;
},
prev() {
if (this.activeImage > 0) {
this.activeImage -= 1;
}
},
next() {
if (this.activeImage < this.images.length - 1) {
this.activeImage += 1;
}
},
},
mounted() {
const sel = ".gallery__viewport .figure";
const elements = this.$el.querySelectorAll(sel);
const images = Array.from(elements);
this.images = images;
},
};
</script>
<style lang="scss">
@import "@/scss/_variables.scss";
@import "@/scss/_mixins.scss";
.gallery {
&__prev,
&__next {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 1em;
height: 1em;
z-index: 1;
border: {
top: 0.125em solid #fff;
right: 0.125em solid #fff;
}
@include mq-desktop {
width: 1.5em;
height: 1.5em;
}
}
&__prev {
left: 1em;
transform: rotate(-135deg);
}
&__next {
right: 1em;
transform: rotate(45deg);
}
&__images {
position: relative;
overflow: hidden;
}
&__viewport {
display: flex;
flex-flow: row nowrap;
align-items: center;
width: 100%;
height: 100%;
transition: 0.3s all ease-in-out;
figure {
flex: 0 0 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
width: 100vw;
height: 100%;
margin: 0;
padding: 0 2em;
@include mq-desktop {
padding: 0 2.5em;
}
}
picture {
flex: 0 1 auto;
text-align: center;
max-height: 80%;
}
figcaption {
flex: 0 0 100%;
text-align: center;
p {
margin: 0.5em auto;
}
}
}
&__navigation {
display: flex;
flex-flow: row wrap;
justify-content: center;
ul {
flex: 0 1 auto;
display: flex;
flex-flow: row wrap;
justify-content: center;
list-style: none;
margin: 1em 0;
padding: 0;
}
li {
flex: 0 1 auto;
padding: 0.375em;
a {
display: block;
width: 0.5em;
height: 0.5em;
border-radius: 1em;
background: rgba(#fff, 0.5);
&.active {
background: #fff;
}
}
}
}
}
</style>

View file

@ -0,0 +1,105 @@
<template>
<nav class="nav">
<ul class="nav__list flex flex--row flex--nowrap flex--center-v">
<li class="nav__item" v-for="(route, idx) in routes" :key="idx">
<router-link class="nav__link" :to="route.path">
{{ route.name }}
</router-link>
<div class="nav__underline"></div>
</li>
</ul>
</nav>
</template>
<script>
export default {
props: {
routes: {
required: true,
type: Array,
},
},
};
</script>
<style lang="scss">
@import "@/scss/base.scss";
.nav {
overflow: auto;
}
.nav__list {
margin: 0;
padding: 0;
list-style-type: none;
z-index: 1;
overflow: auto;
width: 100%;
@include mq-desktop {
justify-content: center;
}
}
.nav__item {
padding: 0.375em;
white-space: nowrap;
}
.nav__link {
display: block;
font-weight: bold;
line-height: 1;
color: $copy-color;
margin-bottom: 0.375em;
text-decoration: none;
&:hover ~ .nav__underline {
&::before,
&::after {
width: 50%;
background-color: $copy-color;
}
}
&.router-link-exact-active {
color: $bg-color-light;
&:hover ~ .nav__underline {
&::before,
&::after {
background-color: $bg-color-light;
}
}
}
}
.nav__underline {
position: relative;
display: block;
width: 100%;
&::before,
&::after {
content: "";
position: absolute;
width: 0;
height: 0.125em;
// background-color: $copy-color;
bottom: 0;
transition: all 0.2s ease-in-out;
}
&::before {
left: 50%;
}
&::after {
right: 50%;
}
}
</style>

View file

@ -0,0 +1,120 @@
<template>
<label class="nsfw-switch" :for="id">
<div>😇</div>
<div class="toggle-wrap">
<input
:checked="modelValue"
@change="$emit('update:modelValue', $event.target.checked)"
type="checkbox"
name="nsfw"
:id="id"
/>
<div class="toggle"></div>
</div>
<div>😈</div>
</label>
</template>
<script>
export default {
props: {
modelValue: Boolean,
id: { type: String, required: true },
},
};
</script>
<style lang="scss">
@import "@/scss/base.scss";
.nsfw-switch {
font-family: "apple color emoji", "segoe ui emoji", "noto color emoji",
"android emoji", "emojisymbols", "emojione mozilla", "twemoji mozilla",
"segoe ui symbol";
padding: 0.5em;
display: inline-flex;
justify-content: center;
align-items: center;
align-content: center;
> div {
flex: 0 1 auto;
align-self: center;
line-height: 1;
text-align: center;
}
.toggle-wrap {
margin: 0 0.5em;
}
.toggle {
position: relative;
display: inline-block;
width: 2.3em;
height: 1.3em;
background-color: #e6e6e6;
border-radius: 1.15em;
vertical-align: text-bottom;
transition: all 0.3s linear;
&::before {
content: "";
position: absolute;
left: 0;
width: 2.1em;
height: 1.1em;
background-color: #fff;
border-radius: 0.55em;
transform: translate3d(0.1em, 0.1em, 0) scale3d(1, 1, 1);
transition: all 0.25s linear;
}
&::after {
content: "";
position: absolute;
left: 0;
width: 1.1em;
height: 1.1em;
background-color: #fff;
border-radius: 0.55em;
box-shadow: 0 0.1em 0.1em rgba(0, 0, 0, 0.24);
transform: translate3d(0.1em, 0.1em, 0);
transition: all 0.2s ease-in-out;
}
}
&:active {
.toggle::after {
width: 1.4em;
transform: translate3d(0.1em, 0.1em, 0);
}
input {
&:checked + .toggle::after {
transform: translate3d(0.8em, 0.1em, 0);
}
}
}
input {
position: absolute;
opacity: 0;
pointer-events: none;
&:checked + .toggle {
background-color: $bg-color-light;
&::before {
transform: translate3d(0.9em, 0.1em, 0) scale3d(0, 0, 0);
}
&::after {
transform: translate3d(1.1em, 0.1em, 0);
}
}
}
}
</style>

View file

@ -0,0 +1,117 @@
<template>
<div class="nsfw-warning">
<div class="nsfw-warning__background"></div>
<div class="nsfw-warning__message">
<div>
<h2><slot name="heading"></slot></h2>
<p><slot name="message"></slot></p>
<div class="btn-container">
<a href="#" class="btn positive" @click.prevent="confirmNsfw(true)">
<slot name="yes"></slot>
</a>
<a href="#" class="btn negative" @click.prevent="confirmNsfw(false)">
<slot name="no"></slot>
</a>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
confirmNsfw(input) {
this.$root.nsfw = input;
this.$root.isConfirmedHorny = input;
this.$root.isWarn = false;
},
},
};
</script>
<style lang="scss">
@import "@/scss/_variables.scss";
@import "@/scss/_mixins.scss";
.nsfw-warning {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9001;
backdrop-filter: blur(1em);
background-color: rgba(#000, 0.5);
display: flex;
flex-flow: row nowrap;
justify-content: center;
padding: 2em;
text-align: center;
&__background {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
&__message {
flex: 0 1 30em;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-content: center;
margin: auto;
border: 0.25em solid $bg-color-warning;
border-radius: 1em;
padding: 1em;
z-index: 9002;
background-color: $bg-color-dark;
> * {
flex: 0 1 100%;
}
}
}
.btn-container {
display: flex;
flex-flow: row wrap;
justify-content: space-around;
align-items: center;
}
.btn {
flex: 0 1 100%;
background-color: $bg-color-light;
border-radius: 0.25em;
font-size: 1.5em;
font-weight: bold;
padding: 0.25em 0.5em;
margin: 0 0 1em 0;
text-decoration: none;
@include mq-desktop {
flex: 0 1 100%;
}
&.positive {
background-color: green;
}
&.negative {
background-color: red;
}
}
</style>

32
src/components/Prose.vue Normal file
View file

@ -0,0 +1,32 @@
<template>
<div class="prose">
<slot name="default"></slot>
</div>
</template>
<style lang="scss">
@import "@/scss/base.scss";
.prose {
padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
h1,
h2,
h3,
p,
.quickfacts {
max-width: 55rem;
margin: {
left: 1rem;
right: 1rem;
}
@media (min-width: 55em) {
margin: {
left: auto;
right: auto;
}
}
}
}
</style>

View file

@ -1,94 +1,88 @@
<script setup lang="ts">
interface Props {
cols?: number
}
defineProps<Props>()
</script>
<template>
<details class="quickfacts">
<summary class="quickfacts__head">Quickfacts</summary>
<div class="quickfacts__list" :class="[`cols-${cols}`]">
<div class="quickfacts" :class="{ open: isExpanded }">
<h4 class="quickfacts__head" @click.prevent="toggle">Quickfacts</h4>
<div class="quickfacts__list">
<slot></slot>
</div>
</details>
</div>
</template>
<script>
export default {
data() {
return {
isExpanded: false,
};
},
methods: {
toggle() {
this.isExpanded = !this.isExpanded;
},
},
};
</script>
<style lang="scss">
@import "@/scss/base.scss";
.quickfacts {
border-radius: 1em;
overflow: hidden;
margin: 1em 0;
position: relative;
background: var(--quickfacts-background);
margin: 1rem 0;
border-radius: 1rem;
box-shadow: var(--container-box-shadow);
overflow: hidden;
transition: 0.3s all ease-in-out;
&:before {
position: absolute;
content: "";
display: block;
content: '';
position: absolute;
top: 1.375rem;
right: 1.375rem;
top: 1em;
right: 1em;
transform: rotate(180deg);
transition: 0.3s all ease-in-out;
border: {
right: 0.625rem solid transparent;
bottom: 0.625rem solid #fff;
left: 0.625rem solid transparent;
right: 0.625em solid transparent;
bottom: 0.625em solid #fff;
left: 0.625em solid transparent;
}
}
&[open]:before {
&.open {
.quickfacts__head {
background-color: $bg-color-light;
}
.quickfacts__list {
max-height: 17em;
padding: 1.5rem;
}
&:before {
transform: rotate(0deg);
}
}
&__head {
font-family: var(--font-family-headings);
font-size: 1.125rem;
list-style: none;
background-color: $bg-color-dark;
margin: 0;
border: 0;
padding: 0.75rem 1.5rem;
transition: 0.3s all ease-in-out;
cursor: pointer;
&::-webkit-details-marker {
display: none;
}
}
&__list {
border-top: 0.125rem solid var(--color-quickfacts-border);
padding: 1.5rem;
&.cols-2 ul {
columns: var(--quickfacts-cols-double);
}
&.cols-3 ul {
columns: var(--quickfacts-cols-triple);
}
&.cols-4 ul {
columns: var(--quickfacts-cols-quadruple);
}
background-color: rgba($bg-color-dark, 0.5);
max-height: 0em;
padding: 0 1.5rem;
transition: 0.3s all ease-in-out;
ul {
margin: 0;
padding: 0 0.5rem;
}
li {
margin: 0 0 0 1rem;
padding: 0;
padding-left: 1.25em;
}
}
}

View file

@ -1,79 +0,0 @@
<script setup lang="ts">
interface Props {
positive?: boolean
negative?: boolean
href?: string
download?: boolean | any
}
defineProps<Props>()
</script>
<template>
<a
class="btn"
:class="{ positive: positive, negative: negative }"
:href="href"
:[download]="download"
>
<slot></slot>
</a>
</template>
<style lang="scss">
.btn {
position: relative;
top: 0;
background-color: var(--color-button);
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);
}
&.positive {
background-color: #259410;
box-shadow: 0 0.5rem 0 0 #1a660b;
&:hover {
box-shadow: 0 0.75rem 0 0 #1a660b;
}
&:active {
box-shadow: 0 0.25rem 0 0 #1a660b;
}
}
&.negative {
background-color: #ae1414;
box-shadow: 0 0.5rem 0 0 #800f0f;
&:hover {
box-shadow: 0 0.75rem 0 0 #800f0f;
}
&:active {
box-shadow: 0 0.25rem 0 0 #800f0f;
}
}
}
</style>

View file

@ -1,223 +0,0 @@
<script setup lang="ts">
import { inject } from 'vue'
import { nsfwKey, showModalKey } from '@/keys'
import RefToggle from '@/components/RefToggle.vue'
interface Props {
cornerText?: boolean
polaroidBorder?: boolean
dropshadow?: boolean
nsfw?: boolean
id: string
}
const isNsfw = inject<boolean>(nsfwKey, false)
const showModal = inject<Function>(showModalKey, Function)
defineProps<Props>()
</script>
<template>
<figure class="figure">
<div
class="figure__border"
:class="{
'figure__border--polaroid': polaroidBorder,
'figure__border--cornertext': cornerText
}"
>
<template v-if="!nsfw || isNsfw">
<div class="figure__image" :class="{ 'figure__image--dropshadow': dropshadow }">
<slot name="img"></slot>
</div>
</template>
<template v-else>
<div class="figure__cencor">
<div class="figure__tape"></div>
<div class="figure__tape"></div>
<div class="figure__tape"></div>
<div class="figure__tape"></div>
<div class="figure__reveal">
<p>🔥 Here be spicy dragons 🌶</p>
<RefToggle
class="figure__toggle"
:id="id"
v-model="isNsfw"
@click.prevent="showModal()"
>
<template #off>😇</template>
<template #on>😈</template>
</RefToggle>
</div>
</div>
</template>
<template v-if="!nsfw || isNsfw">
<figcaption class="figure__meta">
<div class="caption">
<slot name="caption"></slot>
</div>
<div class="copyright">© <slot name="copyright"></slot></div>
</figcaption>
</template>
</div>
</figure>
</template>
<style lang="scss">
.figure {
display: flex;
flex-flow: row nowrap;
justify-content: center;
text-align: center;
margin: 1em auto;
padding: 0 var(--container-spacing-right-safe) 0 var(--container-spacing-left-safe);
&__border {
display: flex;
flex-flow: column nowrap;
justify-content: center;
margin: auto;
&--polaroid {
margin: 1em auto;
padding: 1em;
box-shadow: inset 0 0 1em rgba(0, 0, 0, 0.7), 0 0 1em rgba(0, 0, 0, 0.7);
border-radius: 0.325em;
background-color: #fff;
}
}
&__border--cornertext {
position: relative;
}
&__border--cornertext img,
&__border--cornertext &__cencor {
margin: 1rem 0;
border-radius: 1rem;
filter: drop-shadow(0 0 0.625rem black);
}
&__border--cornertext &__meta {
position: absolute;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.7);
font-size: 0.75rem;
margin: 0 0 1.35rem 0;
border-radius: 1em 0 1rem 0;
padding: 0.25rem 0.75rem;
.caption,
.copyright {
display: inline;
}
.caption {
margin: 0 0.125rem 0 0;
}
}
&__border--polaroid &__meta {
font-family: 'Permanent Marker', fantasy;
color: var(--color-figure-polaroid-text);
max-width: 35rem;
margin: 0.5rem auto;
* {
color: inherit;
}
}
&__image {
flex: 1 0 auto;
&--dropshadow {
filter: drop-shadow(0.5rem 0.25rem 0.375rem #000);
}
img {
max-width: 100%;
max-height: 35rem;
}
}
&__meta {
flex: 0 0 auto;
}
&__cencor {
flex: 1 0 auto;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
padding: 0;
width: var(--figure-cencor-width);
height: var(--figure-cencor-height);
max-width: 35rem;
max-height: 70rem;
position: relative;
background-color: var(--figure-cencor-background-color);
overflow: hidden;
}
&__toggle {
position: relative;
padding: 0;
}
&__tape {
position: absolute;
left: -1rem;
right: -1rem;
top: 0;
transform: rotate(0deg);
height: 1rem;
background-image: repeating-linear-gradient(
-55deg,
#000,
#000 0.75rem,
#ffb101 0.75rem,
#ffb101 1.5rem
);
&:nth-child(1) {
top: 10%;
transform: rotate(5deg);
}
&:nth-child(2) {
top: 15%;
transform: rotate(-10deg);
}
&:nth-child(3) {
top: 75%;
transform: rotate(-15deg);
}
&:nth-child(4) {
top: 85%;
transform: translate(-5rem, -2rem) rotate(40deg);
}
}
}
</style>

View file

@ -1,197 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { debounce } from '@/helpers'
const activeImage = ref(0)
const images = ref<Element[]>([])
const element = document.createElement('div')
const galleryViewport = ref<HTMLElement>(element)
const galleryItemWidth = ref<number>(1)
const resizeObserverCallback = (entries: ResizeObserverEntry[]): void => {
for (const entry of entries) {
galleryItemWidth.value = entry.contentRect.width
}
}
const resizeObserver = new ResizeObserver(debounce(resizeObserverCallback, 1000))
const setActiveImage = (index: number): void => {
activeImage.value = index
galleryViewport.value.scrollTo({
left: galleryItemWidth.value * index,
behavior: 'smooth'
})
}
const getActiveImage = (gallery: HTMLElement, itemWidth: number): number => {
return gallery.scrollLeft / itemWidth
}
const prev = (): void => {
if (activeImage.value > 0) {
galleryViewport.value.scrollBy({
left: galleryItemWidth.value * -1,
behavior: 'smooth'
})
}
}
const next = (): void => {
if (activeImage.value < images.value.length - 1) {
galleryViewport.value.scrollBy({
left: galleryItemWidth.value,
behavior: 'smooth'
})
}
}
const onScroll = (): void => {
const newImg = Math.floor(getActiveImage(galleryViewport.value, galleryItemWidth.value))
setActiveImage(newImg)
}
onMounted(() => {
resizeObserver.observe(galleryViewport.value)
images.value = Array.from(galleryViewport.value.children)
galleryItemWidth.value = galleryViewport.value.scrollWidth / images.value.length
galleryViewport.value.addEventListener('scroll', debounce(onScroll, 500))
})
</script>
<template>
<div class="gallery">
<div class="gallery__images">
<a href="#" class="gallery__prev" @click.prevent="prev()" v-show="activeImage > 0"></a>
<a
href="#"
class="gallery__next"
@click.prevent="next()"
v-show="activeImage < images.length - 1"
></a>
<div class="gallery__viewport" ref="galleryViewport">
<slot></slot>
</div>
</div>
<nav class="gallery__navigation">
<ul>
<li v-for="(image, idx) in images" :key="idx">
<a
href="#"
:class="{ active: activeImage === idx }"
@click.prevent="setActiveImage(idx)"
></a>
</li>
</ul>
</nav>
</div>
</template>
<style lang="scss">
.gallery {
&__prev,
&__next {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: var(--gallery-size);
height: var(--gallery-size);
z-index: 1;
border: {
top: 0.125rem solid #fff;
right: 0.125rem solid #fff;
}
}
&__prev {
left: var(--gallery-arrow-position);
transform: rotate(-135deg);
}
&__next {
right: var(--gallery-arrow-position);
transform: rotate(45deg);
}
&__images {
position: relative;
overflow: hidden;
}
&__viewport {
display: flex;
flex-flow: row nowrap;
align-items: center;
width: 100%;
height: 100%;
overflow: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
transition: 0.3s all ease-in-out;
&::-webkit-scrollbar {
display: none;
}
}
.figure {
margin: 0;
padding: var(--gallery-image-padding);
flex: 1 0 100%;
scroll-snap-align: center;
&__meta {
text-align: center;
p {
margin: 0.5rem auto;
}
}
}
&__navigation {
display: flex;
flex-flow: row wrap;
justify-content: center;
ul {
flex: 0 1 auto;
display: flex;
flex-flow: row wrap;
justify-content: center;
list-style: none;
margin: 1rem 0;
padding: 0;
}
li {
flex: 0 1 auto;
padding: 0.375em;
a {
display: block;
width: 0.5em;
height: 0.5em;
border-radius: 1em;
background: rgba(#fff, 0.5);
&.active {
background: #fff;
}
}
}
}
}
</style>

View file

@ -1,98 +0,0 @@
<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(--modal-background);
color: var(--color-text);
width: var(--modal-width);
margin: auto;
border: 0.25rem solid var(--color-modal-border);
border-radius: 1rem;
padding: 1rem;
overflow: auto;
animation: fade-in 1s;
&::backdrop {
backdrop-filter: blur(1rem);
background-color: rgba(0, 0, 0, 0.5);
animation: fade-in 1s;
}
&__content {
display: flex;
flex-flow: column nowrap;
justify-content: center;
text-align: center;
gap: 1.5rem;
> * {
flex: 1 1 auto;
}
}
&__heading {
margin: 1.875rem 0 0 0;
}
&__message {
flex: 1 1 100%;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
</style>

View file

@ -1,127 +0,0 @@
<script setup lang="ts">
import { computed } from 'vue'
interface Props {
modelValue: boolean
id: string
name?: string
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const checked = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>
<template>
<label :for="id" class="toggle">
<div class="toggle__label">
<slot name="off"></slot>
</div>
<div class="toggle__input">
<input type="checkbox" :name="name" :id="id" v-model="checked" />
<div class="toggle__inner"></div>
</div>
<div class="toggle__label">
<slot name="on"></slot>
</div>
</label>
</template>
<style lang="scss">
.toggle {
font-family: 'apple color emoji', 'noto color emoji', 'segoe ui emoji', 'android emoji',
'emojisymbols', 'emojione mozilla', 'twemoji mozilla', 'segoe ui symbol';
padding: 0.5em;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
&__label,
&__toggle {
flex: 0 1 auto;
align-self: center;
line-height: 1;
text-align: center;
}
&__input {
margin: 0 0.5em;
}
&__input input:checked + &__inner {
background-color: var(--color-toggle);
&:before {
transform: translate3d(0.9em, 0.1em, 0) scale3d(0, 0, 0);
}
&:after {
transform: translate3d(1.1em, 0.1em, 0);
}
}
&__inner {
position: relative;
display: inline-block;
width: 2.3em;
height: 1.3em;
background-color: #e6e6e6;
border-radius: 1.15em;
vertical-align: text-bottom;
transition: all 0.3s linear;
&:before,
&:after {
content: '';
position: absolute;
left: 0;
height: 1.1em;
background-color: #fff;
border-radius: 0.55em;
}
&:before {
width: 2.1em;
transform: translate3d(0.1em, 0.1em, 0) scale3d(1, 1, 1);
transition: all 0.25s linear;
}
&:after {
width: 1.1em;
box-shadow: 0 0.1em 0.1em rgba(0, 0, 0, 0.24);
transform: translate3d(0.1em, 0.1em, 0);
transition: all 0.2s ease-in-out;
}
}
input {
position: absolute;
opacity: 0;
pointer-events: none;
}
&:active &__inner:after {
width: 1.4em;
transform: translate3d(0.1em, 0.1em, 0);
}
&:active input:checked + &__inner:after {
transform: translate3d(0.8em, 0.1em, 0);
}
}
</style>

View file

@ -1,25 +0,0 @@
<template>
<footer class="footer">
<slot></slot>
</footer>
</template>
<style lang="scss">
.footer {
background: url(@/assets/subtle-prism.svg) var(--color-background-footer);
background-blend-mode: multiply;
padding: var(--footer-padding);
text-align: center;
p {
text-align: center;
margin: 0;
+ p {
margin: 0.5em auto 0 auto;
}
}
}
</style>

View file

@ -1,30 +0,0 @@
<template>
<header class="header">
<slot></slot>
</header>
</template>
<style lang="scss">
.header {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
position: sticky;
top: var(--container-spacing-top-safe);
right: var(--container-spacing-right-safe);
left: var(--container-spacing-left-safe);
background: var(--header-background);
max-width: 70rem;
margin: var(--header-margin);
border-radius: 0.5rem;
padding: 0.5rem;
box-shadow: var(--container-box-shadow);
z-index: 2;
}
</style>

View file

@ -1,93 +0,0 @@
<script setup lang="ts">
import { RouterLink } from 'vue-router'
import router from '@/router'
</script>
<template>
<nav class="nav">
<ul class="nav__list">
<li class="nav__item" v-for="(route, idx) in router.options.routes" :key="idx">
<RouterLink class="nav__link" :to="route.path">
{{ route.name }}
</RouterLink>
<div class="nav__underline"></div>
</li>
</ul>
</nav>
</template>
<style lang="scss">
.nav {
overflow: auto;
&__list {
display: flex;
flex-flow: row nowrap;
justify-content: var(--navigation-justify-content);
align-items: center;
width: 100%;
margin: 0;
padding: 0;
list-style-type: none;
overflow: auto;
}
&__item {
padding: 0.375rem;
white-space: nowrap;
}
&__link {
display: block;
font-weight: bold;
line-height: 1;
color: var(--color-text);
margin-bottom: 0.375em;
text-decoration: none;
text-transform: capitalize;
&.router-link-exact-active {
color: var(--color-text);
}
}
&__link:hover ~ &__underline,
&__link.router-link-exact-active ~ &__underline {
&:before,
&:after {
width: 50%;
background-color: var(--color-text);
}
}
&__underline {
position: relative;
display: block;
width: 100%;
&:before,
&:after {
content: '';
position: absolute;
bottom: 0;
width: 0;
height: 0.125rem;
transition: all 0.2s ease-in-out;
}
&:before {
left: 50%;
}
&:after {
right: 50%;
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show more