Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to Abduction are documented here. This project follows

## [Unreleased]

### Fixed

- History, Stats, Reviews, Dependencies, Themes, and Settings scroll again; a shared panel rule had been clipping every view except Code.
- Text stays sharp at every Text & UI scale setting. The scale is now applied with CSS `zoom`, which re-renders the interface at the chosen size, instead of a transform that stretched the rendered pixels and blurred glyphs at non-integer scales.

## [0.1.18] - 2026-09-04

### Changed
Expand Down
10 changes: 7 additions & 3 deletions frontend/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ kbd {
.shell {
position: relative; isolation: isolate;
display: grid; grid-template: var(--titlebar-h) minmax(0, 1fr) / var(--rail-w) minmax(0, 1fr);
width: calc(100vw / var(--scale)); height: calc(100vh / var(--scale));
transform: scale(var(--scale)); transform-origin: top left;
/* The UI scale preference uses zoom, not transform: zoom re-lays out the subtree at the new
size and rasterises text at that size, so glyphs stay crisp at 110% or 125%. A transform
would stretch an already-rendered raster and blur every non-integer scale. */
width: 100%; height: 100%; zoom: var(--scale);
background:
radial-gradient(900px 560px at 74% -18%, color-mix(in srgb, var(--ambient-primary) 24%, transparent), transparent 66%),
radial-gradient(760px 520px at -10% 108%, color-mix(in srgb, var(--ambient-secondary) 20%, transparent), transparent 68%),
Expand Down Expand Up @@ -247,10 +249,12 @@ kbd {
.workspace > section {
min-width: 0; min-height: 0;
border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line)); border-radius: var(--r-lg);
background: var(--panel); overflow: hidden;
background: var(--panel); overflow: auto; overscroll-behavior: contain;
box-shadow: var(--edge), var(--shadow-2), 0 0 calc(40px * var(--glow)) color-mix(in srgb, var(--ambient-primary) 10%, transparent);
animation: view-in var(--t) var(--ease);
}
/* Views that own their own scroll regions (panes, streams) clip instead of scrolling as a whole. */
.workspace > .code-layout, .workspace > .security-view, .workspace > .analysis-view, .workspace > .logs-view { overflow: hidden; }
.workspace > .empty { place-self: center; width: min(560px, 100%); }
.section-title, .stats-view > header, .reviews-view > header, .dependency-hero, .theme-switcher > header, .logs-view > header, .settings-view > header {
display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 18px;
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/viewport.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// updateViewportUnits recomputes --vh/--vw as 1% of the true viewport divided
// by the active --scale, so viewport-unit CSS keeps its real-world proportions
// under the whole-app scale transform on .shell instead of measuring against
// the unscaled window.
// by the active --scale. Inside the zoomed .shell one CSS pixel is --scale real
// pixels, so viewport-unit CSS keeps its real-world proportions instead of
// measuring against the unzoomed window.
export function updateViewportUnits() {
const root = document.documentElement;
const scale = Number(getComputedStyle(root).getPropertyValue("--scale")) || 1;
Expand Down