full page redesign; improved light theme

This commit is contained in:
ari melody 2025-07-10 16:05:21 +01:00
parent b58290b4e5
commit 2e5ddc8dc4
Signed by: ari
GPG key ID: CF99829C92678188
9 changed files with 379 additions and 284 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View file

@ -1,70 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" value="width=device-width, initial-scale=1">
<title>bliss town</title>
<link rel="icon" type="image/x-icon" href="/img/favicon.png">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" value="width=device-width, initial-scale=1">
<title>bliss town</title>
<link rel="icon" type="image/x-icon" href="/img/favicon.png">
<meta property="og:site_name" content="bliss town" />
<meta property="og:title" content="welcome to bliss town!" />
<meta property="og:image" content="https://bliss.town/img/og-icon.png" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://bliss.town" />
<meta property="og:site_name" content="bliss town" />
<meta property="og:title" content="welcome to bliss town!" />
<meta property="og:image" content="https://bliss.town/img/og-icon.png" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://bliss.town" />
<link rel="stylesheet" type="text/css" href="/style/main.css">
<script type="application/javascript" src="/script/vendor/htmx.min.js"></script>
</head>
<body>
<header>
<nav hx-boost="true" hx-target="body" hx-swap="outerHTML show:window:top">
<a href="/">home</a>
<span aria-hidden="true">-</span>
<a href="/links">links</a>
<span aria-hidden="true">-</span>
<a href="/paste">paste</a>
<span aria-hidden="true">-</span>
<a href="https://git.arimelody.me/ari/bliss.town" target="_blank">source</a>
</nav>
</header>
<main class="center-content">
<div class="title-icon">
<img src="/img/icon-light.svg" class="icon-light" width=64 height=64 />
<img src="/img/icon-dark.svg" class="icon-dark" width=64 height=64 />
<link rel="stylesheet" type="text/css" href="/style/main.css">
<link rel="stylesheet" type="text/css" href="/style/index.css">
<script type="module" src="/script/index.js" defer></script>
</head>
<body>
<header>
<nav>
<span class="nav-title">
<span class="title-icon">
<img src="/img/icon-light.svg" class="only-light" width=26 height=26 />
<img src="/img/icon-dark.svg" class="only-dark" width=26 height=26 />
</span>
<strong>bliss<span class="col-on-primary">.</span>town</strong>
</span>
<a href="/">home</a>
<a href="https://git.arimelody.me/ari/bliss.town">source</a>
</nav>
</header>
<main>
<h1>
<span class="title-icon">
<img src="/img/icon-light.svg" class="only-light" width=64 height=64 />
<img src="/img/icon-dark.svg" class="only-dark" width=64 height=64 />
</span>
welcome to bliss<span class="col-on-primary">.</span>town!
</h1>
<p>
we're a collective of online creatives.
</p>
<hr/>
<div id="crew">
<h2>check us out!</h2>
<div id="crew-list">
<div class="crew-item">
<img src="https://arimelody.space/img/favicon.png" alt="ari melody photo" class="avatar" width=64 height=64>
<div class="crew-info">
<h3>ari</h3>
<p><a href="https://arimelody.space" class="handle">@arispacegirl</a></p>
<div class="crew-tags">
<span class="crew-tag">she/her</span>
<span class="crew-tag">developer</span>
<span class="crew-tag">musician</span>
<span class="crew-tag">artist</span>
</div>
</div>
<h1>welcome to bliss<span class="col-primary-bg">.</span>town!</h1>
<hr>
<p>
we're not hosting much at this domain just yet.
<br>
check back later for updates!
</p>
<button id="friendly-button">friendly button</button>
<script>
function hook_button() {
const button = document.getElementById("friendly-button");
if (!button) return;
let clicks = 0;
let saved_clicks = window.localStorage.getItem("friendly-button-clicks");
if (saved_clicks) {
clicks = saved_clicks;
button.innerText = `clicked ${clicks} times!`;
}
button.addEventListener("click", () => {
button.innerText = `clicked ${++clicks} times!`;
window.localStorage.setItem("friendly-button-clicks", clicks);
});
}
document.addEventListener("ready", hook_button);
document.addEventListener("htmx:load", hook_button);
</script>
</main>
<footer>
<p>
made with <span role="img" aria-label="love"></span> by <a href="https://arimelody.me">ari</a>, 2024.
</p>
</footer>
</body>
</div>
<div class="crew-item">
<img src="https://media.wetdry.world/accounts/avatars/107/412/233/663/540/779/original/9e4353266869a4cd.jpeg" alt="vimae photo" class="avatar" width=64 height=64>
<div class="crew-info">
<h3>mae</h3>
<p><a href="https://mae.wtf" class="handle">@vimae</a></p>
<div class="crew-tags">
<span class="crew-tag">she/they</span>
<span class="crew-tag">musician</span>
<span class="crew-tag">artist</span>
<span class="crew-tag">developer</span>
</div>
</div>
</div>
<div class="crew-item">
<img src="https://44.media.tumblr.com/feb33c9c0151a46d09a55a6e0d7fa0f3/34631bc4c40620ff-2c/s128x128u_c1_f1/b06e02240d23dacddf257fe50cfe3a9c6dbee537.gif" alt="claire photo" class="avatar" width=64 height=64>
<div class="crew-info">
<h3>claire</h3>
<p><a href="https://supitszaire.com" class="handle">@zaire</a></p>
<div class="crew-tags">
<span class="crew-tag">she/her</span>
<span class="crew-tag">musician</span>
<span class="crew-tag">artist</span>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div id="projects">
<h2>stuff we make</h2>
<div id="project-list">
<div class="project-item">
<div class="project-item-banner">
<img src="/img/projects/campfire.png" alt="screenshot of the campfire timeline" width=256>
</div>
<div class="project-info">
<h3>campfire</h3>
<p>a pretty, modern web client for the fediverse!</p>
<a href="https://campfire.bliss.town" class="col-on-primary">campfire.bliss.town</a>
</div>
</div>
</div>
</div>
</main>
<footer>
<p>
made with <span role="img" aria-label="love"></span> by <a href="https://arimelody.space">ari</a>, 2025.
</p>
</footer>
</body>
</html>

View file

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" value="width=device-width, initial-scale=1">
<title>shortlinks - bliss town</title>
<link rel="icon" type="image/x-icon" href="/img/favicon.png">
<meta property="og:site_name" content="bliss town" />
<meta property="og:title" content="bliss town shortlinks" />
<meta property="og:image" content="https://bliss.town/img/og-icon.png" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://bliss.town/links" />
<link rel="stylesheet" type="text/css" href="/style/main.css">
<script type="application/javascript" src="/script/vendor/htmx.min.js"></script>
</head>
<body>
<header>
<nav hx-boost="true" hx-target="body" hx-swap="outerHTML show:window:top">
<a href="/">home</a>
<span aria-hidden="true">-</span>
<a href="/links">links</a>
<span aria-hidden="true">-</span>
<a href="/paste">paste</a>
<span aria-hidden="true">-</span>
<a href="https://git.arimelody.me/ari/bliss.town" target="_blank">source</a>
</nav>
</header>
<main class="center-content">
<h1><span aria-hidden="true">🔗</span><br>bliss<span class="col-primary-bg">.</span>town shortlinks</h1>
<hr>
<p>
we run an invite-only shortlink service, <code>link.bliss.town</code>,
<br>
powered by <a href="https://yourls.org/">YOURLS</a>.
</p>
</main>
<footer>
<p>
made with <span role="img" aria-label="love"></span> by <a href="https://arimelody.me">ari</a>, 2024.
</p>
</footer>
</body>
</html>

View file

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" value="width=device-width, initial-scale=1">
<title>pastebin - bliss town</title>
<link rel="icon" type="image/x-icon" href="/img/favicon.png">
<meta property="og:site_name" content="bliss town" />
<meta property="og:title" content="bliss town pastebin" />
<meta property="og:image" content="https://bliss.town/img/og-icon.png" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://bliss.town/paste" />
<link rel="stylesheet" type="text/css" href="/style/main.css">
<script type="application/javascript" src="/script/vendor/htmx.min.js"></script>
</head>
<body>
<header>
<nav hx-boost="true" hx-target="body" hx-swap="outerHTML show:window:top">
<a href="/">home</a>
<span aria-hidden="true">-</span>
<a href="/links">links</a>
<span aria-hidden="true">-</span>
<a href="/paste">paste</a>
<span aria-hidden="true">-</span>
<a href="https://git.arimelody.me/ari/bliss.town" target="_blank">source</a>
</nav>
</header>
<main class="center-content">
<h1><span aria-hidden="true">📝</span><br>bliss<span class="col-primary-bg">.</span>town pastebin</h1>
<hr>
<p>
we run a public pastebin instance, <a href="https://paste.bliss.town"><code>paste.bliss.town</code></a>,
<br>
powered by <a href="https://docs.dpaste.org">dpaste</a>.
</p>
</main>
<footer>
<p>
made with <span role="img" aria-label="love"></span> by <a href="https://arimelody.me">ari</a>, 2024.
</p>
</footer>
</body>
</html>

13
public/script/index.js Normal file
View file

@ -0,0 +1,13 @@
import { hijackClickEvent } from './main.js';
document.addEventListener('readystatechange', () => {
document.querySelectorAll("#project-list .project-item").forEach(projectItem => {
const link = projectItem.querySelector('a');
hijackClickEvent(projectItem, link);
});
document.querySelectorAll("#crew-list .crew-item .crew-info").forEach(crewItem => {
const link = crewItem.querySelector('a.handle');
hijackClickEvent(crewItem, link);
});
});

16
public/script/main.js Normal file
View file

@ -0,0 +1,16 @@
export function hijackClickEvent(container, link) {
container.addEventListener('click', event => {
if (event.target.tagName.toLowerCase() === 'a') return;
event.preventDefault();
link.dispatchEvent(new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
ctrlKey: event.ctrlKey,
metaKey: event.metaKey,
shiftKey: event.shiftKey,
altKey: event.altKey,
button: event.button,
}));
});
}

File diff suppressed because one or more lines are too long

117
public/style/index.css Normal file
View file

@ -0,0 +1,117 @@
#project-list {
display: flex;
gap: 1em;
}
.project-item {
width: 256px;
border-radius: 8px;
overflow: clip;
background-color: var(--primary);
transition: background-color .2s linear;
box-shadow: 2px 2px 2px #0004;
cursor: pointer;
}
.project-item:hover {
outline: 1px solid var(--on-primary);
}
.project-item-banner {
width: 256px;
height: 128px;
}
.project-item-banner img {
width: 100%;
height: 100%;
object-fit: cover;
}
.project-info {
padding: .4em .5em;
}
.project-info h3 {
margin: 0;
}
.project-info p {
font-size: .8em;
margin: 0;
}
.project-info a {
font-style: italic;
font-size: .8em;
color: var(--on-background);
opacity: .75;
transition: color .2s linear;
text-decoration: none;
}
#crew-list {
display: flex;
gap: 1em;
flex-wrap: wrap;
}
.crew-item {
display: flex;
flex-direction: row;
gap: .5em;
}
.crew-item img.avatar {
width: 64px;
height: 64px;
object-fit: cover;
border-radius: 8px;
background-color: #101010;
}
.crew-item .crew-info {
padding: .5em;
background-color: var(--primary);
border-radius: 8px;
box-shadow: 2px 2px 2px #0004;
transition: background-color .2s linear;
cursor: pointer;
}
.crew-info:hover {
outline: 1px solid var(--on-primary);
}
.crew-item h3 {
display: block;
margin: 0 0 -.2em 0;
transition: inherit;
}
.crew-item h3 a {
display: block;
color: inherit;
}
.crew-item a.handle {
display: block;
font-style: italic;
font-size: .8em;
color: var(--on-background);
opacity: .75;
transition: color .2s linear;
text-decoration: none;
}
.crew-item p {
margin: .2em 0;
}
.crew-item .crew-tags {
margin: .5em 0 0 0;
display: flex;
gap: .2em;
}
.crew-item .crew-tag {
font-size: .75em;
padding: .2em .5em;
border-radius: 4px;
text-wrap: nowrap;
color: var(--on-primary);
border: 1px solid var(--on-primary);
}

View file

@ -1,187 +1,181 @@
@import url("/font/lora/lora-font.css");
:root {
--foreground: #322e1f;
--background: #f9f1db;
--primary-fg: #92a40a;
--primary-bg: #c4ce7e;
--background: #fffcf7;
--on-background: #322e1f;
--primary: #f7eddb;
--on-primary: #92a40a;
}
@media screen and (prefers-color-scheme: dark) {
:root {
--foreground: #e2dfe3;
--background: #1b141e;
--primary-fg: #cda1ec;
--primary-bg: #513d60;
}
:root {
--background: #1b141e;
--on-background: #e2dfe3;
--primary: #352640;
--on-primary: #cda1ec;
}
}
body {
margin: 0;
padding: 0;
margin: 0;
padding: 0;
font-family: "Lora", serif;
font-size: 20px;
font-family: "Lora", serif;
font-size: 20px;
color: var(--foreground);
background-color: var(--background);
color: var(--on-background);
background-color: var(--background);
transition: color .2s linear, background-color .2s linear;
transition: color .2s linear, background-color .2s linear;
}
header {
position: fixed;
top: 1em;
left: 50%;
transform: translateX(-50%);
width: min(900px, calc(100vw - 4rem));
margin: 0 auto;
padding: .5em 0;
border-radius: 2em;
text-align: center;
backdrop-filter: blur(1em);
z-index: 100;
position: fixed;
top: 0;
left: 0;
width: 100vw;
transform: none;
border-bottom: 1px solid var(--primary);
background-color: var(--background);
z-index: 1000;
transition: background-color .2s linear, box-shadow .2s linear, border-color .2s linear;
}
header nav {
font-size: .8em;
width: min(900px, calc(100vw - 4rem));
margin: 0 auto;
font-size: .8em;
user-select: none;
}
header nav span {
margin: 0 .8em;
color: var(--primary-fg);
header nav>span,
header nav>div,
header nav>a {
margin: 0;
padding: .5em 1em;
display: inline-block;
color: var(--on-primary);
}
header nav .nav-title {
color: var(--on-background);
}
header nav div {
margin: 0 .4em;
display: inline-block;
}
header nav div img {
display: inline-block;
}
main {
width: min(720px, calc(100vw - 4rem));
min-height: calc(100vh - 8.3em);
margin: 3em auto 0 auto;
text-align: center;
width: min(900px, calc(100vw - 4rem));
min-height: calc(100vh - 9.4em);
margin: 4em auto 0 auto;
padding: 0;
}
.title-icon {
width: 64px;
margin: 1em auto -1em auto;
display: flex;
.only-light {
opacity: 1;
transition: opacity .2s linear;
}
.title-icon img {
transition: opacity .2s linear;
}
.title-icon img.icon-dark {
position: relative;
left: -64px;
opacity: 0;
}
@media screen and (prefers-color-scheme: dark) {
.title-icon img.icon-light {
opacity: 0;
}
.title-icon img.icon-dark {
opacity: 1;
}
}
.center-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.only-dark {
opacity: 0;
transition: opacity .2s linear;
}
hr {
width: 100%;
margin: 1em 0;
border-width: 1px 0 0 0;
width: 100%;
margin: 2em 0 1.5em 0;
border-width: 1px 0 0 0;
text-align: center;
}
hr::after {
content: "✦";
position: absolute;
transform: translate(-50%, -54.5%);
padding: 5px;
color: var(--foreground);
background: var(--background);
transition: color .2s linear, background-color .2s linear;
content: "✦";
position: absolute;
transform: translate(-50%, -54.5%);
padding: 5px;
color: var(--on-background);
background: var(--background);
transition: color .2s linear, background-color .2s linear;
}
a {
color: var(--primary-fg);
text-decoration: none;
font-weight: bold;
transition: color .2s linear;
color: var(--on-primary);
text-decoration: none;
font-weight: bold;
transition: color .2s linear;
}
a:hover {
text-decoration: underline;
text-decoration: underline;
}
button {
padding: .5em 1.2em;
font-size: .8em;
font-family: inherit;
font-weight: bold;
color: var(--foreground);
background-color: var(--primary-bg);
border: none;
border-radius: 2em;
cursor: pointer;
transition: color .2s linear, background-color .2s linear, transform .1s ease-out;
padding: .5em 1.2em;
font-size: .8em;
font-family: inherit;
font-weight: bold;
color: var(--on-background);
background-color: var(--primary);
border: none;
border-radius: 2em;
cursor: pointer;
transition: color .2s linear, background-color .2s linear, transform .1s ease-out;
}
button:hover {
transform: scale(1.05);
transform: scale(1.05);
}
button:active {
transform: scale(0.95);
transform: scale(0.95);
}
footer {
width: min(900px, calc(100vw - 4rem));
margin: 0 auto;
padding: 1em 0;
text-align: center;
opacity: .5;
transition: opacity .1s ease-out;
width: min(900px, calc(100vw - 4rem));
margin: 0 auto;
padding: 1em 0;
text-align: center;
opacity: .5;
transition: opacity .1s ease-out;
}
footer:hover {
opacity: 1;
opacity: 1;
}
#footer-links {
font-size: .8em;
font-size: .8em;
}
[class^="col-"] {
transition: color .2s linear;
.title-icon {
position: relative;
height: 1.2em;
margin: 0 .1em;
padding-right: 1.6em;
display: inline-block;
}
[class^="bg-"] {
transition: background-color .2s linear;
.title-icon img {
position: absolute;
}
.col-fg {
color: var(--foreground);
.col-on-primary {
color: var(--on-primary);
}
.bg-fg {
background-color: var(--foreground);
}
.col-bg {
color: var(--background);
}
.bg-bg {
background-color: var(--background);
}
.col-primary-fg {
color: var(--primary-fg);
}
.bg-primary-fg {
background-color: var(--primary-fg);
}
.col-primary-bg {
color: var(--primary-bg);
}
.bg-primary-bg {
background-color: var(--primary-bg);
@media screen and (prefers-color-scheme: dark) {
.only-light {
opacity: 0;
}
.only-dark {
opacity: 1;
}
header {
box-shadow: 0 2px 8px #0c03116e;
}
}