Themes and backgrounds: refine every palette, per-theme gradients with measured motion, Appearance background picker #110

Closed
opened 2026-09-25 18:30:46 +00:00 by kayg · 2 comments
Owner

Branch job/themes-backgrounds. DESIGN §35 (grill rounds 1-2): keep and refine all themes (gradient, glass tint, accent, surfaces), contrast tests on glass-over-gradient worst case with the least tint that passes; background layer with slow motion on by default everywhere (off under reduced motion, paused when hidden), measured at 60 fps under 4x CPU throttle; Settings → Appearance background picker with separate light/dark picks (theme gradient, solid, upload, Unsplash via the server API from #86), dim slider, live preview.

Branch job/themes-backgrounds. DESIGN §35 (grill rounds 1-2): keep and refine all themes (gradient, glass tint, accent, surfaces), contrast tests on glass-over-gradient worst case with the least tint that passes; background layer with slow motion on by default everywhere (off under reduced motion, paused when hidden), measured at 60 fps under 4x CPU throttle; Settings → Appearance background picker with separate light/dark picks (theme gradient, solid, upload, Unsplash via the server API from #86), dim slider, live preview.
Author
Owner

themes-backgrounds report (branch job/themes-backgrounds, not pushed or merged)

Commits

  • 2129df1 fix(web): theme tokens have one source, @calternal/ui themes.css. calternal-app.css had a duplicate copy of 16 theme blocks that silently overrode themes.css.
  • ccb0e2b feat(themes): a background mesh, glass tint and surface steps per theme (plus the #app-background layer and drift)
  • a521505 fix(ui): file rows are clear over the app background. FileCollection rows were opaque --paper.
  • 8d83152 feat(settings): Appearance → Background, with a Light pick and a Dark pick
  • 238f293 perf(web): the background drift pauses under overlays and is off on touch
  • d294700 fix(settings): arrow keys move and select in the background radio groups
  • 24ec0f3 test(e2e): theme review screens and the drift measurement (layout-sweep.mjs --themes / --motion)

Gates (apps/web)

  • bun run check: COMPLETED 1389 FILES 0 ERRORS 0 WARNINGS 0 FILES_WITH_PROBLEMS
  • bun run test: Test Files 37 passed (37) / Tests 262 passed (262)
  • bun run build: ✓ built in 1m 5s
  • bun run test:e2e:layout (real local server built in the worktree): checked 132 screens / LAYOUT SWEEP PASSED
  • No Rust was changed, so the cargo gates were not run.

Motion measurement

Setup: Chromium, 4× CPU throttling, 390×844 at DPR 3 with touch, 10 s trace per run, 2 rounds, midnight and paper. The Settings sheet is open on the settings screen. The host was an 8-core VM with no GPU (software compositing) and a load average of 32–44 from other jobs.

screen motion on fps motion off fps
Files 4.9–6.7 3.2–6.3
Files + sidebar sheet 3.8–5.6 3.6–6.0
Settings 3.8–4.9 3.4–4.4
  • Dropped frames were 90–96% in every run. Main-thread time was 0.2–68 ms/s in both states (noise).
  • The idle "off" runs are just as slow. The trace shows Viz DirectRenderer::DrawFrame taking about 100 ms per frame, so this host's software compositor is the limit.
  • A cheaper layer (2 blobs, a smaller moving layer) did not change the result: 8.7–13.5 fps against 14.4–16.2 fps for the default layer.
  • Desktop at 1440 with no throttle: 11.4 fps on Files and 8.3 fps on Settings (off runs: 9.7 and 8.6 fps). That is also host-bound.
  • Rule applied: the result is below 55 fps and the cost reduction did not help, so the drift is off where the pointer is coarse. It stays on for fine pointers.
  • The drift now also pauses under any scrim (Settings, Search, the viewer) and the phone drawer. There, the one live blur would otherwise re-filter on every frame.
  • A measurement on a real mid-range phone can lift the touch rule. The rule is one @media (pointer: coarse) block in lib/styles/background.css.
  • Raw numbers: target/theme-screens/motion-protocol.json

Per theme

All tests pass at these values. Glass alpha is at the design floor (55% light, 50% dark) everywhere, because a thinner tint would also pass. The tests enforce "least tint or floor".

Theme Accent / accent-2 Mesh stops (1-4) over paper Glass tint, alpha Worst text on mesh (ink / muted) Worst text on glass (ink / muted)
paper #3d5ac4 / #744ab4 #f5f6f8 + #e8effe #f3efff #ccfcf3 #fff0e9 #ffffff 55% 14.21 / 4.74 15.36 / 5.13
meridian #0b736f / #4458bc #f1f5f4 + #b3faf4 #d1f5ff #ebf0fe #feefe0 #ffffff 55% 13.57 / 4.69 14.71 / 5.08
bloom #a8326b / #6a55b0 #f8f3f4 + #ffe7ed #feebe6 #f0edff #ffefe0 #fffdfd 55% 14.29 / 4.90 15.38 / 5.27
latte #8738ed / #ea76cb #eff1f5 + #ece7fe #ffe4f5 #d8f0ff #feebe3 #eff1f5 55% 6.63 / 5.19 6.84 / 5.35
solarized #17668f / #2aa198 #fdf6e3 + #fff0cf #c1fdf6 #e7f4ff #fff0eb #eee8d5 55% 11.45 / 5.59 10.82 / 5.29
rose-pine-dawn #286983 / #907aa9 #faf4ed + #feeae8 #feedd9 #f5ecff #d0f8ff #fffaf3 55% 8.20 / 4.80 8.65 / 5.06
midnight #7c96f5 / #c29bf0 #0f1320 + #1c266b #311861 #012828 #420d2d #1b2236 50% 11.35 / 4.77 11.93 / 5.02
ember #e59a57 / #e5705a #1a1614 + #442300 #4c130f #391930 #302201 #291f1b 50% 11.58 / 4.93 12.14 / 5.17
forest #7fc79c / #d6b074 #101613 + #00341d #002b2b #1f2800 #331e00 #1c2620 50% 11.35 / 4.86 11.74 / 5.03
tokyo-night #7aa2f7 / #bb9af7 #1a1b26 + #163274 #3e2464 #023248 #362155 #202330 50% 7.46 / 5.71 8.36 / 6.39
gruvbox #8ec07c / #fe8019 #282828 + #622806 #4a3202 #1b3c1d #4f2639 #3c3836 50% 10.14 / 8.39 10.00 / 8.27
frappe #cfa2eb / #f4b8e4 #303446 + #553a65 #34446a #55354d #194741 #414559 50% 6.30 / 5.28 6.17 / 5.17
macchiato #c6a0f6 / #f5bde6 #24273a + #472f61 #253964 #4c2743 #023b35 #363a4f 50% 7.66 / 6.31 7.48 / 6.16
mocha #cba6f7 / #f5c2e7 #1e1e2e + #41285a #18315a #441f3b #02332d #313244 50% 8.66 / 7.08 8.58 / 7.01
mono #3a4046 / #6b7178 #fafaf9 + #ecf5fd #fbf4ed #f1f7fc #f4f4f9 #ffffff 55% 16.14 / 5.76 17.05 / 6.08
noir #c9cccf / #8a8d91 #000000 + #191f30 #201827 #091d1c #1f170e #141416 50% 14.64 / 5.82 15.48 / 6.16
one-light #2b60d8 / #a626a4 #fafafa + #ecf3ff #fef1fd #eef7fe #fff6e8 #ffffff 55% 10.17 / 4.70 10.80 / 4.99
ayu-light #a75203 / #399ee6 #f8f9fa + #fff0e0 #eaf5ff #d4feec #fff3f3 #fcfcfc 55% 5.60 / 4.91 5.83 / 5.11
github-light #0969da / #8250df #ffffff + #f1f7fe #f9f8ff #eaffec #fefafc #ffffff 55% 14.65 / 5.67 15.19 / 5.88
nord #88c0d0 / #b48ead #2e3440 + #2a486b #104956 #553650 #154544 #3b4252 50% 8.14 / 6.95 8.33 / 7.11
dracula #bd93f9 / #ff79c6 #282a36 + #423258 #4f2b3f #13383f #2d354c #343746 50% 10.77 / 7.98 10.83 / 8.02
one-dark #61afef / #c678dd #282c34 + #093b5d #4a2a53 #003b41 #4e272a #21252b 50% 5.49 / 6.39 6.16 / 7.17
everforest #a7c080 / #83c092 #2d353b + #36441c #24442c #1b443f #513528 #343f44 50% 6.21 / 5.68 6.28 / 5.74
kanagawa #7e9cd8 / #957fb8 #1f1f28 + #073752 #392752 #05313f #43210c #2a2a37 50% 8.63 / 6.81 8.96 / 7.07
rose-pine #9ccfd8 / #c4a7e7 #191724 + #023242 #391b54 #4a0f23 #3e1818 #1f1d2e 50% 10.36 / 7.55 11.17 / 8.14
rose-pine-moon #9ccfd8 / #c4a7e7 #232136 + #043547 #38284a #46222b #3d2423 #2a273f 50% 9.92 / 7.23 10.14 / 7.39
ayu-dark #e6b450 / #39bae6 #0d1017 + #2e1f01 #012532 #341500 #261337 #10141c 50% 8.51 / 6.77 9.06 / 7.21
ayu-mirage #ffcc66 / #5ccfe6 #1f2430 + #3f2e09 #02363f #442520 #342740 #242936 50% 7.97 / 6.23 8.22 / 6.43
github-dark #4493f8 / #ab7df8 #0d1117 + #002450 #300f56 #002304 #3b0625 #161b22 50% 12.99 / 5.27 13.49 / 5.47

Screenshots (/home/kayg/Developer/calternal/target/theme-screens/)

  • <theme>-files-1440.png, <theme>-menu-1440.png and <theme>-settings-1440.png for all 29 themes
  • <theme>-{files,sidebar,menu,settings}-390.png for paper, bloom, rose-pine-dawn, midnight, tokyo-night and mocha
  • {paper,midnight}-background-card-1440.png, {paper,midnight}-background-settings-1440.png and {paper,midnight}-image-files-1440.png (uploaded image)
  • paper-unsplash-1440.png (the Unsplash search sheet, with stubbed test answers because this server has no key)

Decisions

  • Mesh: 4 radial blobs with a soft 3-stop falloff, in a .theme-mesh class on one fixed layer in app.html, so it paints on the first frame. Only transform animates, on one composited layer.
    • The layer is z-index 0, not -1, because themeColor.ts paints an opaque inline body background under overlays.
  • Blob colours: solved per theme for the strongest colour that keeps every text role ≥4.5:1 and every state role and control edge ≥3:1 at every point of the mesh. The test composites the full convex set.
    • Light themes use pastels at about the paper's luminance. Dark themes use jewel tones at 2–4× the paper's luminance.
  • Roles moved: to make room, text roles that sat at 4.5–4.9:1 moved to about 5:1, keeping their hue (for example paper --now #ba5130 → #b14827, one-dark --danger #e57078 → #f47e85).
  • Accents checked against upstream:
    • One Light: amber → its UI blue #2b60d8 (from #4078f2)
    • Ayu Light: brown #7e4b01 → orange #a75203
    • GitHub Dark: #2f81f7 → Primer's current #4493f8
  • New tokens:
    • --accent-2 (decorative) and --raised
    • --surface-sunken/card/raised aliases for the other agent's menus
    • --glass-tint and --glass-alpha per theme
  • [data-theme-scope]: theme blocks also match [data-theme-scope], so the Settings previews paint the other scheme's theme without duplicating data.
  • Readability floor: a solid colour or photo always gets the least --paper veil that keeps body and secondary text at 4.5:1 on the page and in the glass (readability.ts). The Dim slider starts at that floor.
    • Consequence: a vivid photo needs a heavy veil (93% in paper for the test image), so photos read washed out.
    • Follow-up worth grilling: a glass content pane when an image background is active, so the photo can show at full strength.
  • Deep link: /settings/appearance/background. /settings/appearance#background also resolves to it.
  • Upload naming: uploads get a generated name (background-<time>.<ext>), so no user text reaches the path.
## themes-backgrounds report (branch job/themes-backgrounds, not pushed or merged) ### Commits - 2129df1 fix(web): theme tokens have one source, @calternal/ui themes.css. calternal-app.css had a duplicate copy of 16 theme blocks that silently overrode themes.css. - ccb0e2b feat(themes): a background mesh, glass tint and surface steps per theme (plus the #app-background layer and drift) - a521505 fix(ui): file rows are clear over the app background. FileCollection rows were opaque --paper. - 8d83152 feat(settings): Appearance → Background, with a Light pick and a Dark pick - 238f293 perf(web): the background drift pauses under overlays and is off on touch - d294700 fix(settings): arrow keys move and select in the background radio groups - 24ec0f3 test(e2e): theme review screens and the drift measurement (layout-sweep.mjs --themes / --motion) ### Gates (apps/web) - `bun run check`: `COMPLETED 1389 FILES 0 ERRORS 0 WARNINGS 0 FILES_WITH_PROBLEMS` - `bun run test`: `Test Files 37 passed (37)` / `Tests 262 passed (262)` - `bun run build`: `✓ built in 1m 5s` - `bun run test:e2e:layout` (real local server built in the worktree): `checked 132 screens` / `LAYOUT SWEEP PASSED` - No Rust was changed, so the cargo gates were not run. ### Motion measurement Setup: Chromium, 4× CPU throttling, 390×844 at DPR 3 with touch, 10 s trace per run, 2 rounds, midnight and paper. The Settings sheet is open on the settings screen. The host was an 8-core VM with no GPU (software compositing) and a load average of 32–44 from other jobs. | screen | motion on fps | motion off fps | |---|---|---| | Files | 4.9–6.7 | 3.2–6.3 | | Files + sidebar sheet | 3.8–5.6 | 3.6–6.0 | | Settings | 3.8–4.9 | 3.4–4.4 | - Dropped frames were 90–96% in every run. Main-thread time was 0.2–68 ms/s in both states (noise). - The idle "off" runs are just as slow. The trace shows Viz DirectRenderer::DrawFrame taking about 100 ms per frame, so this host's software compositor is the limit. - A cheaper layer (2 blobs, a smaller moving layer) did not change the result: 8.7–13.5 fps against 14.4–16.2 fps for the default layer. - Desktop at 1440 with no throttle: 11.4 fps on Files and 8.3 fps on Settings (off runs: 9.7 and 8.6 fps). That is also host-bound. - Rule applied: the result is below 55 fps and the cost reduction did not help, so **the drift is off where the pointer is coarse**. It stays on for fine pointers. - The drift now also pauses under any scrim (Settings, Search, the viewer) and the phone drawer. There, the one live blur would otherwise re-filter on every frame. - A measurement on a real mid-range phone can lift the touch rule. The rule is one `@media (pointer: coarse)` block in lib/styles/background.css. - Raw numbers: target/theme-screens/motion-protocol.json ### Per theme All tests pass at these values. Glass alpha is at the design floor (55% light, 50% dark) everywhere, because a thinner tint would also pass. The tests enforce "least tint or floor". | Theme | Accent / accent-2 | Mesh stops (1-4) over paper | Glass tint, alpha | Worst text on mesh (ink / muted) | Worst text on glass (ink / muted) | |---|---|---|---|---|---| | paper | #3d5ac4 / #744ab4 | #f5f6f8 + #e8effe #f3efff #ccfcf3 #fff0e9 | #ffffff 55% | 14.21 / 4.74 | 15.36 / 5.13 | | meridian | #0b736f / #4458bc | #f1f5f4 + #b3faf4 #d1f5ff #ebf0fe #feefe0 | #ffffff 55% | 13.57 / 4.69 | 14.71 / 5.08 | | bloom | #a8326b / #6a55b0 | #f8f3f4 + #ffe7ed #feebe6 #f0edff #ffefe0 | #fffdfd 55% | 14.29 / 4.90 | 15.38 / 5.27 | | latte | #8738ed / #ea76cb | #eff1f5 + #ece7fe #ffe4f5 #d8f0ff #feebe3 | #eff1f5 55% | 6.63 / 5.19 | 6.84 / 5.35 | | solarized | #17668f / #2aa198 | #fdf6e3 + #fff0cf #c1fdf6 #e7f4ff #fff0eb | #eee8d5 55% | 11.45 / 5.59 | 10.82 / 5.29 | | rose-pine-dawn | #286983 / #907aa9 | #faf4ed + #feeae8 #feedd9 #f5ecff #d0f8ff | #fffaf3 55% | 8.20 / 4.80 | 8.65 / 5.06 | | midnight | #7c96f5 / #c29bf0 | #0f1320 + #1c266b #311861 #012828 #420d2d | #1b2236 50% | 11.35 / 4.77 | 11.93 / 5.02 | | ember | #e59a57 / #e5705a | #1a1614 + #442300 #4c130f #391930 #302201 | #291f1b 50% | 11.58 / 4.93 | 12.14 / 5.17 | | forest | #7fc79c / #d6b074 | #101613 + #00341d #002b2b #1f2800 #331e00 | #1c2620 50% | 11.35 / 4.86 | 11.74 / 5.03 | | tokyo-night | #7aa2f7 / #bb9af7 | #1a1b26 + #163274 #3e2464 #023248 #362155 | #202330 50% | 7.46 / 5.71 | 8.36 / 6.39 | | gruvbox | #8ec07c / #fe8019 | #282828 + #622806 #4a3202 #1b3c1d #4f2639 | #3c3836 50% | 10.14 / 8.39 | 10.00 / 8.27 | | frappe | #cfa2eb / #f4b8e4 | #303446 + #553a65 #34446a #55354d #194741 | #414559 50% | 6.30 / 5.28 | 6.17 / 5.17 | | macchiato | #c6a0f6 / #f5bde6 | #24273a + #472f61 #253964 #4c2743 #023b35 | #363a4f 50% | 7.66 / 6.31 | 7.48 / 6.16 | | mocha | #cba6f7 / #f5c2e7 | #1e1e2e + #41285a #18315a #441f3b #02332d | #313244 50% | 8.66 / 7.08 | 8.58 / 7.01 | | mono | #3a4046 / #6b7178 | #fafaf9 + #ecf5fd #fbf4ed #f1f7fc #f4f4f9 | #ffffff 55% | 16.14 / 5.76 | 17.05 / 6.08 | | noir | #c9cccf / #8a8d91 | #000000 + #191f30 #201827 #091d1c #1f170e | #141416 50% | 14.64 / 5.82 | 15.48 / 6.16 | | one-light | #2b60d8 / #a626a4 | #fafafa + #ecf3ff #fef1fd #eef7fe #fff6e8 | #ffffff 55% | 10.17 / 4.70 | 10.80 / 4.99 | | ayu-light | #a75203 / #399ee6 | #f8f9fa + #fff0e0 #eaf5ff #d4feec #fff3f3 | #fcfcfc 55% | 5.60 / 4.91 | 5.83 / 5.11 | | github-light | #0969da / #8250df | #ffffff + #f1f7fe #f9f8ff #eaffec #fefafc | #ffffff 55% | 14.65 / 5.67 | 15.19 / 5.88 | | nord | #88c0d0 / #b48ead | #2e3440 + #2a486b #104956 #553650 #154544 | #3b4252 50% | 8.14 / 6.95 | 8.33 / 7.11 | | dracula | #bd93f9 / #ff79c6 | #282a36 + #423258 #4f2b3f #13383f #2d354c | #343746 50% | 10.77 / 7.98 | 10.83 / 8.02 | | one-dark | #61afef / #c678dd | #282c34 + #093b5d #4a2a53 #003b41 #4e272a | #21252b 50% | 5.49 / 6.39 | 6.16 / 7.17 | | everforest | #a7c080 / #83c092 | #2d353b + #36441c #24442c #1b443f #513528 | #343f44 50% | 6.21 / 5.68 | 6.28 / 5.74 | | kanagawa | #7e9cd8 / #957fb8 | #1f1f28 + #073752 #392752 #05313f #43210c | #2a2a37 50% | 8.63 / 6.81 | 8.96 / 7.07 | | rose-pine | #9ccfd8 / #c4a7e7 | #191724 + #023242 #391b54 #4a0f23 #3e1818 | #1f1d2e 50% | 10.36 / 7.55 | 11.17 / 8.14 | | rose-pine-moon | #9ccfd8 / #c4a7e7 | #232136 + #043547 #38284a #46222b #3d2423 | #2a273f 50% | 9.92 / 7.23 | 10.14 / 7.39 | | ayu-dark | #e6b450 / #39bae6 | #0d1017 + #2e1f01 #012532 #341500 #261337 | #10141c 50% | 8.51 / 6.77 | 9.06 / 7.21 | | ayu-mirage | #ffcc66 / #5ccfe6 | #1f2430 + #3f2e09 #02363f #442520 #342740 | #242936 50% | 7.97 / 6.23 | 8.22 / 6.43 | | github-dark | #4493f8 / #ab7df8 | #0d1117 + #002450 #300f56 #002304 #3b0625 | #161b22 50% | 12.99 / 5.27 | 13.49 / 5.47 | ### Screenshots (/home/kayg/Developer/calternal/target/theme-screens/) - `<theme>-files-1440.png`, `<theme>-menu-1440.png` and `<theme>-settings-1440.png` for all 29 themes - `<theme>-{files,sidebar,menu,settings}-390.png` for paper, bloom, rose-pine-dawn, midnight, tokyo-night and mocha - `{paper,midnight}-background-card-1440.png`, `{paper,midnight}-background-settings-1440.png` and `{paper,midnight}-image-files-1440.png` (uploaded image) - `paper-unsplash-1440.png` (the Unsplash search sheet, with stubbed test answers because this server has no key) ### Decisions - **Mesh:** 4 radial blobs with a soft 3-stop falloff, in a `.theme-mesh` class on one fixed layer in app.html, so it paints on the first frame. Only `transform` animates, on one composited layer. - The layer is z-index 0, not -1, because themeColor.ts paints an opaque inline body background under overlays. - **Blob colours:** solved per theme for the strongest colour that keeps every text role ≥4.5:1 and every state role and control edge ≥3:1 at every point of the mesh. The test composites the full convex set. - Light themes use pastels at about the paper's luminance. Dark themes use jewel tones at 2–4× the paper's luminance. - **Roles moved:** to make room, text roles that sat at 4.5–4.9:1 moved to about 5:1, keeping their hue (for example paper `--now` #ba5130 → #b14827, one-dark `--danger` #e57078 → #f47e85). - **Accents checked against upstream:** - One Light: amber → its UI blue #2b60d8 (from #4078f2) - Ayu Light: brown #7e4b01 → orange #a75203 - GitHub Dark: #2f81f7 → Primer's current #4493f8 - **New tokens:** - `--accent-2` (decorative) and `--raised` - `--surface-sunken/card/raised` aliases for the other agent's menus - `--glass-tint` and `--glass-alpha` per theme - **[data-theme-scope]:** theme blocks also match `[data-theme-scope]`, so the Settings previews paint the other scheme's theme without duplicating data. - **Readability floor:** a solid colour or photo always gets the least `--paper` veil that keeps body and secondary text at 4.5:1 on the page and in the glass (readability.ts). The Dim slider starts at that floor. - Consequence: a vivid photo needs a heavy veil (93% in paper for the test image), so photos read washed out. - Follow-up worth grilling: a glass content pane when an image background is active, so the photo can show at full strength. - **Deep link:** `/settings/appearance/background`. `/settings/appearance#background` also resolves to it. - **Upload naming:** uploads get a generated name (`background-<time>.<ext>`), so no user text reaches the path.
Author
Owner

Merged dev (polish-menus-search) into job/themes-backgrounds: 0a5c804.

  • One glass system: polish's .glass-material, where --glass-tint picks the tint per surface. My per-theme tint colour is renamed --glass-base, because the old name would have made every glass surface opaque. It now feeds the page, scrim, clear and card tints. The per-theme --glass-alpha sets the page glass (sidebar, menus, popovers).
  • Contrast tests from both sides are kept. Every glass surface (sidebar and menus, sheet, card, palette, previews) is checked over the worst point of each theme's mesh. A new pin stops a theme from setting --glass-tint.
  • The sweep keeps every check and mode from both sides.
  • Gates: bun run check 0 errors 0 warnings; bun run test 40 files / 272 tests passed; bun run build built; test:e2e:layout (server built in the worktree) checked 164 screens, LAYOUT SWEEP PASSED.
  • Re-shot paper, tokyo-night and mocha at 1440 and 390 touch, plus polish's palette set, in /home/kayg/Developer/calternal/target/theme-screens/merge/. The glass reads correctly over the mesh on the sidebar, menus, palette and Settings.
Merged `dev` (polish-menus-search) into job/themes-backgrounds: 0a5c804. - One glass system: polish's `.glass-material`, where `--glass-tint` picks the tint per surface. My per-theme tint colour is renamed `--glass-base`, because the old name would have made every glass surface opaque. It now feeds the page, scrim, clear and card tints. The per-theme `--glass-alpha` sets the page glass (sidebar, menus, popovers). - Contrast tests from both sides are kept. Every glass surface (sidebar and menus, sheet, card, palette, previews) is checked over the worst point of each theme's mesh. A new pin stops a theme from setting `--glass-tint`. - The sweep keeps every check and mode from both sides. - Gates: `bun run check` 0 errors 0 warnings; `bun run test` 40 files / 272 tests passed; `bun run build` built; `test:e2e:layout` (server built in the worktree) checked 164 screens, LAYOUT SWEEP PASSED. - Re-shot paper, tokyo-night and mocha at 1440 and 390 touch, plus polish's palette set, in /home/kayg/Developer/calternal/target/theme-screens/merge/. The glass reads correctly over the mesh on the sidebar, menus, palette and Settings.
kayg closed this issue 2026-09-25 20:24:26 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#110
No description provided.