From 4293904214c1e9eb3e38880a3d0e562cd03e4352 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Fri, 7 Aug 2026 15:41:07 -0700 Subject: [PATCH] [eric] canvas: the stock wash is one flat colour, so a default install has no texture left to tear --- frontend/public/index.html | 2 +- .../src/shared/styles/washBackground.test.ts | 17 ++++++++++++++++- frontend/src/shared/styles/washBackground.ts | 10 +++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/frontend/public/index.html b/frontend/public/index.html index cc93caf7..a651cecf 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -51,7 +51,7 @@ var g = null; try { g = JSON.parse(localStorage.getItem('self-swarm-theme-gradient') || 'null'); } catch (e) {} var accent = localStorage.getItem('self-swarm-theme-accent'); - var stops = Array.isArray(g) && g.length > 1 ? g : (accent ? [accent, accent] : ['#B7CDEA', '#EFE0D2', '#E7BDD1']); + var stops = Array.isArray(g) && g.length > 1 ? g : (accent ? [accent, accent] : ['#DACEDA']); if (stops.length === 1) stops = [stops[0], stops[0]]; var alpha = parseFloat(localStorage.getItem('self-swarm-theme-wash-opacity') || ''); if (!isFinite(alpha) || alpha < 0 || alpha > 1) alpha = 0.17; diff --git a/frontend/src/shared/styles/washBackground.test.ts b/frontend/src/shared/styles/washBackground.test.ts index f99895b5..fe2c6973 100644 --- a/frontend/src/shared/styles/washBackground.test.ts +++ b/frontend/src/shared/styles/washBackground.test.ts @@ -9,7 +9,7 @@ */ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { washIsUniform, washBackgroundLayers, washUnderlayColor, washOpaqueBackgroundUrl } from './washBackground.ts'; +import { washIsUniform, washBackgroundLayers, washUnderlayColor, washOpaqueBackgroundUrl, DEFAULT_WASH_STOPS, effectiveWashStops } from './washBackground.ts'; const PAGE = '#F5F4ED'; @@ -58,3 +58,18 @@ test('no stops and no grain means no background image at all', () => { assert.equal(washBackgroundLayers([], 0.17, PAGE, null), null); assert.equal(washIsUniform([]), true); }); + +test('the STOCK theme is uniform, so a default install cannot tear', () => { + // Everyone who never opened the theme pad lands here. Making this multi-stop again would put a + // full-window texture back under every default install, which is the band, so it is asserted. + assert.equal(washIsUniform(DEFAULT_WASH_STOPS), true, 'default wash must stay one flat colour'); + assert.equal(washBackgroundLayers(DEFAULT_WASH_STOPS, 0.17, PAGE, null), null); + assert.equal(washIsUniform(effectiveWashStops(null, null)), true, 'no accent, no gradient'); + assert.equal(washIsUniform(effectiveWashStops(null, '#B7CDEA')), true, 'a picked accent is one stop'); +}); + +test('a user who picks a real gradient still gets one, texture and all', () => { + const chosen = ['#B7CDEA', '#E7BDD1']; + assert.equal(washIsUniform(effectiveWashStops(chosen, null)), false); + assert.ok(washBackgroundLayers(chosen, 0.17, PAGE, null)); +}); diff --git a/frontend/src/shared/styles/washBackground.ts b/frontend/src/shared/styles/washBackground.ts index f24eda01..cb8b4e72 100644 --- a/frontend/src/shared/styles/washBackground.ts +++ b/frontend/src/shared/styles/washBackground.ts @@ -79,9 +79,13 @@ export function washUnderlayColor(stops: string[], washOpacity: number, pageBg: return mixHex(pageBg, mean, alpha); } -// Stock wallpaper when the user hasn't picked an accent yet: a designed blue-to-cream-to-pink -// gradient (contrasting stops), so a fresh install and the onboarding stage never look flat/white. -export const DEFAULT_WASH_STOPS = ['#B7CDEA', '#EFE0D2', '#E7BDD1']; +// Stock wallpaper when the user hasn't picked an accent yet. ONE stop on purpose: a multi-stop +// default needs a full-window texture, and Chromium fills any tile it drops with the layer's single +// background colour, which is why the gradient used to tear into a hard-edged rectangle under GPU +// pressure. This is the mean of the old blue-cream-pink trio, i.e. exactly the colour those torn +// tiles already painted, so the stock look is now what the worst case used to be. Picking any accent +// is also one stop; only a user-chosen gradient opts back into the texture. +export const DEFAULT_WASH_STOPS = ['#DACEDA']; export function effectiveWashStops(gradient: string[] | null, accent: string | null): string[] { if (gradient && gradient.length > 0) return gradient;