diff --git a/CHANGELOG.md b/CHANGELOG.md index 136e7f1..30a778b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 74b3268..1841089 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -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%), @@ -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; diff --git a/frontend/src/viewport.ts b/frontend/src/viewport.ts index 905f5c4..ca428d2 100644 --- a/frontend/src/viewport.ts +++ b/frontend/src/viewport.ts @@ -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;