Compare commits
122 commits
Author | SHA1 | Date | |
---|---|---|---|
|
15d487ec6f | ||
|
d716e192bb | ||
|
6aa34c1648 | ||
|
34823665c6 | ||
|
134e2c79cc | ||
|
b0abfd8311 | ||
|
61cd15fd5b | ||
|
f3f94be6ae | ||
|
61147be693 | ||
|
6a1474eb52 | ||
|
f4b1003801 | ||
|
5d94323bdd | ||
|
d2774e8150 | ||
|
89831a64a2 | ||
|
4c8d576f13 | ||
|
0c8a3b0348 | ||
|
0335006ee5 | ||
|
07bd197c29 | ||
|
a0b2062137 | ||
|
d5cf84e592 | ||
|
cd9c1d950d | ||
|
665f2c6b35 | ||
|
30a573e9cf | ||
|
ddde6df30b | ||
|
d5703cc274 | ||
|
778142c4c1 | ||
|
d984651fc8 | ||
|
9a529b62fb | ||
|
c143956e9f | ||
|
120a1a03e3 | ||
|
08e01502c5 | ||
|
314255dc31 | ||
|
1b036d3278 | ||
|
b450849075 | ||
|
f100c524af | ||
|
d196c1e680 | ||
|
f147510c04 | ||
|
6cf6e6d045 | ||
|
ff665a6cea | ||
|
a2e2c1f791 | ||
|
0b4813e285 | ||
|
4853e1ec63 | ||
|
de3862bf77 | ||
|
6094a2a559 | ||
|
939610ed61 | ||
|
5ef3d6c0f9 | ||
|
35562692e4 | ||
|
5f65a341a0 | ||
|
e3f2e0c256 | ||
|
51e72e2021 | ||
|
b8c9d8de17 | ||
|
cc664a764d | ||
|
d0f9434700 | ||
|
b9fe7113ed | ||
|
0e225f95c9 | ||
|
8e0756f166 | ||
|
e67a220223 | ||
|
dd70061798 | ||
|
c7444256f1 | ||
|
3c8b726d83 | ||
|
a670952e15 | ||
|
d6f94c26d4 | ||
|
62795740b3 | ||
|
6b0acce446 | ||
|
a0182fe447 | ||
|
fe785f6ed3 | ||
|
52d2f12b75 | ||
|
7a3a58d8fc | ||
|
21df633e9e | ||
|
014451ffa0 | ||
|
6ecba14f6f | ||
|
9893373a43 | ||
|
d84c415b22 | ||
|
c77854667b | ||
|
2c4c07441b | ||
|
c834b7c49e | ||
|
d000c4a4fb | ||
|
6d9515498f | ||
|
88e437d001 | ||
|
fb413a5fba | ||
|
9aa5579bde | ||
|
c7baf62833 | ||
|
092fc92658 | ||
|
ec9e975bda | ||
|
9dcda9d3dd | ||
|
05b8e0c410 | ||
|
9ddc4e5a8c | ||
|
7670634cda | ||
|
a9b6b815e8 | ||
|
3a1a5942df | ||
|
a78ad22578 | ||
|
40f5b32970 | ||
|
a729113b71 | ||
|
600a82d3f2 | ||
|
eb749e1796 | ||
|
267830b15d | ||
|
c1b7bdbbb4 | ||
|
6e2a633b45 | ||
|
4384759616 | ||
|
32c63efeaa | ||
|
81941a9e45 | ||
|
b37e067efd | ||
|
af4427cf3d | ||
|
e902589427 | ||
|
5cf33f6dfa | ||
|
3ba5e0aa2b | ||
|
97ff935b13 | ||
|
313d6f2302 | ||
|
7aeecdb656 | ||
|
baf6161d95 | ||
|
579e57f631 | ||
|
b63a14d8ce | ||
|
5b5c027ea6 | ||
|
6494354a6d | ||
|
90ef5eaf06 | ||
|
10f9ae340c | ||
|
c6bb436ad8 | ||
|
a649fdae0b | ||
|
fa7ff4ac89 | ||
|
81ba54ef10 | ||
|
3d2d876b98 | ||
|
c682e2b38b |
|
@ -1,3 +1,3 @@
|
|||
> 1%
|
||||
defaults
|
||||
>1% and not dead
|
||||
last 2 versions
|
||||
not dead
|
||||
|
|
15
.eslintrc.cjs
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* 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
|
@ -1,14 +0,0 @@
|
|||
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
|
@ -1,23 +1,30 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"esversion": 9
|
||||
}
|
8
.prettierrc.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
7
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"Vue.volar",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
15
.vscode/sftp.json
vendored
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
}
|
57
README.md
|
@ -1,24 +1,55 @@
|
|||
# vue3-test
|
||||
# Sebin Reference Page
|
||||
|
||||
## Project setup
|
||||
```
|
||||
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
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
44
card/header/furaffinity/index.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
<!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>
|
139
card/header/furaffinity/style.css
Normal file
|
@ -0,0 +1,139 @@
|
|||
@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;
|
||||
}
|
44
card/header/mastodon/index.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
<!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>
|
139
card/header/mastodon/style.css
Normal file
|
@ -0,0 +1,139 @@
|
|||
@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;
|
||||
}
|
44
card/header/twitter/index.html
Normal file
|
@ -0,0 +1,44 @@
|
|||
<!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>
|
143
card/header/twitter/style.css
Normal file
|
@ -0,0 +1,143 @@
|
|||
@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;
|
||||
}
|
22
card/index.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="flex">
|
||||
<div class="image">
|
||||
<img src="../src/assets/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>
|
112
card/style.css
Normal file
|
@ -0,0 +1,112 @@
|
|||
@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
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
30
index.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<!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>
|
34567
package-lock.json
generated
50
package.json
|
@ -1,32 +1,38 @@
|
|||
{
|
||||
"name": "sebin-reference",
|
||||
"version": "0.8.1",
|
||||
"version": "0.10.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
"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/"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"normalize.css": "^8.0.1",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
"vue": "^3.4.38",
|
||||
"vue-router": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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"
|
||||
"@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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
RewriteRule ^index\.html$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /index.html [L]
|
||||
RewriteRule . /sebin/index.html [L]
|
||||
</IfModule>
|
||||
|
|
|
@ -1,17 +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,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 id="app">
|
||||
<noscript>
|
||||
<strong>Sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 377 KiB |
BIN
public/preview.png
Normal file
After Width: | Height: | Size: 2.7 MiB |
BIN
public/sebin-ref-full-NSFW-hires.jpg
Executable file → Normal file
Before Width: | Height: | Size: 9.7 MiB After Width: | Height: | Size: 3.3 MiB |
BIN
public/sebin-ref-full-SFW-hires.jpg
Executable file → Normal file
Before Width: | Height: | Size: 9.5 MiB After Width: | Height: | Size: 3.2 MiB |
235
src/App.vue
|
@ -1,158 +1,99 @@
|
|||
<template>
|
||||
<ref-header>
|
||||
<img
|
||||
class="nav-logo"
|
||||
src="@/assets/sebin-smug-icon.png"
|
||||
alt="Sebin Avatar"
|
||||
/>
|
||||
<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'
|
||||
|
||||
<navigation :routes="routes" />
|
||||
</ref-header>
|
||||
const isNsfw = ref(false)
|
||||
const isConfirmedHorny = ref(false)
|
||||
|
||||
const nsfwmodal = ref<InstanceType<typeof RefModal>>()
|
||||
|
||||
const showModal = (): void => {
|
||||
if (!isConfirmedHorny.value) {
|
||||
nsfwmodal.value?.showModal()
|
||||
|
||||
setTimeout(() => {
|
||||
isNsfw.value = false
|
||||
}, 1)
|
||||
} else {
|
||||
isNsfw.value = !isNsfw.value
|
||||
}
|
||||
}
|
||||
|
||||
const modalResult = (value: boolean): void => {
|
||||
isNsfw.value = value
|
||||
isConfirmedHorny.value = value
|
||||
nsfwmodal.value?.close()
|
||||
}
|
||||
|
||||
provide(modalResultKey, modalResult)
|
||||
provide(nsfwKey, isNsfw)
|
||||
provide(showModalKey, showModal)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RefModal id="nsfw-warning" ref="nsfwmodal">
|
||||
<template #heading>
|
||||
⚠️⚠️⚠️<br />
|
||||
Whoa, Nelly!
|
||||
</template>
|
||||
|
||||
<template #message>
|
||||
By enabling NSFW mode you confirm that you are of legal age to view adult content.
|
||||
</template>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<SiteNavigation />
|
||||
</SiteHeader>
|
||||
|
||||
<main>
|
||||
<router-view />
|
||||
<RouterView />
|
||||
</main>
|
||||
|
||||
<ref-footer>
|
||||
<SiteFooter>
|
||||
<p>v{{ version }} © {{ new Date().getFullYear() }} Sebin Nyshkim</p>
|
||||
<p>
|
||||
Background Pattern ©
|
||||
<a href="https://www.svgbackgrounds.com/">SVG Backgrounds</a>
|
||||
</p>
|
||||
</ref-footer>
|
||||
</SiteFooter>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Navigation from "@/components/Navigation.vue";
|
||||
import RefHeader from "@/components/Header.vue";
|
||||
import RefFooter from "@/components/Footer.vue";
|
||||
|
||||
export default {
|
||||
components: { Navigation, RefHeader, RefFooter },
|
||||
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;
|
||||
document.body.classList.toggle("scroll-lock");
|
||||
|
||||
setTimeout(() => {
|
||||
this.nsfw = false;
|
||||
}, 1);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/base.scss";
|
||||
@import "~normalize.css";
|
||||
|
||||
#app {
|
||||
color: $copy-color;
|
||||
font-size: 1.125em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
transition: all ease-in-out 0.25s;
|
||||
|
||||
@include mq-desktop {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
@include mq-bigscreen {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
background: url("/subtle-prism.svg");
|
||||
mix-blend-mode: multiply;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
&:after {
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
$bg-color-lighter 5%,
|
||||
transparent 50%
|
||||
),
|
||||
radial-gradient(
|
||||
circle at top left,
|
||||
$bg-color-light 5%,
|
||||
$bg-color-dark 100%
|
||||
);
|
||||
|
||||
z-index: -2;
|
||||
|
||||
@include theme(dark) {
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
darken($bg-color-lighter, 30%) 5%,
|
||||
transparent 50%
|
||||
),
|
||||
radial-gradient(
|
||||
circle at top left,
|
||||
darken($bg-color-light, 10%) 5%,
|
||||
darken($bg-color-dark, 10%) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-logo {
|
||||
display: block;
|
||||
margin: 0 0.5em 0 0.25em;
|
||||
height: 2em;
|
||||
border: 0.125em solid #fff;
|
||||
border-radius: 100%;
|
||||
box-shadow: 0.125em 0.125em 0.5em rgba(#000, 0.7);
|
||||
}
|
||||
|
||||
main {
|
||||
min-height: 100vh;
|
||||
padding: 2em 0 1em 0;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin: 0;
|
||||
|
||||
& + p {
|
||||
margin: 0.5em auto 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
BIN
src/assets/fonts/dosis/dosis-bold-latin.woff2
Normal file
BIN
src/assets/fonts/dosis/dosis-regular-latin.woff2
Normal file
19
src/assets/fonts/dosis/dosis.css
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* 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;
|
||||
}
|
||||
|
BIN
src/assets/fonts/exo/exo-black-italic-latin.woff2
Normal file
BIN
src/assets/fonts/exo/exo-black-latin.woff2
Normal file
BIN
src/assets/fonts/exo/exo-light-italic-latin.woff2
Normal file
BIN
src/assets/fonts/exo/exo-light-latin.woff2
Normal file
37
src/assets/fonts/exo/exo.css
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* 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;
|
||||
}
|
||||
|
10
src/assets/fonts/permanent-marker/permanent-marker.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* 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;
|
||||
}
|
||||
|
BIN
src/assets/fonts/zilla-slab/zilla-slab-bold-latin.woff2
Normal file
10
src/assets/fonts/zilla-slab/zilla-slab.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* 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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 551 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 524 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 656 KiB |
0
src/assets/refs/clothes/casual/fullbody.png
Executable file → Normal file
Before Width: | Height: | Size: 784 KiB After Width: | Height: | Size: 784 KiB |
BIN
src/assets/refs/clothes/lazy/fullbody.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 42 KiB |
BIN
src/assets/refs/clothes/lazy/undies.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 734 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 3.9 MiB |
Before Width: | Height: | Size: 717 KiB |
BIN
src/assets/refs/muscle/muscle-ref1.png
Normal file
After Width: | Height: | Size: 14 MiB |
Before Width: | Height: | Size: 432 KiB After Width: | Height: | Size: 9.2 MiB |
Before Width: | Height: | Size: 151 KiB |
BIN
src/assets/refs/muscle/muscle-ref11.png
Normal file
After Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 376 KiB |
BIN
src/assets/refs/muscle/muscle-ref12.png
Normal file
After Width: | Height: | Size: 3.6 MiB |
Before Width: | Height: | Size: 657 KiB |
BIN
src/assets/refs/muscle/muscle-ref2.png
Normal file
After Width: | Height: | Size: 8.3 MiB |
Before Width: | Height: | Size: 560 KiB |
BIN
src/assets/refs/muscle/muscle-ref3.png
Normal file
After Width: | Height: | Size: 17 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 16 MiB |
Before Width: | Height: | Size: 393 KiB After Width: | Height: | Size: 589 KiB |
Before Width: | Height: | Size: 512 KiB |
BIN
src/assets/refs/muscle/muscle-ref6.png
Normal file
After Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 867 KiB |
BIN
src/assets/refs/muscle/muscle-ref7.tiff
Normal file
Before Width: | Height: | Size: 378 KiB |
BIN
src/assets/refs/muscle/muscle-ref8.png
Normal file
After Width: | Height: | Size: 4 MiB |
Before Width: | Height: | Size: 619 KiB After Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.8 MiB |
BIN
src/assets/refs/upper-body-ref.png
Normal file
After Width: | Height: | Size: 14 MiB |
67
src/components/AttackItem.vue
Normal file
|
@ -0,0 +1,67 @@
|
|||
<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>
|
18
src/components/AttackList.vue
Normal file
|
@ -0,0 +1,18 @@
|
|||
<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>
|
|
@ -1,57 +0,0 @@
|
|||
<template>
|
||||
<a
|
||||
class="btn"
|
||||
:href="href"
|
||||
:download="href.slice(href.lastIndexOf('/') + 1)"
|
||||
v-if="download"
|
||||
>
|
||||
<slot></slot>
|
||||
</a>
|
||||
<a class="btn" :href="href" v-else><slot></slot></a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
href: String,
|
||||
download: Boolean,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.scss";
|
||||
|
||||
.btn {
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em 1em;
|
||||
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
||||
border-radius: 0.25em;
|
||||
|
||||
transition: all 0.1s ease-out;
|
||||
|
||||
font-weight: bold;
|
||||
background-color: $bg-color-light;
|
||||
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
|
||||
@include button($bg-color-light);
|
||||
|
||||
@include theme(dark) {
|
||||
@include button($bg-color-dark);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
top: -0.25em;
|
||||
}
|
||||
|
||||
&:active {
|
||||
top: 0.25em;
|
||||
}
|
||||
}
|
||||
</style>
|
48
src/components/ButtonGroup.vue
Normal file
|
@ -0,0 +1,48 @@
|
|||
<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>
|
53
src/components/ColorTable.vue
Normal file
|
@ -0,0 +1,53 @@
|
|||
<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>
|
|
@ -1,152 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
interface Props {
|
||||
headings: string[]
|
||||
data: string[][]
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="datatable">
|
||||
<thead class="datatable__head">
|
||||
<tr class="datatable__row">
|
||||
<th
|
||||
class="datatable__heading"
|
||||
v-for="(header, idx) in dataset.headers"
|
||||
:key="idx"
|
||||
>
|
||||
{{ header }}
|
||||
<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 }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<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"
|
||||
:class="{ 'datatable__cell--hex': idx === 1 && isHexValue(row[1]) }"
|
||||
>
|
||||
<template v-if="Array.isArray(cell)">
|
||||
<ul class="col-2">
|
||||
<li v-for="(item, idx) in cell" :key="idx">
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<template v-if="isHexValue(cell)">
|
||||
<a href="#" @click.prevent="copyToClipboard(cell)">
|
||||
{{ cell }}
|
||||
</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ cell }}
|
||||
</template>
|
||||
</template>
|
||||
<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">
|
||||
{{ cell }}
|
||||
</td>
|
||||
<td
|
||||
v-if="isHexValue(row[1])"
|
||||
class="datatable__cell--colorpick"
|
||||
:style="{ backgroundColor: row[1] }"
|
||||
></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DataTable",
|
||||
props: {
|
||||
dataset: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isHexValue(value) {
|
||||
return /^#[0-9a-f]{6}$/i.test(value) ? value : false;
|
||||
},
|
||||
copyToClipboard(value) {
|
||||
navigator.clipboard.writeText(value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.scss";
|
||||
.data-table {
|
||||
table-layout: fixed;
|
||||
|
||||
.datatable {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
@include mq-desktop {
|
||||
max-width: 45rem;
|
||||
}
|
||||
|
||||
@include mq-bigscreen {
|
||||
max-width: 55rem;
|
||||
}
|
||||
|
||||
&__heading,
|
||||
&__cell {
|
||||
padding: 0.25em 0.5em;
|
||||
|
||||
@media (min-width: 35em) {
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@include mq-desktop {
|
||||
&.col-2 {
|
||||
columns: 2 auto;
|
||||
}
|
||||
|
||||
&.col-3 {
|
||||
columns: 3 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 0 0 1em;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__head {
|
||||
color: $copy-color;
|
||||
border-top: 0.0625em solid $sebin-secondary;
|
||||
}
|
||||
|
||||
&__body {
|
||||
border: {
|
||||
top: 0.0625em solid $sebin-secondary;
|
||||
bottom: 0.0625em solid $sebin-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
&__body &__row:hover {
|
||||
background: rgba(#000, 0.3);
|
||||
}
|
||||
|
||||
&__cell {
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&--hex {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
&--colorpick {
|
||||
border: 0.0625em solid #fff;
|
||||
}
|
||||
&__cell:first-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
<template>
|
||||
<figure class="figure">
|
||||
<div
|
||||
class="figure__border"
|
||||
:class="{ 'figure__border--polaroid': polaroidBorder }"
|
||||
>
|
||||
<template v-if="!nsfw || $root.nsfw">
|
||||
<div
|
||||
class="figure__image"
|
||||
:class="{ 'figure__image--dropshadow': dropshadow }"
|
||||
>
|
||||
<slot name="img"></slot>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<div class="figure__reveal">
|
||||
<p>🔥 Here be spicy dragons 🌶</p>
|
||||
|
||||
<nsfw-switch
|
||||
:id="id"
|
||||
v-model="$root.nsfw"
|
||||
@change="$root.showWarning()"
|
||||
/>
|
||||
</div>
|
||||
</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,
|
||||
dropshadow: 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;
|
||||
justify-content: center;
|
||||
|
||||
margin: 1em auto;
|
||||
text-align: center;
|
||||
|
||||
&__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(#000, 0.7), 0 0 1em rgba(#000, 0.7);
|
||||
border-radius: 0.325em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
.figure__meta {
|
||||
margin: 0.5em 0;
|
||||
font-family: "Permanent Marker", fantasy;
|
||||
color: $copy-color-darkgrey;
|
||||
|
||||
* {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__image {
|
||||
flex: 1 0 auto;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 35em;
|
||||
}
|
||||
|
||||
&--dropshadow {
|
||||
filter: drop-shadow(0.5em 0.25em 0.375em #000);
|
||||
}
|
||||
}
|
||||
|
||||
&__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: 50vw;
|
||||
height: 35vh;
|
||||
max-width: 35em;
|
||||
max-height: 70em;
|
||||
position: relative;
|
||||
|
||||
background-color: $bg-color-lighter;
|
||||
overflow: hidden;
|
||||
|
||||
@include mq-desktop {
|
||||
width: 20em;
|
||||
height: 20em;
|
||||
}
|
||||
|
||||
.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: 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(-5em, -2em) rotate(40deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
161
src/components/FilterButton.vue
Normal file
|
@ -0,0 +1,161 @@
|
|||
<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>
|
77
src/components/FilterListTag.vue
Normal file
|
@ -0,0 +1,77 @@
|
|||
<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>
|
127
src/components/FilteredList.vue
Normal file
|
@ -0,0 +1,127 @@
|
|||
<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>
|
|
@ -1,22 +0,0 @@
|
|||
<template>
|
||||
<footer class="footer">
|
||||
<slot></slot>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.scss";
|
||||
|
||||
.footer {
|
||||
background: url("/subtle-prism.svg") $bg-color-dark;
|
||||
background-blend-mode: multiply;
|
||||
|
||||
padding: max(1em, env(safe-area-inset-top)) 0
|
||||
max(1em, env(safe-area-inset-bottom)) 0;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
|
@ -1,188 +0,0 @@
|
|||
<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: 1.5em;
|
||||
transform: rotate(-135deg);
|
||||
|
||||
@include mq-desktop {
|
||||
left: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
&__next {
|
||||
right: 1.5em;
|
||||
transform: rotate(45deg);
|
||||
|
||||
@include mq-desktop {
|
||||
right: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
&__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 {
|
||||
margin: 0;
|
||||
padding: 0 3em;
|
||||
flex: 1 0 100%;
|
||||
|
||||
@include mq-desktop {
|
||||
padding: 0 3.5em;
|
||||
}
|
||||
|
||||
&__meta {
|
||||
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>
|
|
@ -1,65 +0,0 @@
|
|||
<template>
|
||||
<header class="header">
|
||||
<slot></slot>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.scss";
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
position: sticky;
|
||||
top: max(1em, env(safe-area-inset-top));
|
||||
right: max(1em, env(safe-area-inset-right));
|
||||
left: max(1em, env(safe-area-inset-left));
|
||||
|
||||
z-index: 2;
|
||||
|
||||
max-width: 70em;
|
||||
margin: 1em max(1em, env(safe-area-inset-right)) 1em
|
||||
max(1em, env(safe-area-inset-left));
|
||||
padding: 0.5em;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: 0.125em 0.125em 0.5em rgba(#000, 0.7);
|
||||
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
darken($bg-color-lighter, 30%) 20%,
|
||||
transparent 80%
|
||||
),
|
||||
radial-gradient(
|
||||
circle at top left,
|
||||
darken($sebin-secondary, 20%) 5%,
|
||||
darken($sebin-primary, 20%) 100%
|
||||
);
|
||||
|
||||
@include theme(dark) {
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
darken($bg-color-lighter, 35%) 20%,
|
||||
transparent 80%
|
||||
),
|
||||
radial-gradient(
|
||||
circle at top left,
|
||||
darken($sebin-secondary, 35%) 5%,
|
||||
darken($sebin-primary, 35%) 100%
|
||||
);
|
||||
}
|
||||
|
||||
@include theme(dark) {
|
||||
background-color: $bg-color-dark;
|
||||
}
|
||||
|
||||
@media (min-width: 90em) {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,122 +0,0 @@
|
|||
<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">
|
||||
<btn href="#" class="positive" @click.prevent="confirmNsfw(true)">
|
||||
<slot name="yes"></slot>
|
||||
</btn>
|
||||
|
||||
<btn href="#" class="negative" @click.prevent="confirmNsfw(false)">
|
||||
<slot name="no"></slot>
|
||||
</btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import btn from "@/components/Button.vue";
|
||||
|
||||
export default {
|
||||
components: { btn },
|
||||
methods: {
|
||||
confirmNsfw(input) {
|
||||
this.$root.nsfw = input;
|
||||
this.$root.isConfirmedHorny = input;
|
||||
this.$root.isWarn = false;
|
||||
document.body.classList.toggle("scroll-lock");
|
||||
},
|
||||
},
|
||||
};
|
||||
</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;
|
||||
overflow: auto;
|
||||
|
||||
&__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 $sebin-secondary;
|
||||
border-radius: 1em;
|
||||
padding: 1em;
|
||||
|
||||
z-index: 9002;
|
||||
|
||||
@include theme(light) {
|
||||
@include radial-background($bg-color-light, $bg-color-dark);
|
||||
}
|
||||
|
||||
@include theme(dark) {
|
||||
@include radial-background(
|
||||
darken($bg-color-light, 20%),
|
||||
darken($bg-color-dark, 5%)
|
||||
);
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: 0 1 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 0 1 100%;
|
||||
margin: 0.75em 0;
|
||||
|
||||
&.positive {
|
||||
@include button(darken($sebin-eyes, 10%));
|
||||
}
|
||||
|
||||
&.negative {
|
||||
@include button(darken($bg-color-lighter, 20%));
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,35 +0,0 @@
|
|||
<template>
|
||||
<div class="prose">
|
||||
<slot name="default"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_mixins.scss";
|
||||
|
||||
.prose {
|
||||
padding: 0 max(1em, env(safe-area-inset-right)) 0
|
||||
max(1em, env(safe-area-inset-left));
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
p,
|
||||
ul,
|
||||
blockquote,
|
||||
.quickfacts,
|
||||
.btn-group {
|
||||
@include mq-desktop {
|
||||
max-width: 45rem;
|
||||
margin: {
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@include mq-bigscreen {
|
||||
max-width: 55rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,109 +1,93 @@
|
|||
<template>
|
||||
<div class="quickfacts" :class="{ open: isExpanded }">
|
||||
<h4 class="quickfacts__head" @click.prevent="toggle">Quickfacts</h4>
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
cols?: number
|
||||
}
|
||||
|
||||
<div class="quickfacts__list">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isExpanded: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
},
|
||||
},
|
||||
};
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<details class="quickfacts">
|
||||
<summary class="quickfacts__head">Quickfacts</summary>
|
||||
<div class="quickfacts__list" :class="[`cols-${cols}`]">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</details>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.scss";
|
||||
|
||||
.quickfacts {
|
||||
border-radius: 1em;
|
||||
overflow: hidden;
|
||||
margin: 1em 0;
|
||||
position: relative;
|
||||
box-shadow: 0.125em 0.125em 0.5em rgba(#000, 0.7);
|
||||
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
$bg-color-lighter 5%,
|
||||
transparent 50%
|
||||
),
|
||||
radial-gradient(circle at top left, $bg-color-light 5%, $bg-color-dark 100%);
|
||||
background: var(--quickfacts-background);
|
||||
|
||||
@include theme(dark) {
|
||||
background: radial-gradient(
|
||||
circle at bottom right,
|
||||
darken($bg-color-lighter, 30%) 5%,
|
||||
transparent 50%
|
||||
),
|
||||
radial-gradient(
|
||||
circle at top left,
|
||||
darken($bg-color-light, 10%) 5%,
|
||||
darken($bg-color-dark, 10%) 100%
|
||||
);
|
||||
}
|
||||
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;
|
||||
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1.375rem;
|
||||
right: 1.375rem;
|
||||
|
||||
transform: rotate(180deg);
|
||||
transition: 0.3s all ease-in-out;
|
||||
|
||||
border: {
|
||||
right: 0.625em solid transparent;
|
||||
bottom: 0.625em solid #fff;
|
||||
left: 0.625em solid transparent;
|
||||
right: 0.625rem solid transparent;
|
||||
bottom: 0.625rem solid #fff;
|
||||
left: 0.625rem solid transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.open:before {
|
||||
&[open]:before {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
&.open & {
|
||||
&__list {
|
||||
max-height: 25em;
|
||||
border-top: 0.125em solid $sebin-secondary;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
&__head {
|
||||
font-family: var(--font-family-headings);
|
||||
font-size: 1.125rem;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0.75rem 1.5rem;
|
||||
transition: 0.3s all ease-in-out;
|
||||
cursor: pointer;
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__list {
|
||||
max-height: 0em;
|
||||
padding: 0 1.5rem;
|
||||
transition: 0.3s all ease-in-out;
|
||||
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);
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0.5em;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 0 0 1em;
|
||||
margin: 0 0 0 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
|
79
src/components/RefButton.vue
Normal file
|
@ -0,0 +1,79 @@
|
|||
<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>
|
223
src/components/RefFigure.vue
Normal file
|
@ -0,0 +1,223 @@
|
|||
<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>
|
197
src/components/RefGallery.vue
Normal file
|
@ -0,0 +1,197 @@
|
|||
<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>
|
98
src/components/RefModal.vue
Normal file
|
@ -0,0 +1,98 @@
|
|||
<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>
|
|
@ -1,36 +1,48 @@
|
|||
<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 class="nsfw-switch" :for="id">
|
||||
<div class="nsfw-switch__label">😇</div>
|
||||
<div class="nsfw-switch__toggle">
|
||||
<input
|
||||
:checked="modelValue"
|
||||
@change="$emit('update:modelValue', $event.target.checked)"
|
||||
type="checkbox"
|
||||
name="nsfw"
|
||||
:id="id"
|
||||
/>
|
||||
<div class="nsfw-switch__toggle-inner"></div>
|
||||
<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>
|
||||
<div class="nsfw-switch__label">😈</div>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue: Boolean,
|
||||
id: { type: String, required: true },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
|
||||
.nsfw-switch {
|
||||
font-family: "apple color emoji", "segoe ui emoji", "noto color emoji",
|
||||
"android emoji", "emojisymbols", "emojione mozilla", "twemoji mozilla",
|
||||
"segoe ui symbol";
|
||||
.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;
|
||||
|
||||
|
@ -47,23 +59,23 @@ export default {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
&__input {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
& input:checked + &-inner {
|
||||
background-color: $sebin-primary;
|
||||
&__input input:checked + &__inner {
|
||||
background-color: var(--color-toggle);
|
||||
|
||||
&:before {
|
||||
transform: translate3d(0.9em, 0.1em, 0) scale3d(0, 0, 0);
|
||||
}
|
||||
&:before {
|
||||
transform: translate3d(0.9em, 0.1em, 0) scale3d(0, 0, 0);
|
||||
}
|
||||
|
||||
&:after {
|
||||
transform: translate3d(1.1em, 0.1em, 0);
|
||||
}
|
||||
&:after {
|
||||
transform: translate3d(1.1em, 0.1em, 0);
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle-inner {
|
||||
&__inner {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 2.3em;
|
||||
|
@ -75,7 +87,7 @@ export default {
|
|||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 1.1em;
|
||||
|
@ -103,12 +115,12 @@ export default {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:active &__toggle-inner:after {
|
||||
&:active &__inner:after {
|
||||
width: 1.4em;
|
||||
transform: translate3d(0.1em, 0.1em, 0);
|
||||
}
|
||||
|
||||
&:active input:checked + &__toggle-inner:after {
|
||||
&:active input:checked + &__inner:after {
|
||||
transform: translate3d(0.8em, 0.1em, 0);
|
||||
}
|
||||
}
|
25
src/components/SiteFooter.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<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>
|
30
src/components/SiteHeader.vue
Normal file
|
@ -0,0 +1,30 @@
|
|||
<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>
|
|
@ -1,52 +1,43 @@
|
|||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
import router from '@/router'
|
||||
</script>
|
||||
|
||||
<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">
|
||||
<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 }}
|
||||
</router-link>
|
||||
</RouterLink>
|
||||
<div class="nav__underline"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
routes: {
|
||||
required: true,
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/scss/_variables.scss";
|
||||
@import "@/scss/_mixins.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;
|
||||
|
||||
z-index: 1;
|
||||
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
|
||||
@include mq-desktop {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
padding: 0.375em;
|
||||
padding: 0.375rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
@ -54,28 +45,22 @@ export default {
|
|||
display: block;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
color: $copy-color;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 0.375em;
|
||||
text-decoration: none;
|
||||
text-transform: capitalize;
|
||||
|
||||
&.router-link-exact-active {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&__link:hover ~ &__underline {
|
||||
&:before,
|
||||
&:after {
|
||||
width: 50%;
|
||||
background-color: $copy-color;
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
&__link:hover ~ &__underline,
|
||||
&__link.router-link-exact-active ~ &__underline {
|
||||
&:before,
|
||||
&:after {
|
||||
width: 50%;
|
||||
background-color: #fff;
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,11 +71,13 @@ export default {
|
|||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0.125em;
|
||||
bottom: 0;
|
||||
|
||||
width: 0;
|
||||
height: 0.125rem;
|
||||
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|