aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-08-19 20:40:19 +0000
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-08-19 20:40:19 +0000
commit7fdaea73c5c67565202e19d6182fc215427919c3 (patch)
treec69e266fe672cba5f8bffd5f53e93b0efab65e9c /src
downloadcrunched-7fdaea73c5c67565202e19d6182fc215427919c3.tar.gz
crunched-7fdaea73c5c67565202e19d6182fc215427919c3.tar.bz2
crunched-7fdaea73c5c67565202e19d6182fc215427919c3.tar.lz
crunched-7fdaea73c5c67565202e19d6182fc215427919c3.zip

feat: oidc attempt 1

Diffstat (limited to 'src')
-rw-r--r--src/app.css31
-rw-r--r--src/app.d.ts16
-rw-r--r--src/app.html11
-rw-r--r--src/cs16.css761
-rw-r--r--src/hooks.server.ts32
-rw-r--r--src/lib/assets/favicon.svg1
-rw-r--r--src/lib/auth.server.ts73
-rw-r--r--src/lib/index.ts1
-rw-r--r--src/lib/oncePromise.ts30
-rw-r--r--src/routes/+error.svelte6
-rw-r--r--src/routes/+layout.server.ts5
-rw-r--r--src/routes/+layout.svelte23
-rw-r--r--src/routes/+page.svelte26
-rw-r--r--src/routes/login/+server.ts55
-rw-r--r--src/routes/login/callback/+server.ts80
15 files changed, 1151 insertions, 0 deletions
diff --git a/src/app.css b/src/app.css
new file mode 100644
index 0000000..a451f07
--- /dev/null
+++ b/src/app.css
@@ -0,0 +1,31 @@
+@import 'tailwindcss';
+
+@layer base {
+ @import './cs16.css';
+
+ html {
+ font-size: 21px;
+ }
+
+ body {
+ padding: 40px;
+ max-width: 800px;
+ margin: auto;
+ margin: 0 max(0px, round(50vw - (800px/2), 1px));
+ }
+
+ ::selection {
+ background-color: #958831;
+ color: white;
+ }
+
+ @media (max-width: 400px) {
+ body {
+ padding: 20px;
+ }
+ }
+
+ a:not(.default) {
+ @apply hover:underline text-[#baab44];
+ }
+}
diff --git a/src/app.d.ts b/src/app.d.ts
new file mode 100644
index 0000000..cfeb8a5
--- /dev/null
+++ b/src/app.d.ts
@@ -0,0 +1,16 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+type Session = unknown;
+declare global {
+ namespace App {
+ // interface Error {}
+ interface Locals {
+ auth: () => Promise<Session | null>;
+ }
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/src/app.html b/src/app.html
new file mode 100644
index 0000000..b0b3788
--- /dev/null
+++ b/src/app.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ %sveltekit.head%
+ </head>
+ <body data-sveltekit-preload-data="hover" class="cs">
+ <div style="display: contents">%sveltekit.body%</div>
+ </body>
+</html>
diff --git a/src/cs16.css b/src/cs16.css
new file mode 100644
index 0000000..108e9d2
--- /dev/null
+++ b/src/cs16.css
@@ -0,0 +1,761 @@
+:root {
+ --bg: #4a5942;
+ --secondary-bg: #3e4637;
+ --accent: #c4b550;
+ --secondary-accent: #958831;
+ --text: #dedfd6;
+ --secondary-text: #d8ded3;
+ --text-3: #a0aa95;
+ --border-light: #8c9284;
+ --border-dark: #292c21;
+ --disabled-text: #292c21;
+ --disabled-text-shadow: #75806f;
+ --outline: #000;
+ --slider: #7f8c7f;
+ --slider-bg: #1f1f1f;
+ --scrollbar-track: #5a6a50;
+}
+@font-face {
+ font-family: ArialPixel;
+ font-style: normal;
+ font-weight: 400;
+ src: url(https://cdn.jsdelivr.net/gh/ekmas/cs16.css@main/ArialPixel.ttf)
+ format('truetype');
+}
+.cs {
+ & {
+ background-color: var(--bg);
+ color: var(--text);
+ font-family: ArialPixel, system-ui, sans-serif;
+ font-weight: 400;
+ line-height: 1.5;
+ }
+ *,
+ :after,
+ :before {
+ box-sizing: border-box;
+ }
+ * {
+ margin: 0;
+ padding: 0;
+ }
+ button,
+ input,
+ select,
+ textarea {
+ font: inherit;
+ }
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ p {
+ font-weight: 400;
+ overflow-wrap: break-word;
+ }
+ ::-webkit-scrollbar {
+ width: 18px;
+ width: 1.125rem;
+ }
+ ::-webkit-scrollbar-track {
+ background-color: var(--scrollbar-track);
+ border: 1px solid var(--border-dark);
+ border-left: 0;
+ width: 18px;
+ width: 1.125rem;
+ }
+ ::-webkit-scrollbar-thumb {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ width: 17px;
+ width: 1.0625rem;
+ }
+ ::-webkit-scrollbar-corner {
+ background-color: var(--scrollbar-track);
+ }
+ ::-webkit-scrollbar-button:vertical:end:increment,
+ ::-webkit-scrollbar-button:vertical:start:decrement {
+ display: block;
+ }
+ ::-webkit-scrollbar-button:vertical:end:decrement,
+ ::-webkit-scrollbar-button:vertical:end:increment,
+ ::-webkit-scrollbar-button:vertical:start:decrement,
+ ::-webkit-scrollbar-button:vertical:start:increment {
+ background-repeat: no-repeat;
+ height: 17px;
+ height: 1.0625rem;
+ }
+ ::-webkit-scrollbar-button:vertical:start {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23a0aa95' d='M5 9h1v1H5m1-1h1v1H6m0-2h1v1H6m1 0h1v1H7m0-2h1v1H7m0-2h1v1H7m1 1h1v1H8m0-2h1v1H8m0-2h1v1H8m0-2h1v1H8m1 2h1v1H9m0-2h1v1H9m0-2h1v1H9m1 1h1v1h-1m0-2h1v1h-1m1 0h1v1h-1'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end,
+ ::-webkit-scrollbar-button:vertical:start {
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ }
+ ::-webkit-scrollbar-button:vertical:end:active,
+ ::-webkit-scrollbar-button:vertical:start:active {
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ }
+ ::-webkit-scrollbar-button:vertical:start:active,
+ ::-webkit-scrollbar-button:vertical:start:hover {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23fff' d='M5 9h1v1H5m1-1h1v1H6m1-1h1v1H7m1-1h1v1H8m1-1h1v1H9m1-1h1v1h-1m1-1h1v1h-1M6 8h1v1H6m1-1h1v1H7m1-1h1v1H8m1-1h1v1H9m1-1h1v1h-1M7 7h1v1H7m1-1h1v1H8m1-1h1v1H9M8 6h1v1H8'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23a0aa95' d='M5 6h1v1H5m1-1h1v1H6m0 0h1v1H6m1-1h1v1H7m0 0h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8M7 6h1v1H7m1-1h1v1H8m3-1h1v1h-1m-1-1h1v1h-1M9 6h1v1H9m0 1h1v1H9m0-2h1v1H9m1-1h1v1h-1'/%3E%3C/svg%3E");
+ }
+ ::-webkit-scrollbar-button:vertical:end:active {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='16' viewBox='0 0 15 16'%3E%3Cpath fill='%23fff' d='M5 6h1v1H5m6-1h1v1h-1m-1-1h1v1h-1M9 6h1v1H9M8 6h1v1H8M7 6h1v1H7M6 6h1v1H6m0 0h1v1H6m4-1h1v1h-1M9 7h1v1H9M8 7h1v1H8M7 7h1v1H7m0 0h1v1H7m2-1h1v1H9M8 9h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ .cs-btn,
+ button:not(.default-btn),
+ input[type='submit']:not(.default-btn) {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ color: #fff;
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ padding: 0.25rem 0.3125rem 0.1875rem;
+ user-select: none;
+ &.close {
+ background: no-repeat 50%;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='%238c9284' d='M3 3h1v1H3m1-1h1v1H4M3 4h1v1H3m1-1h1v1H4m0 0h1v1H4m1-1h1v1H5m0-2h1v1H5m0 1h1v1H5m1-1h1v1H6m0-2h1v1H6m0 1h1v1H6m0 0h1v1H6m1-1h1v1H7m0-2h1v1H7m0-2h1v1H7m1-1h1v1H8m0 0h1v1H8m0 0h1v1H8m0-4h1v1H8m1-1h1v1H9m0 0h1v1H9m0-3h1v1H9m1-1h1v1h-1m0 0h1v1h-1m0-3h1v1h-1m1-1h1v1h-1m0 0h1v1h-1M9 8h1v1H9m0 0h1v1H9M8 9h1v1H8m2-1h1v1h-1m0 0h1v1h-1m-1-1h1v1H9m2-1h1v1h-1m0 0h1v1h-1m-1-1h1v1h-1M5 8h1v1H5m0 0h1v1H5m1-1h1v1H6M4 9h1v1H4m0 0h1v1H4m1-1h1v1H5m-2-1h1v1H3m0 0h1v1H3m1-1h1v1H4'/%3E%3C/svg%3E");
+ height: 18px;
+ height: 1.125rem;
+ padding: 0;
+ width: 18px;
+ width: 1.125rem;
+ }
+ &:focus-visible {
+ outline: 1px solid var(--outline);
+ outline: 0.0625rem solid var(--outline);
+ padding: 0.1875rem 0.25rem 0.125rem;
+ &.close {
+ outline: 0;
+ padding: 0;
+ }
+ }
+ &:active {
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ }
+ &:disabled {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ text-shadow: var(--disabled-text-shadow) 0.0625rem 0.0625rem;
+ }
+ }
+ hr:not(.default-hr) {
+ border-bottom-color: var(--border-light);
+ border-left: 0;
+ border-right: 0;
+ border-top-color: var(--border-dark);
+ }
+ .cs-checkbox:not(input) {
+ position: relative;
+ }
+ .cs-checkbox input,
+ input.cs-checkbox,
+ input[type='checkbox']:not(.default-checkbox) {
+ position: absolute;
+ clip: rect(1px, 1px, 1px, 1px);
+ clip: rect(0.0625rem, 0.0625rem, 0.0625rem, 0.0625rem);
+ border: 0;
+ height: 1px;
+ height: 0.0625rem;
+ overflow: hidden;
+ padding: 0;
+ width: 1px;
+ width: 0.0625rem;
+ &:focus:not(:focus-visible) {
+ outline: none;
+ }
+ &:focus-visible + .cs-checkbox__label,
+ &:focus-visible + label {
+ outline: dotted 2px var(--outline);
+ outline: dotted 0.125rem var(--outline);
+ outline-offset: 3px;
+ outline-offset: 0.1875rem;
+ }
+ &:checked + .cs-checkbox__label,
+ &:checked + label {
+ color: var(--accent);
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath fill='%23c4b550' d='M2 6h1v1H2m1-2h1v1H3M2 5h1v1H2m0-2h1v1H2m1 1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m0 0h1v1H4m1-2h1v1H5m0-2h1v1H5m0-2h1v1H5m1-2h1v1H6m0 0h1v1H6m0 0h1v1H6m1-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ .cs-checkbox input + label,
+ .cs-checkbox__label,
+ input.cs-checkbox + label,
+ input[type='checkbox']:not(.default-checkbox) + label,
+ label.cs-checkbox:has(input),
+ label:has(.cs-checkbox),
+ label:not(.default-checkbox):has(
+ input[type='checkbox']:not(.default-checkbox)
+ ) {
+ color: var(--secondary--text);
+ cursor: pointer;
+ display: inline-block;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ user-select: none;
+ &:before {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ content: '';
+ display: inline-block;
+ height: 12px;
+ height: 0.75rem;
+ margin-right: 0.4375rem;
+ vertical-align: middle;
+ width: 12px;
+ width: 0.75rem;
+ }
+ &:hover {
+ color: #fff;
+ }
+ }
+ label.cs-checkbox:has(input),
+ label:has(.cs-checkbox),
+ label:not(.default-checkbox):has(
+ input[type='checkbox']:not(.default-checkbox)
+ ) {
+ position: relative;
+ &:has(.cs-checkbox:focus-visible),
+ &:has(input:not(.default-checkbox):focus-visible) {
+ outline: dotted 2px var(--outline);
+ outline: dotted 0.125rem var(--outline);
+ outline-offset: 3px;
+ outline-offset: 0.1875rem;
+ }
+ &:before {
+ margin-right: 0.1875rem;
+ }
+ &:has(.cs-checkbox:checked),
+ &:has(input:not(.default-checkbox):checked) {
+ color: var(--accent);
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath fill='%23c4b550' d='M2 6h1v1H2m1-2h1v1H3M2 5h1v1H2m0-2h1v1H2m1 1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m0 0h1v1H4m1-2h1v1H5m0-2h1v1H5m0-2h1v1H5m1-2h1v1H6m0 0h1v1H6m0 0h1v1H6m1-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1 0h1v1H8m0-2h1v1H8m0-2h1v1H8'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ .cs-input,
+ input:is(
+ [type='text'],
+ [type='number'],
+ [type='email'],
+ [type='date'],
+ [type='datetime-local'],
+ [type='month'],
+ [type='password'],
+ [type='search'],
+ [type='tel'],
+ [type='url'],
+ [type='week'],
+ [type='datetime'],
+ [type='input']
+ ):not(.default-input) {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ color: var(--secondary--text);
+ font-size: 1rem;
+ line-height: 1.0625rem;
+ outline: 0;
+ padding: 0.1875rem 0.125rem 0.125rem;
+ &:focus + .cs-input__label,
+ &:focus + label {
+ color: var(--accent);
+ }
+ &::-moz-selection {
+ background-color: var(--secondary-accent);
+ color: #fff;
+ }
+ &::selection {
+ background-color: var(--secondary-accent);
+ color: #fff;
+ }
+ &:disabled {
+ background-color: var(--bg);
+ color: var(--text-3);
+ pointer-events: none;
+ }
+ &:disabled + .cs-input__label,
+ &:disabled + label {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ text-shadow: var(--disabled-text-shadow) 0.0625rem 0.0625rem;
+ }
+ }
+ .cs-input__label,
+ label:has(
+ input:is(
+ [type='text'],
+ [type='number'],
+ [type='email'],
+ [type='date'],
+ [type='datetime-local'],
+ [type='month'],
+ [type='password'],
+ [type='search'],
+ [type='tel'],
+ [type='url'],
+ [type='week'],
+ [type='datetime'],
+ [type='input']
+ ):not(.default-input)
+ ):not(.default-input) {
+ color: var(--secondary--text);
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ &:has(input:not(.default-input):focus) {
+ color: var(--accent);
+ }
+ &:has(input:not(.default-input):disabled) {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ text-shadow: var(--disabled-text-shadow) 0.0625rem 0.0625rem;
+ }
+ }
+ .cs-select,
+ select:not(.default-select) {
+ appearance: none;
+ background-color: var(--secondary-bg);
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath fill='%23a0aa95' d='M0 0h1v1H0m1-1h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1-1h1v1H3m0 0h1v1H3m0-3h1v1H3M2 0h1v1H2m1-1h1v1H3m1-1h1v1H4m0 1h1v1H4m0-2h1v1H4m1-1h1v1H5m0-2h1v1H5m1-1h1v1H6'/%3E%3C/svg%3E");
+ background-position: right 6px top 50%;
+ background-position: right 0.375rem top 50%;
+ background-repeat: no-repeat;
+ background-size: 7px auto;
+ background-size: 0.4375rem auto;
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ border-radius: 0;
+ color: var(--secondary--text);
+ line-height: 15px;
+ line-height: 0.9375rem;
+ min-width: 150px;
+ min-width: 9.375rem;
+ outline: 0;
+ padding: 0.3125rem 0.9375rem 0.3125rem 0.1875rem;
+ user-select: none;
+ &:focus-within,
+ &:hover {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath fill='%23fff' d='M0 0h1v1H0m1-1h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1 0h1v1H3m0-2h1v1H3m0-2h1v1H3M2 0h1v1H2m1-1h1v1H3m1-1h1v1H4m0 1h1v1H4m0-2h1v1H4m1-1h1v1H5m0-2h1v1H5m1-1h1v1H6'/%3E%3C/svg%3E");
+ }
+ option {
+ background-color: var(--bg);
+ color: var(--text-3);
+ }
+ }
+ .cs-select__label,
+ label:has(select:not(.default-select)):not(.default-select-label) {
+ color: var(--secondary--text);
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ user-select: none;
+ }
+ .cs-fieldset,
+ fieldset:not(.default-fieldset) {
+ border: none;
+ user-select: none;
+ legend {
+ color: var(--secondary--text);
+ margin-bottom: 0.625rem;
+ }
+ > div {
+ padding-left: 0.625rem;
+ }
+ &:disabled {
+ input[type='radio'] {
+ + label {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ text-shadow: var(--disabled-text-shadow) 0.0625rem 0.0625rem;
+ }
+ }
+ legend {
+ color: var(--disabled-text);
+ pointer-events: none;
+ text-shadow: var(--disabled-text-shadow) 1px 1px;
+ text-shadow: var(--disabled-text-shadow) 0.0625rem 0.0625rem;
+ }
+ }
+ input[type='radio'] {
+ opacity: 0;
+ + label {
+ color: var(--secondary--text);
+ cursor: pointer;
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ position: relative;
+ &:before {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23889180' d='M10 2h1v1h-1m0 0h1v1h-1m1 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m-1 0h1v1h-1m0 0h1v1h-1m-2 0h1v1H8m1-1h1v1H9m-2 0h1v1H7m-1-1h1v1H6m-1-1h1v1H5m-3-2h1v1H2m1-1h1v1H3m1 0h1v1H4'/%3E%3Cpath fill='%23292c21' d='M1 2h1v1H1m0 0h1v1H1m1-3h1v1H2m1-1h1v1H3m1-2h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7m1 0h1v1H8m1-1h1v1H9M0 4h1v1H0m0 0h1v1H0m0 0h1v1H0m0 0h1v1H0m1 0h1v1H1m0 0h1v1H1'/%3E%3Cpath fill='%233e4637' d='M4 1h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7m1 0h1v1H8m1-1h1v1H9m0 0h1v1H9m0 0h1v1H9m1-1h1v1h-1m0 0h1v1h-1m0 0h1v1h-1m0 0h1v1h-1M9 7h1v1H9m0 0h1v1H9m0 0h1v1H9M8 9h1v1H8M7 9h1v1H7m0 0h1v1H7m-1-1h1v1H6m-1-1h1v1H5m-1-1h1v1H4m2-2h1v1H6M5 9h1v1H5M4 9h1v1H4M3 9h1v1H3M2 9h1v1H2m0-2h1v1H2M1 7h1v1H1m0-4h1v1H1m1-2h1v1H2m0-2h1v1H2m1-1h1v1H3m1-1h1v1H4m1-1h1v1H5m1-1h1v1H6m1-1h1v1H7M3 3h1v1H3M2 4h1v1H2m0 0h1v1H2M1 5h1v1H1m0 0h1v1H1m1-1h1v1H2m0 0h1v1H2m1 0h1v1H3m0-2h1v1H3m0-2h1v1H3m0-2h1v1H3m0-2h1v1H3m1-2h1v1H4m1-1h1v1H5m0 0h1v1H5M4 8h1v1H4m0-2h1v1H4m0-2h1v1H4m0-3h1v1H4m0 0h1v1H4m1-1h1v1H5m0 0h1v1H5m0 0h1v1H5m0 0h1v1H5m1-1h1v1H6m0-2h1v1H6m0-2h1v1H6m0-4h1v1H6m0 0h1v1H6m0 0h1v1H6m1 1h1v1H7m0 0h1v1H7m1-1h1v1H8m0-2h1v1H8M7 6h1v1H7m0-2h1v1H7m0-2h1v1H7m0-2h1v1H7m1-1h1v1H8m0 0h1v1H8m0 0h1v1H8m0 0h1v1H8m1-1h1v1H9m0-2h1v1H9'/%3E%3C/svg%3E");
+ height: 12px;
+ height: 0.75rem;
+ left: -25px;
+ left: -1.5625rem;
+ top: 1px;
+ top: 0.0625rem;
+ width: 12px;
+ width: 0.75rem;
+ }
+ &:after,
+ &:before {
+ content: '';
+ position: absolute;
+ }
+ &:after {
+ height: 6px;
+ height: 0.375rem;
+ left: -22px;
+ left: -1.375rem;
+ top: 4px;
+ top: 0.25rem;
+ width: 6px;
+ width: 0.375rem;
+ }
+ }
+ &:checked {
+ + label {
+ color: var(--accent);
+ }
+ + label:after {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6' viewBox='0 0 6 6'%3E%3Cpath fill='%23c4b550' d='M1 0h1v1H1m2-1h1v1H3m1-1h1v1H4m0 0h1v1H4m1-1h1v1H5m0 0h1v1H5m0 0h1v1H5m0 0h1v1H5M4 5h1v1H4M3 5h1v1H3M2 5h1v1H2M1 5h1v1H1M0 4h1v1H0m0-2h1v1H0m0-2h1v1H0m1-1h1v1H1m0 0h1v1H1m0 0h1v1H1m1-1h1v1H2m0-2h1v1H2m0-4h1v1H2m0 0h1v1H2m1-1h1v1H3m0 1h1v1H3m0 0h1v1H3m1-1h1v1H4m0-2h1v1H4m0-2h1v1H4M3 2h1v1H3M2 2h1v1H2M1 1h1v1H1M0 1h1v1H0'/%3E%3C/svg%3E");
+ }
+ }
+ }
+ }
+ .cs-slider {
+ display: flex;
+ flex-direction: column-reverse;
+ user-select: none;
+ width: 150px;
+ width: 9.375rem;
+ input {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--slider-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ box-sizing: border-box;
+ height: 4px;
+ height: 0.25rem;
+ outline: none;
+ width: 150px;
+ width: 9.375rem;
+ }
+ input::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ border-radius: 0;
+ box-sizing: border-box;
+ cursor: pointer;
+ height: 16px;
+ height: 1rem;
+ width: 8px;
+ width: 0.5rem;
+ }
+ input::-moz-range-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ border-radius: 0;
+ box-sizing: border-box;
+ cursor: pointer;
+ height: 16px;
+ height: 1rem;
+ width: 8px;
+ width: 0.5rem;
+ }
+ label {
+ color: var(--secondary--text);
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ margin-bottom: 0.75rem;
+ }
+ &:has(input:focus) label {
+ color: var(--accent);
+ }
+ .ruler {
+ background-image: linear-gradient(to right, var(--slider) 1px, #0000 1px);
+ background-image: linear-gradient(
+ to right,
+ var(--slider) 0.0625rem,
+ #0000 0.0625rem
+ );
+ background-size: 15px 5px;
+ background-size: 0.9375rem 0.3125rem;
+ height: 5px;
+ height: 0.3125rem;
+ margin-left: 0.25rem;
+ margin-top: 0.25rem;
+ width: calc(100% + 5px);
+ width: calc(100% + 0.3125rem);
+ z-index: -1;
+ }
+ .value {
+ align-items: center;
+ color: var(--slider);
+ display: flex;
+ font-size: 13px;
+ font-size: 0.8125rem;
+ justify-content: space-between;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ }
+ }
+ .cs-dialog,
+ dialog:not(.default-dialog) {
+ background-color: var(--bg);
+ border: 1px solid;
+ border-color: var(--border-light) var(--border-dark) var(--border-dark)
+ var(--border-light);
+ color: var(--text);
+ margin: auto;
+ max-width: 510px;
+ max-width: 31.875rem;
+ min-width: 350px;
+ min-width: 21.875rem;
+ padding: 0.25rem;
+ position: fixed;
+ right: 0;
+ top: 0;
+ user-select: none;
+ .heading {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+ margin-top: 0.1875rem;
+ padding-left: 0.125rem;
+ .wrapper {
+ align-items: center;
+ display: flex;
+ gap: 5px;
+ gap: 0.3125rem;
+ .icon {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='15' viewBox='0 0 16 15'%3E%3Cpath fill='%238c9284' d='M1 12h1v1H1m1 0h1v1H2m1-2h1v1H3m11-6h1v1h-1'/%3E%3Cpath fill='%23a5aa9c' d='M3 14h1v1H3'/%3E%3Cpath fill='%23bdbeb5' d='M0 11h1v1H0m10-9h1v1h-1m0 1h1v1h-1m2-3h1v1h-1m0 1h1v1h-1m0 2h1v1h-1'/%3E%3Cpath fill='%23fff' d='M0 10h1v1H0m0-2h1v1H0m0-2h1v1H0m1-1h1v1H1m0 0h1v1H1m0 0h1v1H1m1-1h1v1H2m0-2h1v1H2m1-1h1v1H3m0 0h1v1H3m1-2h1v1H4m0 0h1v1H4m1-1h1v1H5m-4 0h1v1H1m1-1h1v1H2m1-1h1v1H3m1-1h1v1H4m1-1h1v1H5m-2 1h1v1H3m3-6h1v1H6m0-2h1v1H6m1-1h1v1H7m0 0h1v1H7m1-2h1v1H8m0 0h1v1H8m1-2h1v1H9m0 0h1v1H9m1-2h1v1h-1m0 0h1v1h-1M7 9h1v1H7m1-1h1v1H8m1-1h1v1H9M7 6h1v1H7m1-1h1v1H8m0-2h1v1H8m0-2h1v1H8m0-2h1v1H8m-1 7h1v1H7m4-9h1v1h-1m0 0h1v1h-1m-1-1h1v1h-1m1 0h1v1h-1m1-2h1v1h-1M9 2h1v1H9m4-1h1v1h-1m0 4h1v1h-1m1-2h1v1h-1m0-2h1v1h-1m0-2h1v1h-1m0-2h1v1h-1m-4-3h1v1h-1m1-1h1v1h-1m1-1h1v1h-1'/%3E%3Cpath fill='%23848e84' d='M0 7h1v1H0m11-8h1v1h-1M7 4h1v1H7m1-4h1v1H8'/%3E%3Cpath fill='%239ca29c' d='M2 8h1v1H2m1-1h1v1H3m3 5h1v1H6m1-2h1v1H7m3-5h1v1h-1m5-6h1v1h-1m0 0h1v1h-1'/%3E%3Cpath fill='%23d6d7ce' d='M4 8h1v1H4m2 0h1v1H6'/%3E%3Cpath fill='%23dedfde' d='M4 14h1v1H4m1-1h1v1H5m3-5h1v1H8'/%3E%3Cpath fill='%23f7f7f7' d='M5 8h1v1H5m6-2h1v1h-1m1-1h1v1h-1m-1 0h1v1h-1'/%3E%3Cpath fill='%23efefef' d='M2 12h1v1H2m4 0h1v1H6m1-2h1v1H7m0-3h1v1H7m0-6h1v1H7'/%3E%3Cpath fill='%23cecfce' d='M4 12h1v1H4m1-1h1v1H5m4-7h1v1H9'/%3E%3Cpath fill='%23d6dbd6' d='M8 2h1v1H8m1-2h1v1H9m4-1h1v1h-1m1 0h1v1h-1'/%3E%3Cpath fill='%23949e94' d='M13 6h1v1h-1'/%3E%3Cpath fill='%235a6952' d='M5 9h1v1H5m1 0h1v1H6m0 0h1v1H6m0 0h1v1H6m-2 0h1v1H4m1-1h1v1H5m8-9h1v1h-1m0-3h1v1h-1m0 4h1v1h-1m-4 1h1v1H9m-2 3h1v1H7'/%3E%3Cpath fill='%23525d4a' d='M10 6h1v1h-1m1-1h1v1h-1m1-1h1v1h-1m1-3h1v1h-1m-1-3h1v1h-1m-1-1h1v1h-1m-1-1h1v1h-1M9 3h1v1H9m0 0h1v1H9m0 0h1v1H9M5 7h1v1H5m2-6h1v1H7m0 0h1v1H7m2-4h1v1H9m1-1h1v1h-1m2-1h1v1h-1m2 0h1v1h-1'/%3E%3Cpath fill='%23adb6ad' d='M6 6h1v1H6'/%3E%3C/svg%3E");
+ height: 15px;
+ height: 0.9375rem;
+ width: 16px;
+ width: 1rem;
+ }
+ .text {
+ color: #fff;
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ }
+ }
+ }
+ .content {
+ padding: 0.625rem;
+ }
+ .footer-btns {
+ float: right;
+ margin: 0.25rem 0.5rem 0.5rem 0;
+ .cs-btn {
+ text-align: left;
+ width: 72px;
+ width: 4.5rem;
+ }
+ }
+ }
+ .cs-tooltip {
+ color: #fff;
+ display: inline-block;
+ line-height: 20px;
+ line-height: 1.25rem;
+ position: relative;
+ user-select: none;
+ &:hover .text {
+ visibility: visible;
+ }
+ .text {
+ background-color: var(--secondary-accent);
+ border: 1px solid var(--border-dark);
+ color: #000;
+ font-size: 16px;
+ font-size: 1rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ padding: 0.125rem 0.125rem 0.0625rem;
+ position: absolute;
+ text-align: center;
+ visibility: hidden;
+ width: max-content;
+ z-index: 1;
+ }
+ }
+ .cs-progress-bar {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ height: 24px;
+ height: 1.5rem;
+ padding: 0.1875rem;
+ width: 260px;
+ width: 16.25rem;
+ .bars {
+ background-image: linear-gradient(to right, var(--accent) 8px, #0000 2px);
+ background-image: linear-gradient(
+ to right,
+ var(--accent) 0.5rem,
+ #0000 0.125rem
+ );
+ background-size: 12px 16px;
+ background-size: 0.75rem 1rem;
+ height: 100%;
+ }
+ }
+ progress:not(.default-progress) {
+ background-color: var(--secondary-bg);
+ border: 1px solid;
+ border-color: var(--border-dark) var(--border-light) var(--border-light)
+ var(--border-dark);
+ height: 24px;
+ height: 1.5rem;
+ padding: 0.1875rem;
+ position: relative;
+ width: 260px;
+ width: 16.25rem;
+ &::-moz-progress-bar {
+ background-color: var(--secondary-bg);
+ background-image: linear-gradient(
+ 90deg,
+ #0000 0,
+ var(--accent) 0.01px,
+ var(--accent) 7.99px,
+ #0000 8px
+ );
+ background-image: linear-gradient(
+ 90deg,
+ #0000 0,
+ var(--accent) 0.00063rem,
+ var(--accent) 0.49938rem,
+ #0000 0.5rem
+ );
+ background-size: 12px 16px;
+ background-size: 0.75rem 1rem;
+ height: 100%;
+ }
+ &::-webkit-progress-bar,
+ &::-webkit-progress-value {
+ background-color: var(--secondary-bg);
+ }
+ &::-webkit-progress-value {
+ background-image: linear-gradient(to right, var(--accent) 8px, #0000 2px);
+ background-image: linear-gradient(
+ to right,
+ var(--accent) 0.5rem,
+ #0000 0.125rem
+ );
+ background-size: 12px 16px;
+ background-size: 0.75rem 1rem;
+ height: 100%;
+ }
+ }
+ .cs-tabs {
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ user-select: none;
+ .radiotab {
+ opacity: 0;
+ position: absolute;
+ }
+ .label {
+ background-color: var(--bg);
+ border-bottom: none;
+ border-left: 0.0625rem solid var(--border-light);
+ border-right: 0.0625rem solid var(--border-dark);
+ border-top: 0.0625rem solid var(--border-light);
+ color: #fff;
+ cursor: pointer;
+ font-size: 16px;
+ font-size: 1rem;
+ height: 27px;
+ height: 1.6875rem;
+ line-height: 15px;
+ line-height: 0.9375rem;
+ margin-right: 0.0625rem;
+ min-width: 64px;
+ min-width: 4rem;
+ padding: 0.25rem 0.3125rem;
+ position: relative;
+ text-align: left;
+ z-index: 10;
+ }
+ .radiotab:checked + .label {
+ background: var(--bg);
+ color: var(--accent);
+ height: 29px;
+ height: 1.8125rem;
+ padding: 0.3125rem;
+ &:before {
+ background-color: var(--bg);
+ bottom: 0;
+ content: '';
+ height: 1px;
+ height: 0.0625rem;
+ left: 0;
+ position: absolute;
+ width: 100%;
+ }
+ }
+ .panel {
+ background: var(--bg);
+ border-bottom: 0.0625rem solid var(--border-dark);
+ border-left: 0.0625rem solid var(--border-light);
+ border-right: 0.0625rem solid var(--border-dark);
+ border-top: 0.0625rem solid var(--border-light);
+ bottom: 1px;
+ bottom: 0.0625rem;
+ color: var(--text);
+ display: none;
+ order: 99;
+ padding: 2rem 2.4375rem 1.6875rem;
+ position: relative;
+ width: 100%;
+ }
+ .radiotab:checked + .label + .panel {
+ display: block;
+ position: relative;
+ }
+ }
+}
diff --git a/src/hooks.server.ts b/src/hooks.server.ts
new file mode 100644
index 0000000..2fe3744
--- /dev/null
+++ b/src/hooks.server.ts
@@ -0,0 +1,32 @@
+import * as auth from './lib/auth.server';
+import * as client from 'openid-client';
+
+// https://svelte.dev/docs/kit/hooks#Server-hooks-handle
+export const handle = ({ event, resolve }) => {
+ event.locals.auth = async () => {
+ const accessToken = event.cookies.get('oid__access_token');
+ const sub = event.cookies.get('oid__sub');
+ console.warn({ accessToken, sub });
+ if (accessToken && sub) {
+ try {
+ const userInfo = await client
+ .fetchUserInfo(await auth.getConfig(), accessToken, sub)
+ .catch((e) => {
+ console.warn(e);
+
+ return null;
+ });
+ console.warn({
+ userInfo,
+ accessToken,
+ sub,
+ });
+ } catch (error) {}
+ } else if (accessToken || sub) {
+ event.cookies.delete('access-token', { path: '/' });
+ event.cookies.delete('sub', { path: '/' });
+ }
+ return null;
+ };
+ return resolve(event);
+};
diff --git a/src/lib/assets/favicon.svg b/src/lib/assets/favicon.svg
new file mode 100644
index 0000000..cc5dc66
--- /dev/null
+++ b/src/lib/assets/favicon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17