: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); } /* ── sky ──────────────────────────────────────────────────────────────── Generated, not photographed. tools/background.py renders every style into img/bg/; inc/header.php enumerates that directory and emits one custom property per style, so --bg-img follows html[data-bg]. Only the matching rule's url() is fetched. Each is Bayer ordered-dithered to a few grey levels and upscaled with pixelated rendering so the cells stay crunchy. Regenerate everything: python tools/background.py all */ :root { --bg: #060606; /* opacity of the text-column scrim; raise for busier background styles */ --scrim: .82; } body { position: relative; } /* background layer */ body::before { content: ""; position: fixed; inset: 0; z-index: -2; background: #060606 var(--bg-img) center center / cover no-repeat; image-rendering: pixelated; } /* Readability scrim + diagonal hatch. The first layer is a feathered vertical band, ~880px wide and centred on the 680px text column, sitting above the artwork (z-index -2) but below the content. It gives every background style a consistent dark bed to read against instead of relying on each one being quiet in the middle, and because the edges fade out there is no visible panel or card. */ body::after { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background: linear-gradient(90deg, transparent 0%, rgba(4, 4, 4, var(--scrim)) 14%, rgba(4, 4, 4, var(--scrim)) 86%, transparent 100%), radial-gradient(ellipse 70% 60% at 50% 38%, rgba(4, 4, 4, .32), transparent 82%), repeating-linear-gradient(-45deg, rgba(240, 240, 240, .045) 0 1px, transparent 1px 8px); background-size: 880px 100%, auto, auto; background-position: center top, center, center; background-repeat: no-repeat, no-repeat, repeat; } /* cards sat on flat #161616 before; let the sky read through them */ .status-card, .spotify-card, .post-body pre { background-color: rgba(6, 6, 6, .66); } input, textarea { background: rgba(6, 6, 6, .66); } /* 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; }