Files
0xa0.dev/css/style.css
T
0xa0 618d8254f1
Deploy / deploy (push) Successful in 3s
koi: swap the sakura panels for a shoal of letter-drawn koi
Five varieties (kohaku, ogon, sanke, showa, tancho) swim in the side
margins, drawn the way the reference does it: every cell is a filled tile
in the koi's colour with a letter punched into it in near-black, picked
from a thin-to-thick ramp by how dense that part of the body is. The tile
carries the colour, the letter carries the texture.

The grid is square and the geometry is in pixels, snapping to cells only
when one is written. Laying the body out in grid cells instead makes its
proportions depend on heading -- thickness is perpendicular to travel, so
on the natural text grid a fish swimming sideways came out short and fat
while one swimming up came out slim.

The body is a follow-the-leader chain with a bend limit per joint. A spine
projected from the head rotates rigidly the moment the fish turns, and a
raw position trail coils into a ball; the chain lags and the bend cap
keeps it from curling. Swimming comes from the head yawing with the tail
beat, which the chain propagates as a travelling wave.

Tails dissolve into loose tiles toward the tip, and the panels carry a 1em
cell grid so the motion reads against something.

Drops the sakura wiring: no art.php parse, no sideart.php stylesheet, no
<pre> layers, and the inlined sideart @font-face goes with them (-6.9 KB
of base64 from style.css). art.php, sideart.php, sakura.ans and the woff2
are left on disk, now unreferenced.
2026-10-24 19:32:58 +02:00

270 lines
7.9 KiB
CSS

:root {
--bg: #0d0d0d;
--fg: #e8e8e8;
--muted: #888;
--line: #262626;
--field: #161616;
}
* { box-sizing: border-box; }
body {
margin-inline: auto;
max-width: 680px;
padding: 2rem 1.25rem;
background: var(--bg);
color: var(--fg);
font: 16px/1.6 ui-monospace, "JetBrains Mono", Menlo, monospace;
}
a { color: var(--fg); text-decoration: none; border-bottom: 1px solid var(--muted); }
a:hover { border-color: var(--fg); }
header nav {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--line);
}
h1 { font-size: 1.6rem; }
h1 .phonetic { color: darkgrey; font-size: 1rem; font-weight: normal; }
h2 { font-size: 1.1rem; color: var(--muted); font-weight: normal; }
footer {
margin-top: 3rem;
padding-top: 1rem;
border-top: 1px solid var(--line);
color: var(--muted);
}
.buttons88x31 {
display: flex;
flex-wrap: wrap;
gap: .4rem;
margin-bottom: .8rem;
}
.buttons88x31 a { border-bottom: none; }
.buttons88x31 img {
width: 88px;
height: 31px;
image-rendering: pixelated;
display: block;
}
.dot {
display: inline-block;
width: .6em; height: .6em;
border-radius: 50%;
background: var(--muted);
vertical-align: middle;
}
.dot-online { background: #3ba55d; }
.dot-idle { background: #faa61a; }
.dot-dnd { background: #ed4245; }
.dot-offline { background: #747f8d; }
.status-row {
display: flex;
flex-wrap: wrap;
align-items: stretch;
gap: .6rem;
}
.status-card {
display: flex;
align-items: center;
gap: .8rem;
padding: .8rem;
flex: 1 1 220px;
min-width: 0;
border: 1px solid var(--line);
border-radius: 4px;
background-size: cover;
background-position: center;
}
.status-card .avatar { border-radius: 4px; flex: none; }
.status-card .who { display: flex; flex-direction: column; gap: .15rem; }
.status-card .name { font-weight: bold; }
.status-card .state { color: var(--muted); font-size: .9rem; }
.spotify-card {
display: flex;
align-items: center;
gap: .8rem;
padding: .7rem;
flex: 1 1 220px;
min-width: 0;
border: 1px solid var(--line);
border-radius: 4px;
color: var(--fg);
}
a.spotify-card:hover { border-color: #1db954; }
.spotify-card .album-art { border-radius: 4px; flex: none; }
.spotify-card .album-art--empty {
width: 64px; height: 64px;
display: flex; align-items: center; justify-content: center;
background: var(--field);
color: var(--muted);
font-size: 1.5rem;
}
.np-label { font-size: .72rem; letter-spacing: .02em; }
.spotify-card .np-label { color: #1db954; }
.spotify-idle .np-label { color: var(--muted); }
.dc-label { color: #5865f2; }
.spotify-card .track { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.spotify-card .np-label { color: #1db954; font-size: .72rem; letter-spacing: .02em; }
.spotify-card .song { font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spotify-card .artist { color: var(--muted); font-size: .85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
form { display: flex; flex-direction: column; gap: .5rem; margin: 1.5rem 0; }
input, textarea {
background: var(--field);
border: 1px solid var(--line);
color: var(--fg);
padding: .6rem;
font: inherit;
border-radius: 4px;
}
textarea { min-height: 5rem; resize: vertical; }
button {
align-self: flex-start;
background: var(--fg);
color: var(--bg);
border: 0;
padding: .5rem 1.2rem;
font: inherit;
cursor: pointer;
border-radius: 4px;
}
.entry { border-top: 1px solid var(--line); padding: .8rem 0; }
.entry .date { color: var(--muted); font-size: .8rem; margin-left: .5rem; }
.entry p { margin: .3rem 0 0; }
.muted { color: var(--muted); }
/* post list (home widget + /blog) */
.posts-widget { margin: 2rem 0; }
.post-list { list-style: none; padding: 0; margin: 1rem 0; }
.post-list li {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 1rem;
padding: .6rem 0;
border-top: 1px solid var(--line);
}
.post-list .date { color: var(--muted); font-size: .85rem; white-space: nowrap; }
/* single post */
.back-link { margin: .5rem 0; }
.back-link a { border-bottom: none; color: var(--muted); }
.back-link a:hover { color: var(--fg); }
.post-title { margin-bottom: .2rem; }
.post-meta { color: var(--muted); font-size: .85rem; margin-bottom: 1.5rem; }
.post-body img {
max-width: 100%;
height: auto;
display: block;
margin: 1.5rem 0;
border-radius: 4px;
}
.post-body h1, .post-body h2, .post-body h3 { margin: 1.8rem 0 .6rem; }
.post-body h2 { color: var(--fg); font-size: 1.2rem; }
.post-body pre {
background: var(--field);
border: 1px solid var(--line);
border-radius: 4px;
padding: .8rem;
overflow-x: auto;
}
.post-body code {
background: var(--field);
padding: .1rem .3rem;
border-radius: 3px;
font-size: .9em;
}
.post-body pre code { background: none; padding: 0; }
.post-body blockquote {
border-left: 3px solid var(--line);
margin: 1rem 0;
padding-left: 1rem;
color: var(--muted);
}
/* The koi own the margins now. Cell size comes straight from this font-size,
and the body is 16 cells long, so this is the dial for how big they are.
The column shadow (body::before, z-index -1) fades them toward the text. */
.koi {
position: fixed;
top: 0;
z-index: -2;
width: calc(50% - 360px);
height: 100vh;
pointer-events: none;
user-select: none;
/* font-size IS the square cell size in px -- the one size dial */
font: clamp(7px, 0.95vh, 10px) / 1 ui-monospace, "JetBrains Mono", Menlo, monospace;
/* the pond's cell grid. 1em == one cell, so it stays locked to the tiles
the canvas draws however the font-size scales. */
background-image:
linear-gradient(to right, rgba(228, 230, 238, .05) 1px, transparent 1px),
linear-gradient(to bottom, rgba(228, 230, 238, .05) 1px, transparent 1px);
background-size: 1em 1em;
}
.koi-left { left: 0; }
.koi-right { right: 0; }
/* the column's shadow: the art fades out under it instead of stopping dead
beside the text. Eased falloff, as wide as about a third of the margin. */
body::before {
content: "";
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
--l: calc(50% - 340px);
--r: calc(50% + 340px);
--fade: clamp(60px, (100vw - 680px) * .16, 180px);
background: linear-gradient(90deg,
transparent calc(var(--l) - var(--fade)),
color-mix(in srgb, var(--bg) 22%, transparent) calc(var(--l) - var(--fade) * .75),
color-mix(in srgb, var(--bg) 55%, transparent) calc(var(--l) - var(--fade) * .5),
color-mix(in srgb, var(--bg) 85%, transparent) calc(var(--l) - var(--fade) * .25),
var(--bg) var(--l) var(--r),
color-mix(in srgb, var(--bg) 85%, transparent) calc(var(--r) + var(--fade) * .25),
color-mix(in srgb, var(--bg) 55%, transparent) calc(var(--r) + var(--fade) * .5),
color-mix(in srgb, var(--bg) 22%, transparent) calc(var(--r) + var(--fade) * .75),
transparent calc(var(--r) + var(--fade)));
}
@media (max-width: 1280px) {
.koi, body::before { display: none; }
}
@media print, (forced-colors: active) {
.koi, body::before { display: none; }
}
/* guestbook sign button */
.btn-sign {
display: inline-flex;
align-items: center;
gap: .5rem;
background: var(--fg);
color: var(--bg);
border: 1px solid var(--fg);
padding: .5rem 1.4rem;
border-radius: 4px;
font: inherit;
cursor: pointer;
transition: background .12s ease, color .12s ease, transform .08s ease;
}
.btn-sign .arrow { transition: transform .15s ease; }
.btn-sign:hover:not(:disabled) { background: transparent; color: var(--fg); }
.btn-sign:hover:not(:disabled) .arrow { transform: translateX(3px); }
.btn-sign:active:not(:disabled) { transform: translateY(1px); }
.btn-sign:focus-visible { outline: 2px solid var(--muted); outline-offset: 2px; }
.btn-sign:disabled { opacity: .55; cursor: progress; }
/* htmx swaps the label while the request is in flight */
.btn-sign .pending { display: none; }
.btn-sign.htmx-request .idle { display: none; }
.btn-sign.htmx-request .pending { display: inline; }
.btn-sign.htmx-request .arrow { display: none; }