From 7977fe9ea7511f02c03f98e92de268cde1de8aee Mon Sep 17 00:00:00 2001 From: Andy Burke Date: Tue, 3 Mar 2026 20:32:45 -0800 Subject: [PATCH 1/4] fix: styling improvements --- public/base.css | 1296 +-------------------------------- public/foo/index.html | 6 - public/icons.css | 1286 ++++++++++++++++++++++++++++++++ public/index.html | 1 + public/signup_login_wall.html | 12 +- 5 files changed, 1289 insertions(+), 1312 deletions(-) delete mode 100644 public/foo/index.html create mode 100644 public/icons.css diff --git a/public/base.css b/public/base.css index 876d988..87aca04 100644 --- a/public/base.css +++ b/public/base.css @@ -1,6 +1,6 @@ /* Dark mode default */ :root { - --base-color: #518; + --base-color: #234; --bg: hsl(from var(--base-color) h 20% 7.5%); --bg-darker: hsl(from var(--base-color) h 20% 5%); @@ -55,13 +55,11 @@ dd { margin-block-end: 0; } -/* Set core body defaults */ body { min-height: 100vh; line-height: 1.5; } -/* Set shorter line heights on headings and interactive elements */ h1, h2, h3, @@ -72,7 +70,6 @@ label { line-height: 1.1; } -/* Balance text wrapping on headings */ h1, h2, h3, @@ -80,20 +77,17 @@ h4 { text-wrap: balance; } -/* A elements that don't have a class get default styles */ a:not([class]) { text-decoration-skip-ink: auto; color: currentColor; } -/* Make images easier to work with */ img, picture { max-width: 100%; display: block; } -/* Inherit fonts for inputs and buttons */ input, button, textarea, @@ -168,7 +162,6 @@ body { display: flex; flex-direction: column; height: 100vh; - /* fixed height? */ } #background-container { @@ -613,1290 +606,3 @@ body[data-perms*="files.write.own"] [data-requires-permission="files.write.own"] .inline { display: inline-block !important; } - -/* ICONS */ -.icon { - width: 24px; - height: 24px; - transform: scale(var(--icon-scale, 1)); - - stroke: white; - fill: transparent; - stroke-width: 1pt; - stroke-miterlimit: 10; - stroke-linecap: round; - stroke-linejoin: round; - stroke-dasharray: 400; - - margin: 0 auto; -} - -/* ICON - ADD (with box) */ -.icon.add { - box-sizing: border-box; - position: relative; - display: block; - width: 22px; - height: 22px; - border: 2px solid; - transform: scale(var(--icon-scale, 1)); - border-radius: 4px; -} - -.icon.add::after, -.icon.add::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 10px; - height: 2px; - background: currentColor; - border-radius: 5px; - top: 8px; - left: 4px; -} - -.icon.add::after { - width: 2px; - height: 10px; - top: 4px; - left: 8px; -} - -/* ICON - ATTACHMENT */ -.icon.attachment { - box-sizing: border-box; - position: relative; - display: block; - width: 14px; - height: 14px; - border: 2px solid; - border-top: 0; - border-bottom-left-radius: 100px; - border-bottom-right-radius: 100px; - transform: scale(var(--icon-scale, 1)); - margin-top: 11px; -} - -.icon.attachment::after, -.icon.attachment::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - border-radius: 3px; - border: 2px solid; -} - -.icon.attachment::after { - border-bottom: 0; - border-top-left-radius: 100px; - border-top-right-radius: 100px; - right: -2px; - width: 10px; - height: 14px; - bottom: 8px; -} - -.icon.attachment::before { - width: 6px; - height: 12px; - border-top: 0; - border-bottom-left-radius: 100px; - border-bottom-right-radius: 100px; - left: 2px; - bottom: 4px; -} - -/* ICON - BLURB */ -.icon.blurb { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - border: 2px solid; - border-radius: 3px; - width: 22px; - height: 16px; -} - -.icon.blurb::after, -.icon.blurb::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - height: 2px; - border-radius: 3px; - background: currentColor; - bottom: 2px; -} - -.icon.blurb::before { - width: 10px; - left: 2px; - box-shadow: 4px -4px 0; -} - -.icon.blurb::after { - width: 3px; - right: 2px; - box-shadow: -11px -4px 0; -} - -/* ICON - CALENDAR */ -.icon.calendar, -.icon.calendar::before { - display: block; - box-sizing: border-box; -} - -.icon.calendar { - position: relative; - transform: scale(var(--icon-scale, 1)); - width: 18px; - height: 18px; - border: 2px solid; - border-top: 4px solid; - border-radius: 3px; -} - -.icon.calendar::before { - content: ""; - position: absolute; - width: 10px; - border-radius: 3px; - left: 2px; - background: currentColor; - height: 2px; - top: 2px; -} - -/* ICON - CAMERA */ -.icon.camera { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - border: 2px solid; - border-radius: 3px; - width: 18px; - height: 12px; - perspective: 24px; -} - -.icon.camera::after, -.icon.camera::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; -} - -.icon.camera::before { - border: 2px solid; - border-left-color: transparent; - transform: rotateY(-70deg); - width: 8px; - height: 8px; - right: -7px; - top: 0; -} - -.icon.camera::after { - width: 10px; - height: 5px; - border-top: 2px solid; - border-right: 2px solid; - top: -5px; - right: 2px; - border-top-right-radius: 2px; -} - -/* ICON - CHAT */ -.icon.chat { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 14px; - height: 10px; -} - -.icon.chat::after, -.icon.chat::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - border-radius: 3px; - height: 2px; - background: currentColor; -} - -.icon.chat::before { - width: 10px; - opacity: 0.5; - box-shadow: 0 4px 0; -} - -.icon.chat::after { - width: 14px; - bottom: 0; -} - -/* ICON - CIRCLE */ -.icon.circle { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 19px; - height: 19px; - border: 2px solid; - border-radius: 100px; -} - -/* ICON - CLOSE */ -.icon.close { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: var(--border-radius); -} - -.icon.close::after, -.icon.close::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 12px; - height: 2px; - background: currentColor; - transform: rotate(45deg); - border-radius: var(--border-radius); - top: 8px; - left: 3px; -} - -.icon.close::after { - transform: rotate(-45deg); -} - -/* ICON - CONTROLLER */ -.icon.controller { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 8px; - height: 8px; - border: 2px solid; - border-radius: 100px; -} - -.icon.controller::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 14px; - height: 14px; - box-shadow: - -6px -6px 0 -4px, - 6px 6px 0 -4px, - 6px -6px 0 -4px, - -6px 6px 0 -4px; - left: -5px; - top: -5px; - transform: rotate(45deg); -} - -/* ICON - DOWNLOAD */ -.icon.download { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 6px; - border: 2px solid; - border-top: 0; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; - margin-top: 8px; -} - -.icon.download::after { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border-left: 2px solid; - border-bottom: 2px solid; - transform: rotate(-45deg); - left: 2px; - bottom: 4px; -} - -.icon.download::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - border-radius: 3px; - width: 2px; - height: 10px; - background: currentColor; - left: 5px; - bottom: 5px; -} - -/* ICON - ESSAY */ -.icon.essay { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 18px; - border: 2px solid; - border-radius: 3px; - box-shadow: 0 -1px 0; -} - -.icon.essay::after, -.icon.essay::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 6px; - top: 2px; -} - -.icon.essay::before { - background: currentColor; - left: 2px; - box-shadow: - 0 4px 0, - 0 8px 0; - border-radius: 3px; - height: 2px; -} - -.icon.essay::after { - height: 10px; - border: 2px solid; - right: 2px; - border-radius: 1px; -} - -/* ICON - EXCHANGE */ -.icon.exchange, -.icon.exchange::after, -.icon.exchange::before { - display: block; - box-sizing: border-box; - width: 8px; - height: 8px; -} - -.icon.exchange { - position: relative; - transform: scale(var(--icon-scale, 1)); - box-shadow: - -3px 3px 0 -1px, - 3px -3px 0 -1px; -} - -.icon.exchange::after, -.icon.exchange::before { - content: ""; - position: absolute; - border: 2px solid; -} - -.icon.exchange::before { - top: -5px; - left: -5px; -} - -.icon.exchange::after { - bottom: -5px; - right: -5px; -} - -/* ICON - FORUM */ -.icon.forum { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 14px; - border-bottom: 2px solid; -} - -.icon.forum::after, -.icon.forum::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - top: 2px; -} - -.icon.forum::before { - border-left: 4px solid; - left: 1px; - width: 0; - height: 0; - border-top: 3px solid transparent; - border-bottom: 3px solid transparent; -} - -.icon.forum::after { - width: 8px; - height: 6px; - border-top: 2px solid; - border-bottom: 2px solid; - right: 0; -} - -/* ICON - FORWARD */ -.icon.forward-copy { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 16px; - box-shadow: 6px -6px 0 -4px; -} - -.icon.forward-copy::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border: 2px solid; - border-radius: 1px; - left: 0; - bottom: 0; -} - -.icon.forward-copy::after { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - background: currentColor; - width: 2px; - height: 10px; - transform: rotate(45deg); - bottom: 8px; - right: 2px; - border-radius: 4px; -} - -/* ICON - HOME */ -.icon.home { - background: - linear-gradient(to left, currentColor 5px, transparent 0) no-repeat 0 bottom/4px 2px, - linear-gradient(to left, currentColor 5px, transparent 0) no-repeat right bottom/4px 2px; - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 18px; - height: 14px; - border: 2px solid; - border-top: 0; - border-bottom: 0; - border-top-right-radius: 3px; - border-top-left-radius: 3px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - margin-bottom: -2px; -} - -.icon.home::after, -.icon.home::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; -} - -.icon.home::before { - border-top: 2px solid; - border-left: 2px solid; - border-top-left-radius: 4px; - transform: rotate(45deg); - top: -5px; - border-radius: 3px; - width: 14px; - height: 14px; - left: 0; -} - -.icon.home::after { - width: 8px; - height: 10px; - border: 2px solid; - border-radius: 100px; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - border-bottom: 0; - left: 3px; - bottom: 0; -} - -/* ICON - LIVE */ -.icon.live { - transform: scale(var(--icon-scale, 1)); -} - -.icon.live, -.icon.live::after, -.icon.live::before { - box-sizing: border-box; - position: relative; - display: block; - width: 14px; - height: 14px; - border: 2px solid; - border-bottom-color: transparent; - border-radius: 50%; -} - -.icon.live::after, -.icon.live::before { - content: ""; - position: absolute; - width: 6px; - height: 6px; - top: 2px; - left: 2px; -} - -.icon.live::after { - width: 22px; - height: 22px; - top: -6px; - left: -6px; -} - -/* ICON - MINUS */ -.icon.minus { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 2px; - background: currentColor; - border-radius: 10px; -} - -/* ICON - MORE */ -.icon.more { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 24px; - height: 20px; - border: 2px solid; - border-radius: 3px; -} - -.icon.more::before { - content: ""; - position: absolute; - box-sizing: border-box; - display: block; - width: 4px; - height: 4px; - background-color: currentColor; - border-radius: 20px; - top: 6px; - left: 8px; - box-shadow: - -5px 0 0, - 5px 0 0; -} - -/* ICON - MOREBORDERLESS */ -.icon.more-borderless { - transform: scale(var(--icon-scale, 1)); -} - -.icon.more-borderless, -.icon.more-borderless::after, -.icon.more-borderless::before { - box-sizing: border-box; - position: relative; - display: block; - width: 4px; - height: 4px; - background: currentColor; - border-radius: 100%; -} - -.icon.more-borderless::after, -.icon.more-borderless::before { - content: ""; - position: absolute; - top: 0; -} - -.icon.more-borderless::after { - left: -6px; -} - -.icon.more-borderless::before { - right: -6px; -} - -/* ICON - MORECIRCLE */ -.icon.more-circle { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 24px; - height: 24px; - border: 2px solid; - border-radius: 24px; -} - -.icon.more-circle::before { - content: ""; - position: absolute; - box-sizing: border-box; - display: block; - width: 4px; - height: 4px; - background-color: currentColor; - border-radius: 20px; - top: 8px; - left: 8px; - box-shadow: - -5px 0 0, - 5px 0 0; -} - -/* ICON - PHONE */ -.icon.phone { - box-sizing: border-box; - position: relative; - display: block; - width: 22px; - height: 22px; - transform: scale(var(--icon-scale, 1)); -} - -.icon.phone::after, -.icon.phone::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; -} - -.icon.phone::after { - width: 18px; - height: 18px; - border-top-left-radius: 1px; - border-bottom-right-radius: 1px; - border-bottom-left-radius: 12px; - border-left: 4px solid; - border-bottom: 4px solid; - left: 2px; - bottom: 2px; - background: - linear-gradient(to left, currentColor 10px, transparent 0) no-repeat right 11px/6px 4px, - linear-gradient(to left, currentColor 10px, transparent 0) no-repeat -1px 0/4px 6px; -} - -.icon.phone::before { - width: 20px; - height: 20px; - border: 6px double; - border-top-color: transparent; - border-bottom-color: transparent; - border-left-color: transparent; - border-radius: 50%; - transform: rotate(-45deg); - bottom: 2px; - left: 2px; -} - -/* ICON - PLUS */ -.icon.plus, -.icon.plus::after, -.icon.plus::before { - display: block; - box-sizing: border-box; -} - -.icon.plus::after, -.icon.plus::before { - border-radius: 10px; - background: currentColor; -} - -.icon.plus { - position: relative; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 16px; -} - -.icon.plus::after { - content: ""; - position: absolute; - width: 2px; - height: 16px; - top: 0; - left: 7px; -} - -.icon.plus::before { - content: ""; - position: absolute; - width: 16px; - height: 2px; - top: 7px; - left: 0; -} - -/* ICON - REPLY */ -.icon.reply { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 16px; - height: 16px; - box-shadow: -6px -6px 0 -4px; -} - -.icon.reply::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border: 2px solid; - border-radius: 1px; - right: 0; - bottom: 0; -} - -.icon.reply::after { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - background: currentColor; - width: 2px; - height: 10px; - transform: rotate(-45deg); - bottom: 8px; - left: 2px; - border-radius: 4px; -} - -/* ICON - RESOURCES */ -.icon.resources, -.icon.resources::after { - display: block; - box-sizing: border-box; - border-radius: 22px; -} - -.icon.resources { - position: relative; - transform: scale(var(--icon-scale, 1)); - width: 20px; - height: 20px; - border: 2px solid transparent; -} - -.icon.resources::after { - content: ""; - position: absolute; - width: 4px; - height: 4px; - background: currentColor; - top: 6px; - left: 6px; - box-shadow: - 0 7px 0 1px, - 0 -7px 0 1px, - -7px 0 0 1px, - 7px 0 0 1px; -} - -/* ICON - SEND */ -.icon.send { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 4px; -} - -.icon.send::after, -.icon.send::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 2px; - height: 8px; - border-right: 2px solid; - top: 5px; - right: 5px; -} - -.icon.send::after { - width: 6px; - height: 6px; - border-bottom: 2px solid; - transform: rotate(-45deg); - right: 9px; - top: 6px; -} - -/* ICON - TALK */ -.icon.talk { - transform: scale(var(--icon-scale, 1)); -} - -.icon.talk, -.icon.talk::after { - box-sizing: border-box; - position: relative; - display: block; - width: 20px; - height: 20px; - border-radius: 100px; - border: 2px dotted currentColor; -} - -.icon.talk::after { - content: ""; - position: absolute; - width: 8px; - height: 8px; - border: 1px solid transparent; - top: 4px; - left: 4px; - box-shadow: - 0 0 0 2px, - inset 0 0 0 2px currentColor; -} - -/* ICON - TRASH */ -.icon.trash { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 10px; - height: 12px; - border: 2px solid transparent; - box-shadow: - 0 0 0 2px, - inset -2px 0 0, - inset 2px 0 0; - border-bottom-left-radius: 1px; - border-bottom-right-radius: 1px; - margin-top: 4px; -} - -.icon.trash::after, -.icon.trash::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; -} - -.icon.trash::after { - background: currentColor; - border-radius: 3px; - width: 16px; - height: 2px; - top: -4px; - left: -5px; -} - -.icon.trash::before { - width: 10px; - height: 4px; - border: 2px solid; - border-bottom: transparent; - border-top-left-radius: 2px; - border-top-right-radius: 2px; - top: -7px; - left: -2px; -} - -/* ICON - USER */ -.icon.user, -.icon.user::after, -.icon.user::before { - display: block; - box-sizing: border-box; - border: 2px solid; - border-radius: 100px; -} - -.icon.user { - overflow: hidden; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - position: relative; -} - -.icon.user::after, -.icon.user::before { - content: ""; - position: absolute; - top: 2px; - left: 5px; - width: 8px; - height: 8px; -} - -.icon.user::after { - border-radius: 200px; - top: 11px; - left: 0px; - width: 18px; - height: 18px; -} - -/* ICON - WORK */ -.icon.work { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 20px; - height: 20px; - border: 2px solid; - border-radius: 22px; -} - -.icon.work::after, -.icon.work::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; -} - -.icon.work::before { - width: 12px; - height: 6px; - border: 2px solid; - border-top-left-radius: 100px; - border-top-right-radius: 100px; - top: 2px; - left: 2px; - border-bottom: 0; -} - -.icon.work::after { - width: 18px; - height: 2px; - background: currentColor; - left: -1px; - top: 8px; -} - -/* ICONS - RIGHT/LEFT */ -.icon.right { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; -} - -.icon.right::after, -.icon.right::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border-right: 2px solid; - border-top: 2px solid; - transform: rotate(45deg); - top: 7px; - right: 6px; -} - -.icon.right::after { - right: 11px; -} - -.icon.left { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; -} - -.icon.left::after, -.icon.left::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border-left: 2px solid; - border-bottom: 2px solid; - transform: rotate(45deg); - top: 7px; - left: 6px; -} - -.icon.left::after { - left: 11px; -} - -.icon.map-pin { - box-sizing: border-box; - position: relative; - display: block; - transform: rotate(45deg) scale(var(--icon-scale, 1)); - width: 18px; - height: 18px; - border-radius: 100% 100% 0 100%; - border: 2px solid; - margin-top: -4px; -} - -.icon.map-pin::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 8px; - height: 8px; - border: 2px solid; - top: 3px; - left: 3px; - border-radius: 40px; -} - - -/* AUDIO PLAYER ICONS */ -.icon.skip-back { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 4px; -} - -.icon.skip-back::after, -.icon.skip-back::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - height: 8px; - top: 5px; -} - -.icon.skip-back::before { - width: 2px; - border-radius: 2px; - right: 11px; - background: currentColor; -} - -.icon.skip-back::after { - width: 0; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - border-right: 5px solid; - right: 5px; -} - -.icon.rewind { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - border: 2px solid; - border-radius: 4px; - width: 22px; - height: 22px; -} - -.icon.rewind::after, -.icon.rewind::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 6px; - height: 6px; - border-left: 2px solid; - border-bottom: 2px solid; - transform: rotate(45deg); - top: 6px; - left: 5px; -} - -.icon.rewind::after { - left: 9px; -} - -.icon.play { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 4px; -} - -.icon.play::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 0; - height: 10px; - border-top: 5px solid transparent; - border-bottom: 5px solid transparent; - border-left: 6px solid; - top: 4px; - left: 7px; -} - -.icon.pause { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 4px; -} - -.icon.pause::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 6px; - height: 6px; - left: 6px; - top: 6px; - border-left: 2px solid; - border-right: 2px solid; -} - -.icon.fastforward { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - border: 2px solid; - border-radius: 4px; - width: 22px; - height: 22px; -} - -.icon.fastforward::after, -.icon.fastforward::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 6px; - height: 6px; - border-right: 2px solid; - border-top: 2px solid; - transform: rotate(45deg); - top: 6px; - right: 5px; -} - -.icon.fastforward::after { - right: 9px; -} - -.icon.skip-forward { - box-sizing: border-box; - position: relative; - display: block; - transform: scale(var(--icon-scale, 1)); - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 4px; -} - -.icon.skip-forward::after, -.icon.skip-forward::before { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - height: 8px; - top: 5px; -} - -.icon.skip-forward::before { - width: 2px; - border-radius: 2px; - left: 11px; - background: currentColor; -} - -.icon.skip-forward::after { - width: 0; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - border-left: 5px solid; - left: 5px; -} diff --git a/public/foo/index.html b/public/foo/index.html deleted file mode 100644 index 42d2802..0000000 --- a/public/foo/index.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -

Hello World - foo

- - diff --git a/public/icons.css b/public/icons.css new file mode 100644 index 0000000..56e8a15 --- /dev/null +++ b/public/icons.css @@ -0,0 +1,1286 @@ +/* ICONS */ +.icon { + width: 24px; + height: 24px; + transform: scale(var(--icon-scale, 1)); + + stroke: white; + fill: transparent; + stroke-width: 1pt; + stroke-miterlimit: 10; + stroke-linecap: round; + stroke-linejoin: round; + stroke-dasharray: 400; + + margin: 0 auto; +} + +/* ICON - ADD (with box) */ +.icon.add { + box-sizing: border-box; + position: relative; + display: block; + width: 22px; + height: 22px; + border: 2px solid; + transform: scale(var(--icon-scale, 1)); + border-radius: 4px; +} + +.icon.add::after, +.icon.add::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 10px; + height: 2px; + background: currentColor; + border-radius: 5px; + top: 8px; + left: 4px; +} + +.icon.add::after { + width: 2px; + height: 10px; + top: 4px; + left: 8px; +} + +/* ICON - ATTACHMENT */ +.icon.attachment { + box-sizing: border-box; + position: relative; + display: block; + width: 14px; + height: 14px; + border: 2px solid; + border-top: 0; + border-bottom-left-radius: 100px; + border-bottom-right-radius: 100px; + transform: scale(var(--icon-scale, 1)); + margin-top: 11px; +} + +.icon.attachment::after, +.icon.attachment::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + border-radius: 3px; + border: 2px solid; +} + +.icon.attachment::after { + border-bottom: 0; + border-top-left-radius: 100px; + border-top-right-radius: 100px; + right: -2px; + width: 10px; + height: 14px; + bottom: 8px; +} + +.icon.attachment::before { + width: 6px; + height: 12px; + border-top: 0; + border-bottom-left-radius: 100px; + border-bottom-right-radius: 100px; + left: 2px; + bottom: 4px; +} + +/* ICON - BLURB */ +.icon.blurb { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + border: 2px solid; + border-radius: 3px; + width: 22px; + height: 16px; +} + +.icon.blurb::after, +.icon.blurb::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + height: 2px; + border-radius: 3px; + background: currentColor; + bottom: 2px; +} + +.icon.blurb::before { + width: 10px; + left: 2px; + box-shadow: 4px -4px 0; +} + +.icon.blurb::after { + width: 3px; + right: 2px; + box-shadow: -11px -4px 0; +} + +/* ICON - CALENDAR */ +.icon.calendar, +.icon.calendar::before { + display: block; + box-sizing: border-box; +} + +.icon.calendar { + position: relative; + transform: scale(var(--icon-scale, 1)); + width: 18px; + height: 18px; + border: 2px solid; + border-top: 4px solid; + border-radius: 3px; +} + +.icon.calendar::before { + content: ""; + position: absolute; + width: 10px; + border-radius: 3px; + left: 2px; + background: currentColor; + height: 2px; + top: 2px; +} + +/* ICON - CAMERA */ +.icon.camera { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + border: 2px solid; + border-radius: 3px; + width: 18px; + height: 12px; + perspective: 24px; +} + +.icon.camera::after, +.icon.camera::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +.icon.camera::before { + border: 2px solid; + border-left-color: transparent; + transform: rotateY(-70deg); + width: 8px; + height: 8px; + right: -7px; + top: 0; +} + +.icon.camera::after { + width: 10px; + height: 5px; + border-top: 2px solid; + border-right: 2px solid; + top: -5px; + right: 2px; + border-top-right-radius: 2px; +} + +/* ICON - CHAT */ +.icon.chat { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 14px; + height: 10px; +} + +.icon.chat::after, +.icon.chat::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + border-radius: 3px; + height: 2px; + background: currentColor; +} + +.icon.chat::before { + width: 10px; + opacity: 0.5; + box-shadow: 0 4px 0; +} + +.icon.chat::after { + width: 14px; + bottom: 0; +} + +/* ICON - CIRCLE */ +.icon.circle { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 19px; + height: 19px; + border: 2px solid; + border-radius: 100px; +} + +/* ICON - CLOSE */ +.icon.close { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: var(--border-radius); +} + +.icon.close::after, +.icon.close::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 12px; + height: 2px; + background: currentColor; + transform: rotate(45deg); + border-radius: var(--border-radius); + top: 8px; + left: 3px; +} + +.icon.close::after { + transform: rotate(-45deg); +} + +/* ICON - CONTROLLER */ +.icon.controller { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 8px; + height: 8px; + border: 2px solid; + border-radius: 100px; +} + +.icon.controller::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 14px; + height: 14px; + box-shadow: + -6px -6px 0 -4px, + 6px 6px 0 -4px, + 6px -6px 0 -4px, + -6px 6px 0 -4px; + left: -5px; + top: -5px; + transform: rotate(45deg); +} + +/* ICON - DOWNLOAD */ +.icon.download { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 6px; + border: 2px solid; + border-top: 0; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + margin-top: 8px; +} + +.icon.download::after { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border-left: 2px solid; + border-bottom: 2px solid; + transform: rotate(-45deg); + left: 2px; + bottom: 4px; +} + +.icon.download::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + border-radius: 3px; + width: 2px; + height: 10px; + background: currentColor; + left: 5px; + bottom: 5px; +} + +/* ICON - ESSAY */ +.icon.essay { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 18px; + border: 2px solid; + border-radius: 3px; + box-shadow: 0 -1px 0; +} + +.icon.essay::after, +.icon.essay::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 6px; + top: 2px; +} + +.icon.essay::before { + background: currentColor; + left: 2px; + box-shadow: + 0 4px 0, + 0 8px 0; + border-radius: 3px; + height: 2px; +} + +.icon.essay::after { + height: 10px; + border: 2px solid; + right: 2px; + border-radius: 1px; +} + +/* ICON - EXCHANGE */ +.icon.exchange, +.icon.exchange::after, +.icon.exchange::before { + display: block; + box-sizing: border-box; + width: 8px; + height: 8px; +} + +.icon.exchange { + position: relative; + transform: scale(var(--icon-scale, 1)); + box-shadow: + -3px 3px 0 -1px, + 3px -3px 0 -1px; +} + +.icon.exchange::after, +.icon.exchange::before { + content: ""; + position: absolute; + border: 2px solid; +} + +.icon.exchange::before { + top: -5px; + left: -5px; +} + +.icon.exchange::after { + bottom: -5px; + right: -5px; +} + +/* ICON - FORUM */ +.icon.forum { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 14px; + border-bottom: 2px solid; +} + +.icon.forum::after, +.icon.forum::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + top: 2px; +} + +.icon.forum::before { + border-left: 4px solid; + left: 1px; + width: 0; + height: 0; + border-top: 3px solid transparent; + border-bottom: 3px solid transparent; +} + +.icon.forum::after { + width: 8px; + height: 6px; + border-top: 2px solid; + border-bottom: 2px solid; + right: 0; +} + +/* ICON - FORWARD */ +.icon.forward-copy { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 16px; + box-shadow: 6px -6px 0 -4px; +} + +.icon.forward-copy::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border: 2px solid; + border-radius: 1px; + left: 0; + bottom: 0; +} + +.icon.forward-copy::after { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + background: currentColor; + width: 2px; + height: 10px; + transform: rotate(45deg); + bottom: 8px; + right: 2px; + border-radius: 4px; +} + +/* ICON - HOME */ +.icon.home { + background: + linear-gradient(to left, currentColor 5px, transparent 0) no-repeat 0 bottom/4px 2px, + linear-gradient(to left, currentColor 5px, transparent 0) no-repeat right bottom/4px 2px; + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 18px; + height: 14px; + border: 2px solid; + border-top: 0; + border-bottom: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + margin-bottom: -2px; +} + +.icon.home::after, +.icon.home::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +.icon.home::before { + border-top: 2px solid; + border-left: 2px solid; + border-top-left-radius: 4px; + transform: rotate(45deg); + top: -5px; + border-radius: 3px; + width: 14px; + height: 14px; + left: 0; +} + +.icon.home::after { + width: 8px; + height: 10px; + border: 2px solid; + border-radius: 100px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom: 0; + left: 3px; + bottom: 0; +} + +/* ICON - LIVE */ +.icon.live { + transform: scale(var(--icon-scale, 1)); +} + +.icon.live, +.icon.live::after, +.icon.live::before { + box-sizing: border-box; + position: relative; + display: block; + width: 14px; + height: 14px; + border: 2px solid; + border-bottom-color: transparent; + border-radius: 50%; +} + +.icon.live::after, +.icon.live::before { + content: ""; + position: absolute; + width: 6px; + height: 6px; + top: 2px; + left: 2px; +} + +.icon.live::after { + width: 22px; + height: 22px; + top: -6px; + left: -6px; +} + +/* ICON - MINUS */ +.icon.minus { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 2px; + background: currentColor; + border-radius: 10px; +} + +/* ICON - MORE */ +.icon.more { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 24px; + height: 20px; + border: 2px solid; + border-radius: 3px; +} + +.icon.more::before { + content: ""; + position: absolute; + box-sizing: border-box; + display: block; + width: 4px; + height: 4px; + background-color: currentColor; + border-radius: 20px; + top: 6px; + left: 8px; + box-shadow: + -5px 0 0, + 5px 0 0; +} + +/* ICON - MOREBORDERLESS */ +.icon.more-borderless { + transform: scale(var(--icon-scale, 1)); +} + +.icon.more-borderless, +.icon.more-borderless::after, +.icon.more-borderless::before { + box-sizing: border-box; + position: relative; + display: block; + width: 4px; + height: 4px; + background: currentColor; + border-radius: 100%; +} + +.icon.more-borderless::after, +.icon.more-borderless::before { + content: ""; + position: absolute; + top: 0; +} + +.icon.more-borderless::after { + left: -6px; +} + +.icon.more-borderless::before { + right: -6px; +} + +/* ICON - MORECIRCLE */ +.icon.more-circle { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 24px; + height: 24px; + border: 2px solid; + border-radius: 24px; +} + +.icon.more-circle::before { + content: ""; + position: absolute; + box-sizing: border-box; + display: block; + width: 4px; + height: 4px; + background-color: currentColor; + border-radius: 20px; + top: 8px; + left: 8px; + box-shadow: + -5px 0 0, + 5px 0 0; +} + +/* ICON - PHONE */ +.icon.phone { + box-sizing: border-box; + position: relative; + display: block; + width: 22px; + height: 22px; + transform: scale(var(--icon-scale, 1)); +} + +.icon.phone::after, +.icon.phone::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +.icon.phone::after { + width: 18px; + height: 18px; + border-top-left-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 12px; + border-left: 4px solid; + border-bottom: 4px solid; + left: 2px; + bottom: 2px; + background: + linear-gradient(to left, currentColor 10px, transparent 0) no-repeat right 11px/6px 4px, + linear-gradient(to left, currentColor 10px, transparent 0) no-repeat -1px 0/4px 6px; +} + +.icon.phone::before { + width: 20px; + height: 20px; + border: 6px double; + border-top-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; + border-radius: 50%; + transform: rotate(-45deg); + bottom: 2px; + left: 2px; +} + +/* ICON - PLUS */ +.icon.plus, +.icon.plus::after, +.icon.plus::before { + display: block; + box-sizing: border-box; +} + +.icon.plus::after, +.icon.plus::before { + border-radius: 10px; + background: currentColor; +} + +.icon.plus { + position: relative; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 16px; +} + +.icon.plus::after { + content: ""; + position: absolute; + width: 2px; + height: 16px; + top: 0; + left: 7px; +} + +.icon.plus::before { + content: ""; + position: absolute; + width: 16px; + height: 2px; + top: 7px; + left: 0; +} + +/* ICON - REPLY */ +.icon.reply { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 16px; + height: 16px; + box-shadow: -6px -6px 0 -4px; +} + +.icon.reply::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border: 2px solid; + border-radius: 1px; + right: 0; + bottom: 0; +} + +.icon.reply::after { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + background: currentColor; + width: 2px; + height: 10px; + transform: rotate(-45deg); + bottom: 8px; + left: 2px; + border-radius: 4px; +} + +/* ICON - RESOURCES */ +.icon.resources, +.icon.resources::after { + display: block; + box-sizing: border-box; + border-radius: 22px; +} + +.icon.resources { + position: relative; + transform: scale(var(--icon-scale, 1)); + width: 20px; + height: 20px; + border: 2px solid transparent; +} + +.icon.resources::after { + content: ""; + position: absolute; + width: 4px; + height: 4px; + background: currentColor; + top: 6px; + left: 6px; + box-shadow: + 0 7px 0 1px, + 0 -7px 0 1px, + -7px 0 0 1px, + 7px 0 0 1px; +} + +/* ICON - SEND */ +.icon.send { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 4px; +} + +.icon.send::after, +.icon.send::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 2px; + height: 8px; + border-right: 2px solid; + top: 5px; + right: 5px; +} + +.icon.send::after { + width: 6px; + height: 6px; + border-bottom: 2px solid; + transform: rotate(-45deg); + right: 9px; + top: 6px; +} + +/* ICON - TALK */ +.icon.talk { + transform: scale(var(--icon-scale, 1)); +} + +.icon.talk, +.icon.talk::after { + box-sizing: border-box; + position: relative; + display: block; + width: 20px; + height: 20px; + border-radius: 100px; + border: 2px dotted currentColor; +} + +.icon.talk::after { + content: ""; + position: absolute; + width: 8px; + height: 8px; + border: 1px solid transparent; + top: 4px; + left: 4px; + box-shadow: + 0 0 0 2px, + inset 0 0 0 2px currentColor; +} + +/* ICON - TRASH */ +.icon.trash { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 10px; + height: 12px; + border: 2px solid transparent; + box-shadow: + 0 0 0 2px, + inset -2px 0 0, + inset 2px 0 0; + border-bottom-left-radius: 1px; + border-bottom-right-radius: 1px; + margin-top: 4px; +} + +.icon.trash::after, +.icon.trash::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +.icon.trash::after { + background: currentColor; + border-radius: 3px; + width: 16px; + height: 2px; + top: -4px; + left: -5px; +} + +.icon.trash::before { + width: 10px; + height: 4px; + border: 2px solid; + border-bottom: transparent; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + top: -7px; + left: -2px; +} + +/* ICON - USER */ +.icon.user, +.icon.user::after, +.icon.user::before { + display: block; + box-sizing: border-box; + border: 2px solid; + border-radius: 100px; +} + +.icon.user { + overflow: hidden; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + position: relative; +} + +.icon.user::after, +.icon.user::before { + content: ""; + position: absolute; + top: 2px; + left: 5px; + width: 8px; + height: 8px; +} + +.icon.user::after { + border-radius: 200px; + top: 11px; + left: 0px; + width: 18px; + height: 18px; +} + +/* ICON - WORK */ +.icon.work { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 20px; + height: 20px; + border: 2px solid; + border-radius: 22px; +} + +.icon.work::after, +.icon.work::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; +} + +.icon.work::before { + width: 12px; + height: 6px; + border: 2px solid; + border-top-left-radius: 100px; + border-top-right-radius: 100px; + top: 2px; + left: 2px; + border-bottom: 0; +} + +.icon.work::after { + width: 18px; + height: 2px; + background: currentColor; + left: -1px; + top: 8px; +} + +/* ICONS - RIGHT/LEFT */ +.icon.right { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; +} + +.icon.right::after, +.icon.right::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border-right: 2px solid; + border-top: 2px solid; + transform: rotate(45deg); + top: 7px; + right: 6px; +} + +.icon.right::after { + right: 11px; +} + +.icon.left { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; +} + +.icon.left::after, +.icon.left::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border-left: 2px solid; + border-bottom: 2px solid; + transform: rotate(45deg); + top: 7px; + left: 6px; +} + +.icon.left::after { + left: 11px; +} + +.icon.map-pin { + box-sizing: border-box; + position: relative; + display: block; + transform: rotate(45deg) scale(var(--icon-scale, 1)); + width: 18px; + height: 18px; + border-radius: 100% 100% 0 100%; + border: 2px solid; + margin-top: -4px; +} + +.icon.map-pin::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 8px; + height: 8px; + border: 2px solid; + top: 3px; + left: 3px; + border-radius: 40px; +} + + +/* AUDIO PLAYER ICONS */ +.icon.skip-back { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 4px; +} + +.icon.skip-back::after, +.icon.skip-back::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + height: 8px; + top: 5px; +} + +.icon.skip-back::before { + width: 2px; + border-radius: 2px; + right: 11px; + background: currentColor; +} + +.icon.skip-back::after { + width: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 5px solid; + right: 5px; +} + +.icon.rewind { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + border: 2px solid; + border-radius: 4px; + width: 22px; + height: 22px; +} + +.icon.rewind::after, +.icon.rewind::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 6px; + height: 6px; + border-left: 2px solid; + border-bottom: 2px solid; + transform: rotate(45deg); + top: 6px; + left: 5px; +} + +.icon.rewind::after { + left: 9px; +} + +.icon.play { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 4px; +} + +.icon.play::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 10px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 6px solid; + top: 4px; + left: 7px; +} + +.icon.pause { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 4px; +} + +.icon.pause::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 6px; + height: 6px; + left: 6px; + top: 6px; + border-left: 2px solid; + border-right: 2px solid; +} + +.icon.fastforward { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + border: 2px solid; + border-radius: 4px; + width: 22px; + height: 22px; +} + +.icon.fastforward::after, +.icon.fastforward::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 6px; + height: 6px; + border-right: 2px solid; + border-top: 2px solid; + transform: rotate(45deg); + top: 6px; + right: 5px; +} + +.icon.fastforward::after { + right: 9px; +} + +.icon.skip-forward { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(var(--icon-scale, 1)); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 4px; +} + +.icon.skip-forward::after, +.icon.skip-forward::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + height: 8px; + top: 5px; +} + +.icon.skip-forward::before { + width: 2px; + border-radius: 2px; + left: 11px; + background: currentColor; +} + +.icon.skip-forward::after { + width: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 5px solid; + left: 5px; +} diff --git a/public/index.html b/public/index.html index 2b5a262..09d55ed 100644 --- a/public/index.html +++ b/public/index.html @@ -10,6 +10,7 @@ + diff --git a/public/signup_login_wall.html b/public/signup_login_wall.html index 23eb841..a1bc6ce 100644 --- a/public/signup_login_wall.html +++ b/public/signup_login_wall.html @@ -17,19 +17,9 @@ } #auth-container { - width: 95%; - max-height: calc(min(90vh,900px)); - border-radius: 10px; position: relative; - background: var(--bg-lighter); - max-width: 40em; - margin: 0 auto; - border-radius: calc( var(--border-radius) * 2.5); - padding: 2em 1em; + padding: 8em 4em; overflow-y: scroll; - - transition: all 0.33s ease; - animation: zoomsettle 0.4s ease; } #signup-tab, From a2e035830c4bc9bd814b71cecceaaf2e70eb7d33 Mon Sep 17 00:00:00 2001 From: Timothy Ristau Date: Mon, 9 Mar 2026 14:32:35 -0400 Subject: [PATCH 2/4] First draft of UX issues --- ISSUES.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 ISSUES.md diff --git a/ISSUES.md b/ISSUES.md new file mode 100644 index 0000000..54a9fad --- /dev/null +++ b/ISSUES.md @@ -0,0 +1,70 @@ +# Issues + + +## Creating Channels +* Creating a channel is weird from a UX perspective. You it the plus arrow and a textfield comes up but there isn't any indication on how to submit it (hitting enter works but not have a button is a weird UX) +* Hitting the plus icon again hides the text field but doesn't clear the value +* The plus button works as a visibility toggle but doesn't change from + to -. I would add a + button next to the Channels title which opens a mini form that has a text field with a create and cancel button. You can have the ESC key close the dialog but there should be clear buttons on what does what. + + +## Chatting + +* Attaching files doesn't really show whats happening, there should be a preview (whether link or image or whatever). +* The change bar should have a dragable area to drop files into +* The file upload currently accepts anything it seams but creating local links +* By default it seems 'react' gives a permission error? It also has a weird assortment of emoji's by default. + + +## Blurbs + +* + button acts as hide/show toggle but doesn't change to - or whatever when it is shown +* hiding blurb doesn't clear fields +* character count seems to keep previous character count after blurb +* Need a filter and sort feature so you can see blubs by topic or user. +* Need a subscription feature with notifications so you can see what a user is saying +* Need a read/notread feature so users can filter out read blurbs +* Is the goal to be able to repond to blurbs? +* Hastags? +* Sharing and linking to Chats, Essays, and Forums + +## Forum + +* If this is supposed to be like a BBS forum should there be folders and/or topics? +* Need a way to respond +* Need a way to see unread posts +* Need a way to search, filter/subscribe and hide +* Do Forums need admins or owners who can block users, delete posts, etc? +* Sharing and linking to Chats, Essays, and Forums + +## Essays + +* Need a way to see unread posts +* Need a way to search, filter and hide +* Likes? +* Sharing and linking to Blurbs, Chats, and Forums + +## Map + +* Is the point to show where users are? If so users need to be able to set their location. +* Should users be only able to share their location with certain users or everyone + + +## General UI + +* Log out button is very large and in a weird spot. Logging out is not a common activity so it shouldn't have such prominence. +* What is the purpose of the left hand tray? Is it for eventually having access to multiple servers or just a logo? It takes up reastate without providing a use. If the server feature isn't going to exist for awhile it should be removed and the logo placed elsewhere. +* The user's avatar is very large with some properties around it. This should probably follow the more common convenstion of it being an icon in the top right and have the settings in a properties panel or or page. Once set the user isn't going to interact with the profile that much so more room should be given to common operations. +* No theme really or at least the look is very sparse. Setting just a color is find by it would be nice to have the ability to set a swatch or theme of different colors (like an IDE theme) +* Context menu icons are rough +* No server admin panel +* Need a way to admin users +* History of users actions +* Global search to find chats, blurbs, forums, or essays + +## Accessibility + + * Might need to look at the tabbing order and make sure everything is tabbable. + * hot keys for switching between areas + * Contrast is harsh for different colors in theme. Colors for buttons labels/icons should be calculated to have adequete contrast to primary color + * Light/dark theme + From 7a04d1f7af9a6326fc44d31d575df8a1bd7cd7d7 Mon Sep 17 00:00:00 2001 From: Timothy Ristau Date: Mon, 9 Mar 2026 14:36:05 -0400 Subject: [PATCH 3/4] spelling grammar --- .gitignore | 9 +++ ISSUES.md | 38 +++++---- PERMISSIONS.md | 151 +++++++++++++++++++++++++++++++++++ README.md | 2 +- public/api/auth/index.ts | 19 ++++- public/api/channels/index.ts | 2 +- public/api/users/index.ts | 3 +- 7 files changed, 197 insertions(+), 27 deletions(-) create mode 100644 PERMISSIONS.md diff --git a/.gitignore b/.gitignore index 639a628..319252b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,12 @@ data/ .fsdb* public/files/* .vscode/* + + +# tim +ABOUT.md +AGENTS.md +API.md +ARCHITECTURE.md +CONTRIBUTING.md +REVIEW.md \ No newline at end of file diff --git a/ISSUES.md b/ISSUES.md index 54a9fad..34a7501 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -2,29 +2,27 @@ ## Creating Channels -* Creating a channel is weird from a UX perspective. You it the plus arrow and a textfield comes up but there isn't any indication on how to submit it (hitting enter works but not have a button is a weird UX) +* Creating a channel is weird from a UX perspective. You hit the plus arrow and a text field comes up, but there isn't any indication of how to submit it. Hitting Enter works, but not having a button is a weird UX choice. * Hitting the plus icon again hides the text field but doesn't clear the value -* The plus button works as a visibility toggle but doesn't change from + to -. I would add a + button next to the Channels title which opens a mini form that has a text field with a create and cancel button. You can have the ESC key close the dialog but there should be clear buttons on what does what. - +* The plus button works as a visibility toggle but doesn't change from + to -. I would add a + button next to the Channels title that opens a mini form with a text field plus Create and Cancel buttons. You can have the Esc key close the dialog, but there should be clear buttons showing what does what. ## Chatting -* Attaching files doesn't really show whats happening, there should be a preview (whether link or image or whatever). -* The change bar should have a dragable area to drop files into -* The file upload currently accepts anything it seams but creating local links +* Attaching files doesn't really show what's happening; there should be a preview, whether link, image, or whatever. +* The chat bar should have a draggable area to drop files into. * By default it seems 'react' gives a permission error? It also has a weird assortment of emoji's by default. ## Blurbs -* + button acts as hide/show toggle but doesn't change to - or whatever when it is shown -* hiding blurb doesn't clear fields -* character count seems to keep previous character count after blurb -* Need a filter and sort feature so you can see blubs by topic or user. +* The + button acts as a hide/show toggle but doesn't change to - or whatever when it is shown. +* Hiding a blurb doesn't clear the fields. +* The character count seems to keep the previous count after posting a blurb. +* Need a filter and sort feature so you can see blurbs by topic or user. * Need a subscription feature with notifications so you can see what a user is saying -* Need a read/notread feature so users can filter out read blurbs -* Is the goal to be able to repond to blurbs? -* Hastags? +* Need a read/unread feature so users can filter out read blurbs +* Is the goal to be able to respond to blurbs? +* Hashtags? * Sharing and linking to Chats, Essays, and Forums ## Forum @@ -46,25 +44,25 @@ ## Map * Is the point to show where users are? If so users need to be able to set their location. -* Should users be only able to share their location with certain users or everyone +* Should users only be able to share their location with certain users, or everyone? ## General UI * Log out button is very large and in a weird spot. Logging out is not a common activity so it shouldn't have such prominence. -* What is the purpose of the left hand tray? Is it for eventually having access to multiple servers or just a logo? It takes up reastate without providing a use. If the server feature isn't going to exist for awhile it should be removed and the logo placed elsewhere. -* The user's avatar is very large with some properties around it. This should probably follow the more common convenstion of it being an icon in the top right and have the settings in a properties panel or or page. Once set the user isn't going to interact with the profile that much so more room should be given to common operations. -* No theme really or at least the look is very sparse. Setting just a color is find by it would be nice to have the ability to set a swatch or theme of different colors (like an IDE theme) +* What is the purpose of the left-hand tray? Is it for eventually having access to multiple servers, or is it just a logo? It takes up real estate without providing a use. If the server feature isn't going to exist for a while, it should be removed and the logo placed elsewhere. +* The user's avatar is very large with some properties around it. This should probably follow the more common convention of being an icon in the top right, with the settings in a properties panel or page. Once set, the user isn't going to interact with the profile that much, so more room should be given to common operations. +* There isn't really a theme, or at least the look is very sparse. Setting just a color is fine, but it would be nice to have the ability to set a swatch or theme of different colors, like an IDE theme. * Context menu icons are rough * No server admin panel * Need a way to admin users -* History of users actions +* History of user actions * Global search to find chats, blurbs, forums, or essays ## Accessibility * Might need to look at the tabbing order and make sure everything is tabbable. - * hot keys for switching between areas - * Contrast is harsh for different colors in theme. Colors for buttons labels/icons should be calculated to have adequete contrast to primary color + * Hotkeys for switching between areas + * Contrast is harsh for different colors in the theme. Colors for buttons, labels, and icons should be calculated to have adequate contrast with the primary color * Light/dark theme diff --git a/PERMISSIONS.md b/PERMISSIONS.md new file mode 100644 index 0000000..036aea1 --- /dev/null +++ b/PERMISSIONS.md @@ -0,0 +1,151 @@ +# PERMISSIONS.md + +Permission reference for `autonomous.contact`. + +This document was built by crawling the codebase for: + +- default permission assignment in [public/api/users/index.ts](public/api/users/index.ts) +- server-side permission checks in [public/api/](public/api) +- frontend permission gates in [public/tabs/](public/tabs) and related UI files + +## Sources of truth + +Current default permission sets are defined in [public/api/users/index.ts](public/api/users/index.ts#L14-L58). + +- `DEFAULT_USER_PERMISSIONS` are assigned to normal users during signup. +- `DEFAULT_SUPERUSER_PERMISSIONS` are assigned to the first/bootstrap user. + +## How permissions work + +There are two layers of access control in this codebase: + +1. **Global permission strings** stored on the user record. +2. **Object-level ACLs** stored inside resources, especially channel `permissions.read`, `permissions.write`, `permissions.events.read`, and `permissions.events.write`. + +Important consequence: a user may have a global permission and still be blocked by a channel-level ACL. + +## Generic permission families + +These are not stored as standalone permissions, but the server checks for these prefixes: + +- `events.create.*` via [public/api/events/index.ts](public/api/events/index.ts#L188) and [utils/prechecks.ts](utils/prechecks.ts#L47-L48) +- `events.write.*` via [public/api/events/:event_id/index.ts](public/api/events/:event_id/index.ts#L34-L35), [public/api/events/:event_id/index.ts](public/api/events/:event_id/index.ts#L117-L118), and [utils/prechecks.ts](utils/prechecks.ts#L50-L51) + +## Permissions bible + +| Permission | Default user | Bootstrap superuser | Purpose | Where checked | Notes | +| --- | --- | --- | --- | --- | --- | +| `channels.read` | yes | yes | Allows listing channels. | [public/api/channels/index.ts](public/api/channels/index.ts#L12) | Channel detail reads also require channel ACL membership; this permission gates the channel list endpoint only. | +| `channels.create` | no | yes | Allows creating channels. | [public/api/channels/index.ts](public/api/channels/index.ts#L31), [public/tabs/chat/channel_sidebar.html](public/tabs/chat/channel_sidebar.html#L189) | Fully wired. | +| `channels.delete` | no | yes | Intended to allow channel deletion. | Defined in [public/api/users/index.ts](public/api/users/index.ts#L51) | **No direct server-side check found.** Channel deletion currently uses `channel.permissions.write` membership instead of this string. See [public/api/channels/:channel_id/index.ts](public/api/channels/:channel_id/index.ts#L98-L100). | +| `channels.write` | no | yes | Intended to allow channel updates. | Defined in [public/api/users/index.ts](public/api/users/index.ts#L52) | **No direct server-side check found.** Channel updates currently use `channel.permissions.write` membership instead of this string. See [public/api/channels/:channel_id/index.ts](public/api/channels/:channel_id/index.ts#L45-L47). | +| `events.create.blurb` | yes | yes | Allows creating `blurb` events. | [utils/prechecks.ts](utils/prechecks.ts#L47-L48), [public/tabs/blurbs/new_blurb.html](public/tabs/blurbs/new_blurb.html#L28) | Matches server behavior. | +| `events.create.chat` | yes | yes | Allows creating `chat` events. | [utils/prechecks.ts](utils/prechecks.ts#L47-L48) | **UI mismatch:** chat composer is gated by `events.write.chat`, not `events.create.chat`. See [public/tabs/chat/chat.html](public/tabs/chat/chat.html#L151). | +| `events.create.essay` | yes | yes | Allows creating `essay` events. | [utils/prechecks.ts](utils/prechecks.ts#L47-L48), [public/tabs/essays/new_essay.html](public/tabs/essays/new_essay.html#L25) | Matches server behavior. | +| `events.create.post` | yes | yes | Allows creating `post` events. | [utils/prechecks.ts](utils/prechecks.ts#L47-L48), [public/tabs/forum/new_post.html](public/tabs/forum/new_post.html#L9) | Matches server behavior. | +| `events.create.presence` | yes | yes | Intended to allow creating `presence` events. | [utils/prechecks.ts](utils/prechecks.ts#L47-L48) | No dedicated UI or route-specific feature found beyond generic event creation. | +| `events.read.blurb` | yes | yes | Intended to allow viewing blurbs. | [public/tabs/blurbs/blurbs.html](public/tabs/blurbs/blurbs.html#L150) | **Frontend-only gate found.** No matching server-side event-read check by permission string was found. | +| `events.read.chat` | yes | yes | Intended to allow viewing chat. | [public/tabs/chat/chat.html](public/tabs/chat/chat.html#L23) | **Frontend-only gate found.** Server reads rely on authentication and channel ACLs, not this string. | +| `events.read.essay` | yes | yes | Intended to allow viewing essays. | [public/tabs/essays/essays.html](public/tabs/essays/essays.html#L126) | **Frontend-only gate found.** | +| `events.read.post` | yes | yes | Intended to allow viewing posts. | [public/tabs/forum/forum.html](public/tabs/forum/forum.html#L181) | **Frontend-only gate found.** | +| `events.read.presence` | yes | yes | Intended to allow viewing presence events. | Defined in [public/api/users/index.ts](public/api/users/index.ts#L27) | **No active check found** beyond the default assignment. | +| `events.write.blurb` | yes | yes | Allows updating/deleting `blurb` events. | [utils/prechecks.ts](utils/prechecks.ts#L50-L51) | Used by generic event update/delete endpoints. | +| `events.write.chat` | yes | yes | Allows updating/deleting `chat` events. | [utils/prechecks.ts](utils/prechecks.ts#L50-L51), [public/tabs/chat/chat.html](public/tabs/chat/chat.html#L151) | Also used by the chat composer UI, which appears to be stricter/different than server-side create rules. | +| `events.write.essay` | yes | yes | Allows updating/deleting `essay` events. | [utils/prechecks.ts](utils/prechecks.ts#L50-L51) | No dedicated UI gate found. | +| `events.write.post` | yes | yes | Allows updating/deleting `post` events. | [utils/prechecks.ts](utils/prechecks.ts#L50-L51) | No dedicated UI gate found. | +| `events.write.presence` | yes | yes | Intended to allow updating/deleting `presence` events. | [utils/prechecks.ts](utils/prechecks.ts#L50-L51) | No dedicated UI or route-specific usage found beyond generic event mutation logic. | +| `files.write.own` | yes | yes | Allows uploads only inside the current user's home path under `/files/users//...`. | [public/_pre.ts](public/_pre.ts#L12-L20) | Fully wired. | +| `files.write.all` | no | yes | Allows uploads anywhere under `/files/...`. | [public/_pre.ts](public/_pre.ts#L13-L20), [tests/11_file_uploads.test.ts](tests/11_file_uploads.test.ts#L165) | Fully wired. | +| `invites.create` | yes | yes | Allows creating invite codes. | [public/api/users/:user_id/invites/index.ts](public/api/users/:user_id/invites/index.ts#L73) | Fully wired. | +| `invites.read.own` | yes | yes | Allows reading invites for the path user when it is self. | [public/api/users/:user_id/invites/index.ts](public/api/users/:user_id/invites/index.ts#L17-L20) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `invites.read.all` | no | yes | Allows reading invites across users. | [public/api/users/:user_id/invites/index.ts](public/api/users/:user_id/invites/index.ts#L18-L20) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `self.read` | yes | yes | Allows reading the current authenticated user's own profile. | [public/api/users/me/index.ts](public/api/users/me/index.ts#L8), [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L13-L17) | Fully wired. | +| `self.write` | yes | yes | Allows updating/deleting the current user's own profile. | [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L44-L48), [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L109-L113) | Fully wired. | +| `signups.read.own` | yes | yes | Allows reading signups for the path user when it is self. | [public/api/users/:user_id/signups/index.ts](public/api/users/:user_id/signups/index.ts#L13-L16) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `signups.read.all` | no | yes | Allows reading signups across users. | [public/api/users/:user_id/signups/index.ts](public/api/users/:user_id/signups/index.ts#L14-L16) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `users.read` | yes | yes | Allows reading/searching other users. | [public/api/users/index.ts](public/api/users/index.ts#L67), [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L14-L17) | Fully wired. | +| `users.write` | no | yes | Allows updating/deleting other users and editing permissions. | [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L45), [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L81), [public/api/users/:user_id/index.ts](public/api/users/:user_id/index.ts#L110) | Fully wired. | +| `watches.create.own` | yes | yes | Allows creating watches for self. | [public/api/users/:user_id/watches/index.ts](public/api/users/:user_id/watches/index.ts#L80-L83) | Fully wired. | +| `watches.create.all` | no | no | Allows creating watches for other users. | [public/api/users/:user_id/watches/index.ts](public/api/users/:user_id/watches/index.ts#L81-L83) | **Referenced but not granted by either default permission set.** Must be assigned manually if needed. | +| `watches.read.own` | yes | yes | Allows reading watches for self. | [public/api/users/:user_id/watches/index.ts](public/api/users/:user_id/watches/index.ts#L15-L18) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `watches.read.all` | no | yes | Allows reading watches across users. | [public/api/users/:user_id/watches/index.ts](public/api/users/:user_id/watches/index.ts#L16-L18) | Route behavior currently has filtering issues; see [REVIEW.md](REVIEW.md). | +| `watches.write.own` | yes | yes | Intended to allow updating/deleting own watches. | Defined in [public/api/users/index.ts](public/api/users/index.ts#L44) | **No direct permission check found.** Watch update/delete currently use ownership only. See [public/api/users/:user_id/watches/:watch_id/index.ts](public/api/users/:user_id/watches/:watch_id/index.ts#L20-L22) and [public/api/users/:user_id/watches/:watch_id/index.ts](public/api/users/:user_id/watches/:watch_id/index.ts#L73-L75). | +| `watches.write.all` | no | yes | Intended to allow updating/deleting others' watches. | Defined in [public/api/users/index.ts](public/api/users/index.ts#L58) | **No direct permission check found.** Watch update/delete currently use ownership only. | + +## Summary: default permissions vs actual code + +### Normal-user defaults that are clearly used + +These are present in `DEFAULT_USER_PERMISSIONS` and have matching checks in code: + +- `channels.read` +- `events.create.blurb` +- `events.create.chat` +- `events.create.essay` +- `events.create.post` +- `events.create.presence` +- `events.write.blurb` +- `events.write.chat` +- `events.write.essay` +- `events.write.post` +- `events.write.presence` +- `files.write.own` +- `invites.create` +- `invites.read.own` +- `self.read` +- `self.write` +- `signups.read.own` +- `users.read` +- `watches.create.own` +- `watches.read.own` + +### Defaults that are only partially matched or frontend-only + +- `events.read.blurb` +- `events.read.chat` +- `events.read.essay` +- `events.read.post` +- `events.read.presence` +- `watches.write.own` + +### Bootstrap/superuser defaults that are present but not fully wired as permission strings + +- `channels.delete` +- `channels.write` +- `watches.write.all` + +### Referenced in code but not granted by default + +- `watches.create.all` + +## Biggest mismatches to know about + +1. **Channel update/delete do not use `channels.write` or `channels.delete`.** + They use per-channel ACL membership instead. See [public/api/channels/:channel_id/index.ts](public/api/channels/:channel_id/index.ts). + +2. **Watch update/delete do not use `watches.write.own` or `watches.write.all`.** + They use ownership checks only. See [public/api/users/:user_id/watches/:watch_id/index.ts](public/api/users/:user_id/watches/:watch_id/index.ts). + +3. **`events.read.*` permissions are mostly UI gates, not server-enforced authorization.** + The event read endpoints do not generally check these strings. + +4. **Chat creation UI uses `events.write.chat`, but the server requires `events.create.chat` for POST.** + This is the clearest create-vs-write mismatch in the current code. + +5. **`watches.create.all` exists in code but is missing from both default sets.** + +## Recommendation + +If the goal is to make permissions predictable, the cleanest next step would be to choose one of these approaches: + +1. remove unused permission strings from defaults, or +2. add explicit checks so every documented permission is actually authoritative + +The most important cleanup targets are: + +- `channels.write` +- `channels.delete` +- `watches.write.own` +- `watches.write.all` +- the `events.read.*` family +- the chat UI mismatch between `events.create.chat` and `events.write.chat` diff --git a/README.md b/README.md index b83bfc0..d3f86f6 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ feature discussions. 3) Start the server: - `deno run task serve` + `deno run serve` 4) Navigate to http://localhost:8000 diff --git a/public/api/auth/index.ts b/public/api/auth/index.ts index 7d47e32..d1b0d58 100644 --- a/public/api/auth/index.ts +++ b/public/api/auth/index.ts @@ -122,7 +122,8 @@ export async function POST(req: Request, meta: Record): Promise): Promise): Response | undefined => { const can_create_channels = meta.user.permissions.includes('channels.create'); - + console.log('User permissions:', meta.user.permissions); if (!can_create_channels) { return CANNED_RESPONSES.permission_denied(); } diff --git a/public/api/users/index.ts b/public/api/users/index.ts index b3d8c46..6730626 100644 --- a/public/api/users/index.ts +++ b/public/api/users/index.ts @@ -245,7 +245,8 @@ export async function POST(req: Request, meta: Record): Promise Date: Mon, 9 Mar 2026 14:57:11 -0700 Subject: [PATCH 4/4] refactor: require password verification chore: styling work --- deno.json | 6 +- deno.lock | 63 +++++---- public/api/events/index.ts | 7 - public/api/users/index.ts | 16 +++ public/base.css | 81 +++++++----- public/icons.css | 43 ++++++ public/js/embeds/vimeo.js | 2 +- public/js/embeds/youtube.js | 2 +- public/sidebar/sidebar.html | 8 +- public/signup_login_wall.html | 4 + public/tabs/chat/channel_sidebar.html | 2 +- public/tabs/chat/chat.css | 2 +- public/tabs/chat/chat.html | 4 +- tests/01_create_user.test.ts | 180 +++++++++++++++++++++++++- tests/helpers.ts | 12 ++ utils/prechecks.ts | 4 - 16 files changed, 348 insertions(+), 88 deletions(-) diff --git a/deno.json b/deno.json index a4b793c..beda9ac 100644 --- a/deno.json +++ b/deno.json @@ -46,10 +46,10 @@ "@andyburke/lurid": "jsr:@andyburke/lurid@^0.2.0", "@andyburke/serverus": "jsr:@andyburke/serverus@^0.16.0", "@da/bcrypt": "jsr:@da/bcrypt@^1.0.1", - "@std/assert": "jsr:@std/assert@^1.0.17", + "@std/assert": "jsr:@std/assert@^1.0.19", "@std/encoding": "jsr:@std/encoding@^1.0.10", - "@std/fs": "jsr:@std/fs@^1.0.22", - "@std/http": "jsr:@std/http@^1.0.23", + "@std/fs": "jsr:@std/fs@^1.0.23", + "@std/http": "jsr:@std/http@^1.0.25", "@std/media-types": "jsr:@std/media-types@^1.1.0", "@std/path": "jsr:@std/path@^1.1.4" } diff --git a/deno.lock b/deno.lock index 0e06569..e974966 100644 --- a/deno.lock +++ b/deno.lock @@ -6,28 +6,27 @@ "jsr:@andyburke/serverus@0.16": "0.16.0", "jsr:@da/bcrypt@*": "1.0.1", "jsr:@da/bcrypt@^1.0.1": "1.0.1", - "jsr:@std/assert@^1.0.17": "1.0.17", - "jsr:@std/cli@^1.0.19": "1.0.25", - "jsr:@std/cli@^1.0.20": "1.0.25", - "jsr:@std/cli@^1.0.21": "1.0.25", - "jsr:@std/cli@^1.0.25": "1.0.25", + "jsr:@std/assert@^1.0.19": "1.0.19", + "jsr:@std/cli@^1.0.19": "1.0.28", + "jsr:@std/cli@^1.0.20": "1.0.28", + "jsr:@std/cli@^1.0.21": "1.0.28", + "jsr:@std/cli@^1.0.28": "1.0.28", "jsr:@std/encoding@^1.0.10": "1.0.10", - "jsr:@std/fmt@^1.0.6": "1.0.8", - "jsr:@std/fmt@^1.0.8": "1.0.8", - "jsr:@std/fs@^1.0.18": "1.0.22", - "jsr:@std/fs@^1.0.19": "1.0.22", - "jsr:@std/fs@^1.0.21": "1.0.22", - "jsr:@std/fs@^1.0.22": "1.0.22", + "jsr:@std/fmt@^1.0.6": "1.0.9", + "jsr:@std/fmt@^1.0.9": "1.0.9", + "jsr:@std/fs@^1.0.18": "1.0.23", + "jsr:@std/fs@^1.0.19": "1.0.23", + "jsr:@std/fs@^1.0.23": "1.0.23", "jsr:@std/html@^1.0.5": "1.0.5", - "jsr:@std/http@^1.0.20": "1.0.23", - "jsr:@std/http@^1.0.23": "1.0.23", + "jsr:@std/http@^1.0.20": "1.0.25", + "jsr:@std/http@^1.0.25": "1.0.25", "jsr:@std/internal@^1.0.12": "1.0.12", "jsr:@std/media-types@^1.1.0": "1.1.0", "jsr:@std/net@^1.0.6": "1.0.6", "jsr:@std/path@^1.1.0": "1.1.4", "jsr:@std/path@^1.1.1": "1.1.4", "jsr:@std/path@^1.1.4": "1.1.4", - "jsr:@std/streams@^1.0.16": "1.0.16", + "jsr:@std/streams@^1.0.17": "1.0.17", "npm:@types/node@*": "22.15.15" }, "jsr": { @@ -59,23 +58,23 @@ "@da/bcrypt@1.0.1": { "integrity": "d2172d3acbcff52e0465557a1a48b1ff1c92df08c90712dae5372255a8c45eb3" }, - "@std/assert@1.0.17": { - "integrity": "df5ebfffe77c03b3fa1401e11c762cc8f603d51021c56c4d15a8c7ab45e90dbe", + "@std/assert@1.0.19": { + "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e", "dependencies": [ "jsr:@std/internal" ] }, - "@std/cli@1.0.25": { - "integrity": "1f85051b370c97a7a9dfc6ba626e7ed57a91bea8c081597276d1e78d929d8c91" + "@std/cli@1.0.28": { + "integrity": "74ef9b976db59ca6b23a5283469c9072be6276853807a83ec6c7ce412135c70a" }, "@std/encoding@1.0.10": { "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" }, - "@std/fmt@1.0.8": { - "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" + "@std/fmt@1.0.9": { + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" }, - "@std/fs@1.0.22": { - "integrity": "de0f277a58a867147a8a01bc1b181d0dfa80bfddba8c9cf2bacd6747bcec9308", + "@std/fs@1.0.23": { + "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", "dependencies": [ "jsr:@std/internal", "jsr:@std/path@^1.1.4" @@ -84,13 +83,13 @@ "@std/html@1.0.5": { "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" }, - "@std/http@1.0.23": { - "integrity": "6634e9e034c589bf35101c1b5ee5bbf052a5987abca20f903e58bdba85c80dee", + "@std/http@1.0.25": { + "integrity": "577b4252290af1097132812b339fffdd55fb0f4aeb98ff11bdbf67998aa17193", "dependencies": [ - "jsr:@std/cli@^1.0.25", + "jsr:@std/cli@^1.0.28", "jsr:@std/encoding", - "jsr:@std/fmt@^1.0.8", - "jsr:@std/fs@^1.0.21", + "jsr:@std/fmt@^1.0.9", + "jsr:@std/fs@^1.0.23", "jsr:@std/html", "jsr:@std/media-types", "jsr:@std/net", @@ -113,8 +112,8 @@ "jsr:@std/internal" ] }, - "@std/streams@1.0.16": { - "integrity": "85030627befb1767c60d4f65cb30fa2f94af1d6ee6e5b2515b76157a542e89c4" + "@std/streams@1.0.17": { + "integrity": "7859f3d9deed83cf4b41f19223d4a67661b3d3819e9fc117698f493bf5992140" } }, "npm": { @@ -137,10 +136,10 @@ "jsr:@andyburke/lurid@0.2", "jsr:@andyburke/serverus@0.16", "jsr:@da/bcrypt@^1.0.1", - "jsr:@std/assert@^1.0.17", + "jsr:@std/assert@^1.0.19", "jsr:@std/encoding@^1.0.10", - "jsr:@std/fs@^1.0.22", - "jsr:@std/http@^1.0.23", + "jsr:@std/fs@^1.0.23", + "jsr:@std/http@^1.0.25", "jsr:@std/media-types@^1.1.0", "jsr:@std/path@^1.1.4" ] diff --git a/public/api/events/index.ts b/public/api/events/index.ts index 2bf633b..41b5aa8 100644 --- a/public/api/events/index.ts +++ b/public/api/events/index.ts @@ -41,13 +41,6 @@ export async function GET(request: Request, meta: Record): Promise< event_id } = /^.*\/events\/.*\/(?.*?)\:(?[A-Za-z-]+)\.json$/.exec(entry.path)?.groups ?? {}; - console.dir({ - entry, - event_type, - event_id, - query: meta.query - }); - if (meta.query.after_id && event_id <= meta.query.after_id) { return false; } diff --git a/public/api/users/index.ts b/public/api/users/index.ts index b3d8c46..a8db076 100644 --- a/public/api/users/index.ts +++ b/public/api/users/index.ts @@ -139,6 +139,22 @@ export async function POST(req: Request, meta: Record): Promise diff --git a/public/js/embeds/youtube.js b/public/js/embeds/youtube.js index 1269d6c..5d65b6d 100644 --- a/public/js/embeds/youtube.js +++ b/public/js/embeds/youtube.js @@ -29,7 +29,7 @@ function embed_youtube(link_info) {