feat(web): adopt cyberspace terminal aesthetic + dithered images
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

Rebrand light/dark themes to the cyberspace.online look: warm cream-on-black
palette (light/dark are exact inverses), self-hosted JetBrains Mono + VT323,
square corners, border-driven surfaces with no soft shadows. Adds a terminal
design-system CSS layer (DOS double-border modals with hatched corner, fg focus,
inversion-on-hover), a theme-aware <RasterImage> (Atkinson-dithered canvas with
img fallback), and unifies desktop icons, taskbar, window controls, pills and
links under one idiom. Pins window titlebars to a fixed height and switches chat
auto-scroll off scrollIntoView to avoid titlebar reflow.

VERSION 0.15.1 -> 0.16.0
This commit is contained in:
2026-08-03 22:03:24 +02:00
parent b27e1bf3ec
commit 757ef2f34b
18 changed files with 554 additions and 139 deletions

View File

@@ -59,7 +59,6 @@
} = $props()
let input = $state(typeof initialDraft === 'string' ? initialDraft : '')
let messagesEnd = $state<HTMLDivElement | null>(null)
let scrolledUp = $state(false)
let container = $state<HTMLDivElement | null>(null)
@@ -150,12 +149,17 @@
}
// Auto-scroll to bottom on new messages (or a freshly-raised question) —
// unless user scrolled up to read.
// unless user scrolled up to read. Sets scrollTop on the messages container
// directly instead of `scrollIntoView`, which walks ancestors and forces a
// reflow that can momentarily perturb the window titlebar height.
$effect(() => {
void messages
void question
if (streaming || !scrolledUp) {
setTimeout(() => messagesEnd?.scrollIntoView({ behavior: 'smooth' }), 50)
setTimeout(
() => container?.scrollTo({ top: container.scrollHeight, behavior: 'smooth' }),
50
)
}
})
@@ -326,7 +330,6 @@
{#if question}
<OperatorQuestion {sessionId} {question} />
{/if}
<div bind:this={messagesEnd}></div>
</div>
</div>