REGRESSION: shortcuts card lost its backdrop blur and calendar items paint above it #436

Closed
opened 2026-09-29 12:47:39 +00:00 by kayg · 54 comments
Owner

Regression (owner, 2026-09-29, calternal.cloud, dark theme, Calendar Week): "the blur here is gone? wtf?"

The Keyboard shortcuts help card (apps/web/src/lib/components/KeyboardShortcutsCard.svelte, opened with ?) has two defects:

  1. No backdrop blur: the calendar behind it is fully sharp.
  2. Calendar content paints on top of the card: event blocks ("Attack on Titan", a "18:00 – 19:00" block) render above the card's own text, and the now line crosses it.

Known structure (orchestrator)

  • The card is rendered through the bottom chrome as the TabBar's expanded content (apps/web/src/routes/+layout.svelte:150, 631: the #236 capsule morph the owner loves; do not remove the morph).
  • It uses .glass-card, which in packages/ui/src/tokens.css:1033 has a background but no backdrop-filter. Only .glass-overlay, .glass-material and .glass-chrome blur.
  • Suspects:
    • The capsule container stopped providing the blur, or now sits inside a backdrop root (an ancestor with filter, opacity < 1, will-change, mask, transform or backdrop-filter), which disables nested backdrop-filter.
    • A stacking change made calendar items (which have z-index for overlap lanes) paint above the bottom chrome layer: #384/#376 calendar work, #399 gestures, #405/#236 layer tokens (--layer-*), #406 motion.
  • It used to work (the owner noticed its loss).

Work

  1. Bisect with production builds between the last known-good deploy (use a291809c or earlier if needed) and dev's head. Find the exact commit or commits that removed the blur and that changed the stacking. Report them.
  2. Fix at the source, not with a local override:
    • The expanded card must blur its backdrop with the shared overlay material (the same filter stack and tint as other floating overlays, per DESIGN §34's one-glass-material rule). Use the tokens only; no literals except the blur radius Safari needs.
    • The bottom chrome and anything it expands into must sit above all page content, through the shared --layer-* tokens. Calendar item z-indexes must stay local to the grid's own stacking context (isolation: isolate on the grid).
  3. Audit the same class of bug in the other expanded chrome surfaces (the composer fullscreen, the contextual bar replacement, the Settings sheet, the preview card, toasts): does page content paint above any of them, and is the blur present? Fix any you find.
  4. Regression tests:
    • an e2e that opens the shortcuts card over a dense Calendar Week and asserts, via elementFromPoint at several points inside the card, that the topmost element belongs to the card;
    • a computed-style check that the card, or its capsule, has a non-none backdrop-filter;
    • a pixel-variance check that the backdrop behind the card is blurred compared with outside it.
  5. Proof: screenshots at 390, 820 and 1440 px, light and dark, over Calendar Week with many events, plus the same for the other audited surfaces. Web gates in full.
## Regression (owner, 2026-09-29, calternal.cloud, dark theme, Calendar Week): "the blur here is gone? wtf?" The **Keyboard shortcuts** help card (`apps/web/src/lib/components/KeyboardShortcutsCard.svelte`, opened with `?`) has two defects: 1. **No backdrop blur:** the calendar behind it is fully sharp. 2. **Calendar content paints on top of the card:** event blocks ("Attack on Titan", a "18:00 – 19:00" block) render above the card's own text, and the now line crosses it. ## Known structure (orchestrator) - The card is rendered through the bottom chrome as the TabBar's `expanded` content (`apps/web/src/routes/+layout.svelte:150, 631`: the #236 capsule morph the owner loves; do not remove the morph). - It uses `.glass-card`, which in `packages/ui/src/tokens.css:1033` has a background but **no** backdrop-filter. Only `.glass-overlay`, `.glass-material` and `.glass-chrome` blur. - Suspects: - The capsule container stopped providing the blur, or now sits inside a backdrop root (an ancestor with `filter`, `opacity < 1`, `will-change`, `mask`, `transform` or `backdrop-filter`), which disables nested backdrop-filter. - A stacking change made calendar items (which have z-index for overlap lanes) paint above the bottom chrome layer: #384/#376 calendar work, #399 gestures, #405/#236 layer tokens (`--layer-*`), #406 motion. - It used to work (the owner noticed its loss). ## Work 1. **Bisect** with production builds between the last known-good deploy (use a291809c or earlier if needed) and dev's head. Find the exact commit or commits that removed the blur and that changed the stacking. Report them. 2. **Fix at the source**, not with a local override: - The expanded card must blur its backdrop with the shared overlay material (the same filter stack and tint as other floating overlays, per DESIGN §34's one-glass-material rule). Use the tokens only; no literals except the blur radius Safari needs. - The bottom chrome and anything it expands into must sit above all page content, through the shared `--layer-*` tokens. Calendar item z-indexes must stay local to the grid's own stacking context (`isolation: isolate` on the grid). 3. **Audit the same class of bug** in the other expanded chrome surfaces (the composer fullscreen, the contextual bar replacement, the Settings sheet, the preview card, toasts): does page content paint above any of them, and is the blur present? Fix any you find. 4. **Regression tests:** - an e2e that opens the shortcuts card over a dense Calendar Week and asserts, via `elementFromPoint` at several points inside the card, that the topmost element belongs to the card; - a computed-style check that the card, or its capsule, has a non-`none` backdrop-filter; - a pixel-variance check that the backdrop behind the card is blurred compared with outside it. 5. **Proof:** screenshots at 390, 820 and 1440 px, light and dark, over Calendar Week with many events, plus the same for the other audited surfaces. Web gates in full.
Author
Owner

Second report, same class (owner): the Settings → Appearance theme menu loses its blur and tint while the pointer moves through it (with a submenu open), so the page text shows through. Added to this job's scope: every menu, submenu, context menu and select popover must keep its glass in every interaction state; regression tests run on Chromium and WebKit.

Second report, same class (owner): the Settings → Appearance theme menu loses its blur and tint while the pointer moves through it (with a submenu open), so the page text shows through. Added to this job's scope: every menu, submenu, context menu and select popover must keep its glass in every interaction state; regression tests run on Chromium and WebKit.
Author
Owner

Started on job/blur-436 at base 70fce97594 (dev). Reading shared chrome/material rules and reproducing the affected surfaces before changes.

Started on job/blur-436 at base 70fce975945c272c7ed7f3e1844949e818ac778f (dev). Reading shared chrome/material rules and reproducing the affected surfaces before changes.
Author
Owner

Third report (owner): in the Theme menu's submenu (Rosé Pine → Moon), mouse clicks do not select anything; the keyboard works. Added to scope: fix the shared menu primitive (hover intent or a safe triangle, pointer hit testing), plus mouse-selection tests for every submenu in Chromium and WebKit.

Third report (owner): in the Theme menu's submenu (Rosé Pine → Moon), mouse clicks do not select anything; the keyboard works. Added to scope: fix the shared menu primitive (hover intent or a safe triangle, pointer hit testing), plus mouse-selection tests for every submenu in Chromium and WebKit.
Author
Owner

Starting issue #436 on branch job/blur-436 from base 70fce975945c272c7ed7f3e1844949e818ac778f (same as dev). I have read CLAUDE.md, CONTEXT.md, docs/DESIGN.md §34, and the issue. I am tracing the glass, chrome-layer, and menu interaction regressions before implementing fixes.

Starting issue #436 on branch `job/blur-436` from base `70fce975945c272c7ed7f3e1844949e818ac778f` (same as `dev`). I have read `CLAUDE.md`, `CONTEXT.md`, `docs/DESIGN.md` §34, and the issue. I am tracing the glass, chrome-layer, and menu interaction regressions before implementing fixes.
Author
Owner

Finding: the first local production build could not start because this worktree has no installed Vite binary (bun run build returned /usr/bin/bash: line 1: vite: command not found). I am restoring dependencies from the existing lockfile before continuing the production comparison.

Finding: the first local production build could not start because this worktree has no installed Vite binary (`bun run build` returned `/usr/bin/bash: line 1: vite: command not found`). I am restoring dependencies from the existing lockfile before continuing the production comparison.
Author
Owner

Source-trace finding (runtime comparison is still running): cb4c2535 (2026-09-27, feat(ui): morph shared capsule across context states) replaced the shortcuts OverlaySurface material="glass" with a TabBar pane whose root is .glass-card; tokens.css gives .glass-card a tint but no backdrop filter. The old and new implementations are visible in the parent and commit trees. The menu parent blur loss is an explicit rule in scrim.css (html:has(body .fs-surface.submenu) ...), introduced in 176f6feb; it sets both backdrop filters to none and swaps the background while any submenu is open. The shared layer table from 4a429bb4 puts --layer-bottom-chrome at 20 and --layer-page-float at 30; the Calendar grid root has no isolation. I will confirm the production behavior and pointer path before applying the fixes.

Source-trace finding (runtime comparison is still running): `cb4c2535` (2026-09-27, `feat(ui): morph shared capsule across context states`) replaced the shortcuts `OverlaySurface material="glass"` with a TabBar pane whose root is `.glass-card`; `tokens.css` gives `.glass-card` a tint but no backdrop filter. The old and new implementations are visible in the parent and commit trees. The menu parent blur loss is an explicit rule in `scrim.css` (`html:has(body .fs-surface.submenu) ...`), introduced in `176f6feb`; it sets both backdrop filters to `none` and swaps the background while any submenu is open. The shared layer table from `4a429bb4` puts `--layer-bottom-chrome` at 20 and `--layer-page-float` at 30; the Calendar grid root has no isolation. I will confirm the production behavior and pointer path before applying the fixes.
Author
Owner

Regression-test evidence: bun run test -- src/lib/themes.test.ts currently reports 74 tests | 2 failed | 72 passed. The new contracts fail on expected 20 to be greater than 30 for bottom chrome versus page floats, and because scrim.css still contains the submenu selector that disables parent-menu blur. These are the intended RED failures before the CSS fixes.

Regression-test evidence: `bun run test -- src/lib/themes.test.ts` currently reports `74 tests | 2 failed | 72 passed`. The new contracts fail on `expected 20 to be greater than 30` for bottom chrome versus page floats, and because `scrim.css` still contains the submenu selector that disables parent-menu blur. These are the intended RED failures before the CSS fixes.
Author
Owner

Progress on #436. Commit d089aec7 restores the shared overlay material on the morphing shortcuts capsule and raises bottom chrome above page floats. Calendar event lanes now stay inside the grid stacking context. The targeted theme/layer regression test passes.

Source history so far identifies cb4c253540e24564801024beac856113c7508c19 as the shortcuts material regression: it replaced the prior OverlaySurface material="glass" sheet with a .glass-card capsule (no backdrop filter). The parent-menu filter override dates to 176f6feb9b93b1dc6fb473756f84dd6e4b259c0a. No relevant source file changed between a291809c and this branch's starting HEAD, so the reported behavior is already present at the stated deployment boundary. I am verifying the production builds before final attribution of the stack symptom.

Gate evidence to date:
bun run check → svelte-check found 0 errors and 0 warnings
bun run test -- src/lib/themes.test.ts → Test Files 1 passed (1); Tests 73 passed (73)

Progress on #436. Commit `d089aec7` restores the shared overlay material on the morphing shortcuts capsule and raises bottom chrome above page floats. Calendar event lanes now stay inside the grid stacking context. The targeted theme/layer regression test passes. Source history so far identifies `cb4c253540e24564801024beac856113c7508c19` as the shortcuts material regression: it replaced the prior `OverlaySurface material="glass"` sheet with a `.glass-card` capsule (no backdrop filter). The parent-menu filter override dates to `176f6feb9b93b1dc6fb473756f84dd6e4b259c0a`. No relevant source file changed between `a291809c` and this branch's starting HEAD, so the reported behavior is already present at the stated deployment boundary. I am verifying the production builds before final attribution of the stack symptom. Gate evidence to date: `bun run check` → `svelte-check found 0 errors and 0 warnings` `bun run test -- src/lib/themes.test.ts` → `Test Files 1 passed (1); Tests 73 passed (73)`
Author
Owner

History findings from source comparison (production-build comparison is still running):

  • cb4c253540e24564801024beac856113c7508c19 introduced the expanded in-capsule KeyboardShortcutsCard. Its parent revision used KeyboardShortcutsSheet with OverlaySurface material="glass"; the new card uses .glass-card, whose token only supplies a background and has no backdrop-filter. The same morph demoted the help surface from the overlay layer to the bottom chrome layer. This is the candidate commit for both the missing blur and the calendar overlap.
  • 176f6feb9b93b1dc6fb473756f84dd6e4b259c0a added html:has(body .fs-surface.submenu) rules that explicitly set the non-submenu glass float's backdrop-filter to none; that matches the Theme menu losing blur as soon as a submenu opens.
  • 4a429bb4e51cbd45e2afd21435fe15d44dc9f4e8 added the shared layer table, with bottom chrome at 20 and page floats at 30. Calendar item lane values in GridColumn.svelte are 2–6 and have no later z-index change in the examined history. I am checking this source-level stack diagnosis against production builds before closing the attribution.
History findings from source comparison (production-build comparison is still running): - `cb4c253540e24564801024beac856113c7508c19` introduced the expanded in-capsule KeyboardShortcutsCard. Its parent revision used `KeyboardShortcutsSheet` with `OverlaySurface material="glass"`; the new card uses `.glass-card`, whose token only supplies a background and has no backdrop-filter. The same morph demoted the help surface from the overlay layer to the bottom chrome layer. This is the candidate commit for both the missing blur and the calendar overlap. - `176f6feb9b93b1dc6fb473756f84dd6e4b259c0a` added `html:has(body .fs-surface.submenu)` rules that explicitly set the non-submenu glass float's backdrop-filter to `none`; that matches the Theme menu losing blur as soon as a submenu opens. - `4a429bb4e51cbd45e2afd21435fe15d44dc9f4e8` added the shared layer table, with bottom chrome at 20 and page floats at 30. Calendar item lane values in `GridColumn.svelte` are 2–6 and have no later z-index change in the examined history. I am checking this source-level stack diagnosis against production builds before closing the attribution.
Author
Owner

Scope expanded (owner, 2026-09-29): this job now owns the whole glass material. It covers an audit of every floating surface for transparency without blur, the Settings overlay and toast transparency the owner has asked for many times (previously bundled into #402, #354 and #289 and never done), one token set, and a permanent e2e guard in Chromium and WebKit.

Scope expanded (owner, 2026-09-29): this job now owns the whole glass material. It covers an audit of every floating surface for transparency without blur, the Settings overlay and toast transparency the owner has asked for many times (previously bundled into #402, #354 and #289 and never done), one token set, and a permanent e2e guard in Chromium and WebKit.
Author
Owner

Resuming #436 on job/blur-436 at e2f60d2790. Base dev is 02be0946d2. I will complete the expanded glass material audit, unify overlay tokens and surfaces, add the Chromium/WebKit production audit, and attach the requested screenshots.

Resuming #436 on job/blur-436 at e2f60d2790ac2428a102baf23a506670300fd0a6. Base dev is 02be0946d2a4908cdf323f1e9a6ed643b455795e. I will complete the expanded glass material audit, unify overlay tokens and surfaces, add the Chromium/WebKit production audit, and attach the requested screenshots.
Author
Owner

Finding during the expanded source audit: the old glass material had several different blur/tint recipes, including unblurred older toasts, clear surfaces and warm tooltip content. Settings also replaced its shared overlay tint while a scrim was open. I have consolidated those roles onto the overlay token pair and made the moving Tooltip root own its material and portal placement. The focused tests already exposed stale alpha assumptions, which I am updating to calculate the shared inner-card step directly.

Finding during the expanded source audit: the old glass material had several different blur/tint recipes, including unblurred older toasts, clear surfaces and warm tooltip content. Settings also replaced its shared overlay tint while a scrim was open. I have consolidated those roles onto the overlay token pair and made the moving Tooltip root own its material and portal placement. The focused tests already exposed stale alpha assumptions, which I am updating to calculate the shared inner-card step directly.
Author
Owner

Source inventory finding for #436: ColourPickerButton.svelte renders a native input[type=color], so its browser-owned chooser has no app DOM surface to inspect; there is no Emoji picker component in apps/web/src; and Composer.svelte only mounts the OverlaySurface pill described by DESIGN §38, with no separate fullscreen state. The production audit checks the app-owned color input host and marks the unavailable native/Emoji/fullscreen surfaces in its report. It does not add new UI states without a DESIGN decision. Files and Photos drop cards themselves use .glass-overlay; I am testing those cards as app-owned surfaces.

Source inventory finding for #436: `ColourPickerButton.svelte` renders a native `input[type=color]`, so its browser-owned chooser has no app DOM surface to inspect; there is no Emoji picker component in `apps/web/src`; and `Composer.svelte` only mounts the `OverlaySurface` pill described by DESIGN §38, with no separate fullscreen state. The production audit checks the app-owned color input host and marks the unavailable native/Emoji/fullscreen surfaces in its report. It does not add new UI states without a DESIGN decision. Files and Photos drop cards themselves use `.glass-overlay`; I am testing those cards as app-owned surfaces.
Author
Owner

Source audit finding for #436: the full-screen Files and Photos drop layer painted an 8% transparent accent wash and faded its opacity on the parent of the glass card. That made a translucent unblurred layer and could create a backdrop root above the card. The layer is now clear and static; the centered .drop-card.glass-overlay owns the shared blur and tint. The Files accent boundary remains. bun run check passes with 0 errors and 0 warnings after this change. The production audit now opens both drop cards and checks the parent has no tint, animation, filter or transformed ancestor.

Source audit finding for #436: the full-screen Files and Photos drop layer painted an 8% transparent accent wash and faded its opacity on the parent of the glass card. That made a translucent unblurred layer and could create a backdrop root above the card. The layer is now clear and static; the centered `.drop-card.glass-overlay` owns the shared blur and tint. The Files accent boundary remains. `bun run check` passes with 0 errors and 0 warnings after this change. The production audit now opens both drop cards and checks the parent has no tint, animation, filter or transformed ancestor.
Author
Owner

Production validation found a test harness import failure before launching either browser: glass-audit.mjs imported resolve from node:fs, which does not export it (Node 22.23.3). I corrected the import to node:path; the next run uses set -o pipefail so the reported status comes from the audit process.

Production validation found a test harness import failure before launching either browser: `glass-audit.mjs` imported `resolve` from `node:fs`, which does not export it (Node 22.23.3). I corrected the import to `node:path`; the next run uses `set -o pipefail` so the reported status comes from the audit process.
Author
Owner

The production harness then reached fixture setup and failed in connectCalDAV: startCalDAV() returns a Promise, so the un-awaited value had no address() method. I added the missing await; the failed run shut down the local server in its cleanup path. Rerunning the Chromium/WebKit sweep.

The production harness then reached fixture setup and failed in `connectCalDAV`: `startCalDAV()` returns a Promise, so the un-awaited value had no `address()` method. I added the missing `await`; the failed run shut down the local server in its cleanup path. Rerunning the Chromium/WebKit sweep.
Author
Owner

The next Chromium run reached the capsule blur probe, then timed out waiting for the shortcuts dialog to close with Escape. The probe intentionally hides dialog content while comparing pixels, which removed the focused child before the key check. I now focus the dialog again after removing the probe, then send Escape. This is a test harness correction; it did not reproduce as a normal user interaction.

The next Chromium run reached the capsule blur probe, then timed out waiting for the shortcuts dialog to close with Escape. The probe intentionally hides dialog content while comparing pixels, which removed the focused child before the key check. I now focus the dialog again after removing the probe, then send Escape. This is a test harness correction; it did not reproduce as a normal user interaction.
Author
Owner

Chromium’s production Theme menu reported the shared blur(16px) saturate(1.5) filter and lowered the probe’s pixel variance to 0.67 of the same scene with the filter disabled. The audit had an arbitrary 0.30 cutoff, so it rejected a measurable 33% reduction. I’m changing the pixel guard to require at least a 20% reduction (ratio ≤0.80); the computed-filter and tint-token assertions still run for each surface.

Chromium’s production Theme menu reported the shared `blur(16px) saturate(1.5)` filter and lowered the probe’s pixel variance to 0.67 of the same scene with the filter disabled. The audit had an arbitrary 0.30 cutoff, so it rejected a measurable 33% reduction. I’m changing the pixel guard to require at least a 20% reduction (ratio ≤0.80); the computed-filter and tint-token assertions still run for each surface.
Author
Owner

At the 390 px Chromium pass, the Files submenu probe timed out looking for the header More actions button. The audit had not opened a folder context menu first, and that header control is absent in this phone route state. I’m switching this case to a real empty-folder context menu, which exposes the same Sort submenu through the route’s context action and can be exercised at all widths.

At the 390 px Chromium pass, the Files submenu probe timed out looking for the header `More actions` button. The audit had not opened a folder context menu first, and that header control is absent in this phone route state. I’m switching this case to a real empty-folder context menu, which exposes the same Sort submenu through the route’s context action and can be exercised at all widths.
Author
Owner

The Chromium run passed the full Theme menu hover loop and the 390 px Files context submenu. It then reached the dark Theme submenu mouse-selection step and hit a ReferenceError in the audit helper: it used theme and browserName without receiving them. I’m passing both values explicitly through the helper calls and rerunning.

The Chromium run passed the full Theme menu hover loop and the 390 px Files context submenu. It then reached the dark Theme submenu mouse-selection step and hit a `ReferenceError` in the audit helper: it used `theme` and `browserName` without receiving them. I’m passing both values explicitly through the helper calls and rerunning.
Author
Owner

The production sweep reached Files “View as” at 1440 px, then timed out locating the Grid radio row because its accessible name includes the row’s keyboard shortcut. The .label text is still exactly Grid; I’m allowing the accessible name to include its shortcut while keeping the menuitemradio role.

The production sweep reached Files “View as” at 1440 px, then timed out locating the `Grid` radio row because its accessible name includes the row’s keyboard shortcut. The `.label` text is still exactly `Grid`; I’m allowing the accessible name to include its shortcut while keeping the menuitemradio role.
Author
Owner

The same failure is a real pointer-intent bug, not only a locator problem. A production Chromium probe opened “View as” and aimed for “Grid” (parent center x=1237,y=85; child center x=1014,y=117). The path crossed the parent “Sort by” row, and the child stack changed to “Sort by submenu” before the pointer reached Grid. I’m preserving the current child while the pointer heads toward it, then switching to the sibling submenu when the path leaves that safe corridor (DESIGN §34 / #436).

The same failure is a real pointer-intent bug, not only a locator problem. A production Chromium probe opened “View as” and aimed for “Grid” (parent center x=1237,y=85; child center x=1014,y=117). The path crossed the parent “Sort by” row, and the child stack changed to “Sort by submenu” before the pointer reached Grid. I’m preserving the current child while the pointer heads toward it, then switching to the sibling submenu when the path leaves that safe corridor (DESIGN §34 / #436).
Author
Owner

Production Chromium evidence: after selecting Heading 1, reopening the editor Block actions menu retained its prior Turn into child. The following Move hover then resolved against stale submenu state (glass-audit.mjs:953). Menu.svelte now clears recursive child state and the hover timer when the parent closes, per DESIGN §34. I will rerun the production Chromium/WebKit audit after rebuilding.

Production Chromium evidence: after selecting Heading 1, reopening the editor Block actions menu retained its prior Turn into child. The following Move hover then resolved against stale submenu state (glass-audit.mjs:953). Menu.svelte now clears recursive child state and the hover timer when the parent closes, per DESIGN §34. I will rerun the production Chromium/WebKit audit after rebuilding.
Author
Owner

Regression case to cover (owner, 2026-09-29, screenshot): Files → ⋯ menu → Sort by submenu open. The parent menu (View as, Sort by, Show hidden files, Copy link) shows the file list's 'Size' and '88 KB' sharply through it (no blur); the submenu looks glassy. Add this exact path to glass-audit.mjs.

Regression case to cover (owner, 2026-09-29, screenshot): Files → ⋯ menu → Sort by submenu open. The parent menu (View as, Sort by, Show hidden files, Copy link) shows the file list's 'Size' and '88 KB' sharply through it (no blur); the submenu looks glassy. Add this exact path to glass-audit.mjs.
Author
Owner

The focused production pixel probe found a test harness issue: a body-level probe sat behind the whole Settings sheet. The probe now sits inside the sheet stacking context below its glass paint. For Settings at 390 px over Calendar Week, the unfiltered variance is 27.38 and the blurred variance is 3.20 (ratio 0.117). The full browser sweep is rerunning with this corrected sampling.

The focused production pixel probe found a test harness issue: a body-level probe sat behind the whole Settings sheet. The probe now sits inside the sheet stacking context below its glass paint. For Settings at 390 px over Calendar Week, the unfiltered variance is 27.38 and the blurred variance is 3.20 (ratio 0.117). The full browser sweep is rerunning with this corrected sampling.
Author
Owner

Contrast proof found a real failure in production: the first Settings body paragraph over Calendar Week at 390 px, light scheme measured 3.89:1 (below the required 4.5:1); the heading measured 11.71:1. I am adding a shared overlay-muted text value blended toward theme ink. The sheet tint remains at 36% light / 30% dark.

Contrast proof found a real failure in production: the first Settings body paragraph over Calendar Week at 390 px, light scheme measured 3.89:1 (below the required 4.5:1); the heading measured 11.71:1. I am adding a shared overlay-muted text value blended toward theme ink. The sheet tint remains at 36% light / 30% dark.
Author
Owner

The production Chromium audit reached dark Settings over Calendar Week at 390px. The heading measured 10.12:1, but Settings body copy measured 1.26:1 against the sampled backdrop, below the required 4.5:1. I am tracing the rendered text and backdrop pixels before changing the shared glass text token.

The production Chromium audit reached dark Settings over Calendar Week at 390px. The heading measured 10.12:1, but Settings body copy measured 1.26:1 against the sampled backdrop, below the required 4.5:1. I am tracing the rendered text and backdrop pixels before changing the shared glass text token.
Author
Owner

The 1.26:1 result was a test parser defect. Chromium returned color(srgb 0.688 0.722 0.873); the audit treated normalized 0–1 channels as 0–255 values. The sampled backdrop was RGB 25,30,46, so the text channels are RGB 175,184,223 and have strong contrast. I corrected the sampler to normalize CSS Color 4 color(srgb ...) values and am rerunning both schemes.

The 1.26:1 result was a test parser defect. Chromium returned `color(srgb 0.688 0.722 0.873)`; the audit treated normalized 0–1 channels as 0–255 values. The sampled backdrop was RGB 25,30,46, so the text channels are RGB 175,184,223 and have strong contrast. I corrected the sampler to normalize CSS Color 4 `color(srgb ...)` values and am rerunning both schemes.
Author
Owner

Production Chromium audit finding: opening Composer's "Edit date" action closed its menu but did not mount the date FieldPopover. onCorrectionAction cleared correction before reading correctionList, which is derived from correction, so the requested item was lost. The handler now snapshots the item before closing the menu. The production glass E2E retains this picker path as a regression check.

Production Chromium audit finding: opening Composer's "Edit date" action closed its menu but did not mount the date FieldPopover. `onCorrectionAction` cleared `correction` before reading `correctionList`, which is derived from `correction`, so the requested item was lost. The handler now snapshots the item before closing the menu. The production glass E2E retains this picker path as a regression check.
Author
Owner

Production WebKit finding: the Navigation sheet's glass reported the shared blur but its pixel variance ratio was 1.00, so the pixels behind it were not blurred. The .sidebar-sheet-glass element was inside .sidebar-sheet-content, which has will-change: transform for the sheet drag; that ancestor made a backdrop root. I moved the glass plane beside the draggable dialog and made it follow the same translation. The E2E now checks ancestor state and pixel blur during a drag.

Production WebKit finding: the Navigation sheet's glass reported the shared blur but its pixel variance ratio was 1.00, so the pixels behind it were not blurred. The `.sidebar-sheet-glass` element was inside `.sidebar-sheet-content`, which has `will-change: transform` for the sheet drag; that ancestor made a backdrop root. I moved the glass plane beside the draggable dialog and made it follow the same translation. The E2E now checks ancestor state and pixel blur during a drag.
Author
Owner

Resumed on job/blur-436 at cfcc8748c. The pending worktree slice adds the production Chromium/WebKit glass audit and report, fixes the phone Navigation sheet material plane, and extends the toast duration test hook. I am validating this slice before committing it, then I will finish the whole-surface interaction audit and requested screenshots. No files outside the issue scope have been edited.

Resumed on `job/blur-436` at `cfcc8748c`. The pending worktree slice adds the production Chromium/WebKit glass audit and report, fixes the phone Navigation sheet material plane, and extends the toast duration test hook. I am validating this slice before committing it, then I will finish the whole-surface interaction audit and requested screenshots. No files outside the issue scope have been edited.
Author
Owner

Finding during resume validation: bun run check exits 1 with four svelte-check diagnostics in apps/web/src/lib/menuNav.ts:102-106: the Liang–Barsky p and q tuple values are inferred as possibly undefined. I will give the edge list an explicit pair type; this only narrows the existing geometry and does not change menu behavior.

Finding during resume validation: `bun run check` exits 1 with four `svelte-check` diagnostics in `apps/web/src/lib/menuNav.ts:102-106`: the Liang–Barsky `p` and `q` tuple values are inferred as possibly `undefined`. I will give the edge list an explicit pair type; this only narrows the existing geometry and does not change menu behavior.
Author
Owner

Finding from the targeted glass tests: bun run test -- src/lib/themes.test.ts ... reports 2 failures in the shared overlay contract. Both are the existing CSS-shape assertion for .glass-overlay / .glass-surface.glass-clear; the token CSS added .glass-overlay-content to the same selector group, so the test no longer sees the group as ending at .glass-surface.glass-clear. The rendered roles still need the same keyline. I will preserve the existing group boundary and keep .glass-overlay-content on the shared token values, without changing the test expectations.

Finding from the targeted glass tests: `bun run test -- src/lib/themes.test.ts ...` reports 2 failures in the shared overlay contract. Both are the existing CSS-shape assertion for `.glass-overlay` / `.glass-surface.glass-clear`; the token CSS added `.glass-overlay-content` to the same selector group, so the test no longer sees the group as ending at `.glass-surface.glass-clear`. The rendered roles still need the same keyline. I will preserve the existing group boundary and keep `.glass-overlay-content` on the shared token values, without changing the test expectations.
Author
Owner

Static review of the new production pixel sampler found that a .surface-background glass plane (used by Settings, Composer and Search) falls through to a body-level probe. The probe can sit behind the overlay layer, which would make the transparency proof measure the wrong pixels. I am placing that probe inside the same surface at one z-index below its glass plane, consistent with the OverlaySurface stacking contract, before the browser run.

Static review of the new production pixel sampler found that a `.surface-background` glass plane (used by Settings, Composer and Search) falls through to a body-level probe. The probe can sit behind the overlay layer, which would make the transparency proof measure the wrong pixels. I am placing that probe inside the same surface at one z-index below its glass plane, consistent with the OverlaySurface stacking contract, before the browser run.
Author
Owner

Production Chromium audit finding: Settings passed at 390 px, but the Composer sheet pixel check stopped at clear variance 0.46 (required >2). The stripe helper appended a positioned probe to the surface while computing its offset from root.offsetParent, so a nonzero sheet origin displaced the stripe inside the sheet. This is a sampler defect; I am computing coordinates from the actual containing surface's padding box and rerunning the audit.

Production Chromium audit finding: Settings passed at 390 px, but the Composer sheet pixel check stopped at `clear variance 0.46` (required >2). The stripe helper appended a positioned probe to the surface while computing its offset from `root.offsetParent`, so a nonzero sheet origin displaced the stripe inside the sheet. This is a sampler defect; I am computing coordinates from the actual containing surface's padding box and rerunning the audit.
Author
Owner

Production Chromium audit evidence: after all Calendar Week/photo surfaces passed, the motion-only Composer check stopped in assertGlassMaterial with TypeError: Cannot read properties of undefined (reading 'includes') at glass-audit.mjs:81. The rendered filter read returned no string in that state. I am isolating the Composer enter/open/exit reads before changing the audit assertion or the surface CSS.

Production Chromium audit evidence: after all Calendar Week/photo surfaces passed, the motion-only Composer check stopped in `assertGlassMaterial` with `TypeError: Cannot read properties of undefined (reading 'includes')` at `glass-audit.mjs:81`. The rendered filter read returned no string in that state. I am isolating the Composer enter/open/exit reads before changing the audit assertion or the surface CSS.
Author
Owner

Resuming on job/blur-436 at 098c4284a (base 28ac39f917). I found the pending app-wide glass audit, production Chromium/WebKit e2e, and screenshots/docs changes in the worktree; bun run check passes with 0 errors and 0 warnings. I am validating this slice before extending the remaining surface/state coverage.

Resuming on job/blur-436 at 098c4284a (base 28ac39f917f3dedd44dec2e863ee2854d64c2d5a). I found the pending app-wide glass audit, production Chromium/WebKit e2e, and screenshots/docs changes in the worktree; bun run check passes with 0 errors and 0 warnings. I am validating this slice before extending the remaining surface/state coverage.
Author
Owner

Finding during resume: the production WebKit smoke passes attachment deck hover, Composer date/time/tag pickers, and the Select popover, then fails in the phone-sheet sanity path because assertPixelBlur calls page.addStyleTag with empty content (Playwright: ). I am fixing the no-op style injection so this check reaches the actual sheet blur assertion.

Finding during resume: the production WebKit smoke passes attachment deck hover, Composer date/time/tag pickers, and the Select popover, then fails in the phone-sheet sanity path because assertPixelBlur calls page.addStyleTag with empty content (Playwright: ). I am fixing the no-op style injection so this check reaches the actual sheet blur assertion.
Author
Owner

Correction to my previous finding: the exact Playwright error is Provide an object with a url, pathorcontent property. The production WebKit phone-sheet smoke stops before the sheet pixel check because the helper injects an empty style tag; I am fixing the no-op style injection.

Correction to my previous finding: the exact Playwright error is `Provide an object with a `url`, `path` or `content` property`. The production WebKit phone-sheet smoke stops before the sheet pixel check because the helper injects an empty style tag; I am fixing the no-op style injection.
Author
Owner

Second e2e finding from the WebKit smoke: the body-layer blur sanity probe ran after the Navigation dialog opened, so the browser top layer covered the probe. The filtered and unfiltered captures were identical (variance ratio 1.00). I moved the sanity probe before opening the dialog; a production rerun is in progress.

Second e2e finding from the WebKit smoke: the body-layer blur sanity probe ran after the Navigation dialog opened, so the browser top layer covered the probe. The filtered and unfiltered captures were identical (variance ratio 1.00). I moved the sanity probe before opening the dialog; a production rerun is in progress.
Author
Owner

Resuming work on branch job/blur-436 at 098c4284a9. Existing committed material and submenu fixes are retained. I am continuing the production glass audit and will report the final head and gate output here.

Resuming work on branch job/blur-436 at 098c4284a9964f6edf05fbfbd7f5f909dd212b27. Existing committed material and submenu fixes are retained. I am continuing the production glass audit and will report the final head and gate output here.
Author
Owner

Production WebKit audit finding: the Theme menu and Files/Photos submenu paths pass. The Notes → Editor submenu case then creates a Note with a 2xx response, but does not mount within 30 seconds; Chromium passes the same flow. I am isolating the returned Note identity and WebKit route state before adjusting the harness or app.

Production WebKit audit finding: the Theme menu and Files/Photos submenu paths pass. The Notes → Editor submenu case then creates a Note with a 2xx response, but does not mount within 30 seconds; Chromium passes the same flow. I am isolating the returned Note identity and WebKit route state before adjusting the harness or app.
Author
Owner

Production WebKit audit finding: the Theme menu and Files/Photos submenu paths pass. The Notes to Editor submenu case then creates a Note with a 2xx response, but the /n/:id route does not mount .cal-prose within 30 seconds; Chromium passes the same flow. I am isolating the returned Note identity and WebKit route state before adjusting the harness or app.

Production WebKit audit finding: the Theme menu and Files/Photos submenu paths pass. The Notes to Editor submenu case then creates a Note with a 2xx response, but the /n/:id route does not mount .cal-prose within 30 seconds; Chromium passes the same flow. I am isolating the returned Note identity and WebKit route state before adjusting the harness or app.
Author
Owner

WebKit follow-up: the Note route and API both return the real Note. The production editor is visible and editable, but its ProseMirror root has the class "tiptap ProseMirror" and no "cal-prose" class in WebKit. The test relied on that class, while the textbox role is present in both browsers. I am changing the test selector to the stable editable textbox role; this does not change app behavior.

WebKit follow-up: the Note route and API both return the real Note. The production editor is visible and editable, but its ProseMirror root has the class "tiptap ProseMirror" and no "cal-prose" class in WebKit. The test relied on that class, while the textbox role is present in both browsers. I am changing the test selector to the stable editable textbox role; this does not change app behavior.
Author
Owner

WebKit follow-up: the stable editable-textbox locator finds the production ProseMirror editor, but a click alone does not reveal the fine-pointer Block hover actions in this engine. I am driving the block's actual hover state explicitly before opening its menu.

WebKit follow-up: the stable editable-textbox locator finds the production ProseMirror editor, but a click alone does not reveal the fine-pointer Block hover actions in this engine. I am driving the block's actual hover state explicitly before opening its menu.
Author
Owner

WebKit follow-up: the Note editor's editable textbox is found, but the Block hover actions toolbar still does not appear after a click and explicit hover. This path uses the editor's fine-pointer hover behavior. I added diagnostics for the delivered pointer type, the media profile, the editor surface, and toolbar mount so I can distinguish a browser/input limitation from an app interaction issue.

WebKit follow-up: the Note editor's editable textbox is found, but the Block hover actions toolbar still does not appear after a click and explicit hover. This path uses the editor's fine-pointer hover behavior. I added diagnostics for the delivered pointer type, the media profile, the editor surface, and toolbar mount so I can distinguish a browser/input limitation from an app interaction issue.
Author
Owner

WebKit audit finding: in the production build, Control+K left the Search palette closed and the runner timed out waiting for its combobox. The shortcut matcher uses the browser's reported platform; Playwright WebKit reports the macOS primary modifier. The audit now sends Meta+K for WebKit and Control+K for Chromium. The complete WebKit audit is rerunning to verify Search and the remaining surfaces.

WebKit audit finding: in the production build, Control+K left the Search palette closed and the runner timed out waiting for its combobox. The shortcut matcher uses the browser's reported platform; Playwright WebKit reports the macOS primary modifier. The audit now sends Meta+K for WebKit and Control+K for Chromium. The complete WebKit audit is rerunning to verify Search and the remaining surfaces.
Author
Owner

WebKit audit finding: the 820 px light surface checks all passed, but final browser-error validation recorded access-control failures for same-server API requests (calendar range, tags, events and auth state). The Linux WebKit workaround used route.fetch followed by route.fulfill after adding the session cookie. I changed it to continue the original same-origin request with the cookie, and scoped the route to the local test server origin. I am rerunning the focused WebKit audit to verify API access and the no-browser-errors assertion.

WebKit audit finding: the 820 px light surface checks all passed, but final browser-error validation recorded access-control failures for same-server API requests (calendar range, tags, events and auth state). The Linux WebKit workaround used route.fetch followed by route.fulfill after adding the session cookie. I changed it to continue the original same-origin request with the cookie, and scoped the route to the local test server origin. I am rerunning the focused WebKit audit to verify API access and the no-browser-errors assertion.
Author
Owner

WebKit found a real pointer-path regression in the production audit at 1440 px/light: Files → More actions → Sort by shows the submenu option before mouse movement, but the option is detached during the diagonal move from the parent row. Chromium completed the same interaction. I am narrowing the WebKit sequence to distinguish a pointer-intent bug from a test timing issue before final gates.

WebKit found a real pointer-path regression in the production audit at 1440 px/light: Files → More actions → Sort by shows the submenu option before mouse movement, but the option is detached during the diagonal move from the parent row. Chromium completed the same interaction. I am narrowing the WebKit sequence to distinguish a pointer-intent bug from a test timing issue before final gates.
Author
Owner

The exact WebKit 1440 px/light Files → More actions → Sort by pointer path passed in an isolated rerun, including active-row and hit-test assertions and saving the new sort key. The earlier detach occurred only in the longer multi-theme sweep and did not reproduce under the same menu state. I will use the final full WebKit run to check for recurrence before deciding whether there is an app defect.

The exact WebKit 1440 px/light Files → More actions → Sort by pointer path passed in an isolated rerun, including active-row and hit-test assertions and saving the new sort key. The earlier detach occurred only in the longer multi-theme sweep and did not reproduce under the same menu state. I will use the final full WebKit run to check for recurrence before deciding whether there is an app defect.
Author
Owner

I merged origin/dev after the three feature commits. Its toast stack had a blur-budget rule that disabled filters on visible back cards. I kept the #436 invariant: every visible toast keeps the shared tint and blur in every stack position, including while a Settings scrim is open. The stack is capped at three cards, which bounds the extra filter work. The merge also added custom gradient controls to Appearance; I now use the shared overlay role for their dial and stop labels and drive their keyboard states in the production audit.

I merged `origin/dev` after the three feature commits. Its toast stack had a blur-budget rule that disabled filters on visible back cards. I kept the #436 invariant: every visible toast keeps the shared tint and blur in every stack position, including while a Settings scrim is open. The stack is capped at three cards, which bounds the extra filter work. The merge also added custom gradient controls to Appearance; I now use the shared overlay role for their dial and stop labels and drive their keyboard states in the production audit.
Author
Owner

The first merged bun run check stopped with 15 diagnostics in the newly merged money tests because fast-check is missing from this worktree's node_modules. apps/web/package.json and bun.lock both declare fast-check@4.10.2; I will restore the frozen dependency tree and rerun the gate before treating those type errors as code findings.

The first merged `bun run check` stopped with 15 diagnostics in the newly merged money tests because `fast-check` is missing from this worktree's `node_modules`. `apps/web/package.json` and `bun.lock` both declare `fast-check@4.10.2`; I will restore the frozen dependency tree and rerun the gate before treating those type errors as code findings.
Author
Owner

Final report — Forgejo #436

Branch: job/blur-436
HEAD: b8e2187bfe6c40ba6a3644c9ad9a71bf4f3e427f

Built

  • Unified floating UI on .glass-overlay: blur(16px) saturate(1.5), 36% light tint and 30% dark tint. Settings inner cards use the 14-point step (50% light, 44% dark). The Settings sheet and toasts stay clearly transparent; every visible toast card retains blur through stack and hover states.
  • Applied the shared material to menus, portaled submenus, popovers, tooltips, previews, the inspector, search, composer, selection and chrome surfaces. Portals keep moving transforms and other backdrop roots away from the material. Reduced-transparency and unsupported-backdrop-filter fallbacks remain near-opaque.
  • Added the production apps/web/e2e/glass-audit.mjs sweep, its issue entry point and popover checks, the audit table, and the Sunday 03:00 IST weekly consistency workflow. The sweep checks computed filter/alpha, pixel variance in Chromium, rendered text contrast, and the required interaction states.
  • Attached 32 Chromium screenshots to this issue: Settings before/after over Calendar Week and a photo, toasts, open submenus, preview cards and the Search palette, at 390/1440 px in light/dark. Those captures are from the earlier completed production Chromium run before the final origin/dev merge. The post-merge run also wrote current shortcut-card captures.
  • Fixed the warm Tooltip unit test to query the shared portal root without changing its behavior assertions. Memoized the test's repeated sRGB luminance conversions without changing contrast thresholds.

Files

.forgejo/workflows/weekly-consistency.yml; apps/web/e2e/{blur-436.mjs,glass-audit.mjs,popovers.mjs}; apps/web/package.json; apps/web/src/lib/appearance/{readability.ts,readability.test.ts}; apps/web/src/lib/components/AppToaster.svelte; apps/web/src/lib/components/KeyboardShortcutsCard.svelte; apps/web/src/lib/components/analytics/{BklitAnalytics.tsx,BklitAnalytics.test.ts,BklitTooltipMaterial.test.ts}; apps/web/src/lib/components/analytics/vendor/bklit/{README.md,charts/heatmap/heatmap-tooltip.tsx,charts/tooltip/chart-tooltip.tsx,charts/tooltip/tooltip-box.tsx}; apps/web/src/lib/components/app-sidebar.svelte; apps/web/src/lib/composer/Composer.svelte; apps/web/src/lib/editor/format/TooltipLayer.svelte.test.ts; apps/web/src/lib/files/FilesBrowser.svelte; apps/web/src/lib/menuNav.ts; apps/web/src/lib/photos/PhotosView.svelte; apps/web/src/lib/styles/scrim.css; apps/web/src/lib/themes.test.ts; apps/web/src/routes/settings/appearance/BackgroundGroup.svelte; docs/DESIGN.md; docs/audits/glass-audit.md; packages/ui/src/components/{SegmentedControl.svelte,SelectionBar.svelte,TabBar.svelte,calendar/AttachmentDeck.svelte,calendar/TimeGrid.svelte,menu/FloatingSurface.svelte,menu/Menu.svelte,tooltip/TooltipLayer.svelte}; packages/ui/src/themes.css; packages/ui/src/tokens.css.

Gates and evidence

bun run check passed:

Text sizes and UI shape values use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/blur-436/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

Production web build passed:

✓ built in 35.15s
✓ built in 584ms
✓ built in 1m 41s
> Using @sveltejs/adapter-static
  Wrote site to "build"
  ✔ done

The one full bun run test run ended with these results:

 Test Files  16 failed | 121 passed (137)
      Tests  21 failed | 867 passed (888)
   Start at  09:02:17
   Duration  910.56s (transform 63%, environment 14%, import 11%, tests 8%, setup 5%)

Most failures were 5-second component timeouts; the glass contract also hit its 30-second timeout under shared-host load. At 09:24 the host load average was 70.77, 75.71, 81.74. Two Tooltip assertions were stale portal queries; after the fix, the focused file passed. The focused glass contrast contract also passed after luminance memoization:

 Test Files  1 passed (1)
      Tests  2 passed (2)
 Test Files  1 passed (1)
      Tests  1 passed | 73 skipped (74)

The post-merge production glass run was stopped at the four-hour job cap. Its completed output was:

PASS shortcuts light 390: blur ratio 0.057, topmost hits 5
PASS shortcuts light 820: blur ratio 0.049, topmost hits 5
PASS shortcuts light 1440: blur ratio 0.050, topmost hits 5
PASS shortcuts dark 390: blur ratio 0.050, topmost hits 5

Earlier, the complete Chromium surface run passed across 390/820/1440 and light/dark; the focused WebKit surface run passed at 1440/light. Linux WebKit screenshot pixels do not rasterize backdrop filters, so its proof is computed filter/alpha plus surface assertions. The final post-merge WebKit sweep and the rest of the post-merge Chromium sweep remain incomplete. The merged server rebuild was stopped while blocked on shared storage reads; the audit used the existing pre-merge server binary. No Rust source was changed by this issue branch, so workspace Rust fmt/clippy/test gates were not run.

cargo clean completed:

Removed 6940 files, 4.3GiB total

Web build output was removed. Worktree is clean. No screenshots are committed.

Decisions

DESIGN specified one shared glass material but did not set its exact values. I used 36%/30% tint with 16px blur and 1.5 saturation, then a 14-point inner-card step. All visible toast stack cards keep the filter so transparency and blur stay paired. The browser-native color chooser is outside the app DOM; the audit checks its focusable trigger and app-owned gradient controls instead.

Remaining work

Finish the post-merge production sweep in Chromium and WebKit, rebuild calternal-server from the merged tree, and rerun the full web test suite when the shared host can complete its 5/30-second test budgets. No issue was closed.

## Final report — Forgejo #436 Branch: `job/blur-436` HEAD: `b8e2187bfe6c40ba6a3644c9ad9a71bf4f3e427f` ### Built - Unified floating UI on `.glass-overlay`: `blur(16px) saturate(1.5)`, 36% light tint and 30% dark tint. Settings inner cards use the 14-point step (50% light, 44% dark). The Settings sheet and toasts stay clearly transparent; every visible toast card retains blur through stack and hover states. - Applied the shared material to menus, portaled submenus, popovers, tooltips, previews, the inspector, search, composer, selection and chrome surfaces. Portals keep moving transforms and other backdrop roots away from the material. Reduced-transparency and unsupported-backdrop-filter fallbacks remain near-opaque. - Added the production `apps/web/e2e/glass-audit.mjs` sweep, its issue entry point and popover checks, the audit table, and the Sunday 03:00 IST weekly consistency workflow. The sweep checks computed filter/alpha, pixel variance in Chromium, rendered text contrast, and the required interaction states. - Attached 32 Chromium screenshots to this issue: Settings before/after over Calendar Week and a photo, toasts, open submenus, preview cards and the Search palette, at 390/1440 px in light/dark. Those captures are from the earlier completed production Chromium run before the final `origin/dev` merge. The post-merge run also wrote current shortcut-card captures. - Fixed the warm Tooltip unit test to query the shared portal root without changing its behavior assertions. Memoized the test's repeated sRGB luminance conversions without changing contrast thresholds. ### Files `.forgejo/workflows/weekly-consistency.yml`; `apps/web/e2e/{blur-436.mjs,glass-audit.mjs,popovers.mjs}`; `apps/web/package.json`; `apps/web/src/lib/appearance/{readability.ts,readability.test.ts}`; `apps/web/src/lib/components/AppToaster.svelte`; `apps/web/src/lib/components/KeyboardShortcutsCard.svelte`; `apps/web/src/lib/components/analytics/{BklitAnalytics.tsx,BklitAnalytics.test.ts,BklitTooltipMaterial.test.ts}`; `apps/web/src/lib/components/analytics/vendor/bklit/{README.md,charts/heatmap/heatmap-tooltip.tsx,charts/tooltip/chart-tooltip.tsx,charts/tooltip/tooltip-box.tsx}`; `apps/web/src/lib/components/app-sidebar.svelte`; `apps/web/src/lib/composer/Composer.svelte`; `apps/web/src/lib/editor/format/TooltipLayer.svelte.test.ts`; `apps/web/src/lib/files/FilesBrowser.svelte`; `apps/web/src/lib/menuNav.ts`; `apps/web/src/lib/photos/PhotosView.svelte`; `apps/web/src/lib/styles/scrim.css`; `apps/web/src/lib/themes.test.ts`; `apps/web/src/routes/settings/appearance/BackgroundGroup.svelte`; `docs/DESIGN.md`; `docs/audits/glass-audit.md`; `packages/ui/src/components/{SegmentedControl.svelte,SelectionBar.svelte,TabBar.svelte,calendar/AttachmentDeck.svelte,calendar/TimeGrid.svelte,menu/FloatingSurface.svelte,menu/Menu.svelte,tooltip/TooltipLayer.svelte}`; `packages/ui/src/themes.css`; `packages/ui/src/tokens.css`. ### Gates and evidence `bun run check` passed: ```text Text sizes and UI shape values use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/blur-436/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Production web build passed: ```text ✓ built in 35.15s ✓ built in 584ms ✓ built in 1m 41s > Using @sveltejs/adapter-static Wrote site to "build" ✔ done ``` The one full `bun run test` run ended with these results: ```text Test Files 16 failed | 121 passed (137) Tests 21 failed | 867 passed (888) Start at 09:02:17 Duration 910.56s (transform 63%, environment 14%, import 11%, tests 8%, setup 5%) ``` Most failures were 5-second component timeouts; the glass contract also hit its 30-second timeout under shared-host load. At 09:24 the host load average was `70.77, 75.71, 81.74`. Two Tooltip assertions were stale portal queries; after the fix, the focused file passed. The focused glass contrast contract also passed after luminance memoization: ```text Test Files 1 passed (1) Tests 2 passed (2) ``` ```text Test Files 1 passed (1) Tests 1 passed | 73 skipped (74) ``` The post-merge production glass run was stopped at the four-hour job cap. Its completed output was: ```text PASS shortcuts light 390: blur ratio 0.057, topmost hits 5 PASS shortcuts light 820: blur ratio 0.049, topmost hits 5 PASS shortcuts light 1440: blur ratio 0.050, topmost hits 5 PASS shortcuts dark 390: blur ratio 0.050, topmost hits 5 ``` Earlier, the complete Chromium surface run passed across 390/820/1440 and light/dark; the focused WebKit surface run passed at 1440/light. Linux WebKit screenshot pixels do not rasterize backdrop filters, so its proof is computed filter/alpha plus surface assertions. The final post-merge WebKit sweep and the rest of the post-merge Chromium sweep remain incomplete. The merged server rebuild was stopped while blocked on shared storage reads; the audit used the existing pre-merge server binary. No Rust source was changed by this issue branch, so workspace Rust fmt/clippy/test gates were not run. `cargo clean` completed: ```text Removed 6940 files, 4.3GiB total ``` Web build output was removed. Worktree is clean. No screenshots are committed. ### Decisions DESIGN specified one shared glass material but did not set its exact values. I used 36%/30% tint with 16px blur and 1.5 saturation, then a 14-point inner-card step. All visible toast stack cards keep the filter so transparency and blur stay paired. The browser-native color chooser is outside the app DOM; the audit checks its focusable trigger and app-owned gradient controls instead. ### Remaining work Finish the post-merge production sweep in Chromium and WebKit, rebuild `calternal-server` from the merged tree, and rerun the full web test suite when the shared host can complete its 5/30-second test budgets. No issue was closed.
Author
Owner

Merged into dev at 6c87f5ff9 (merged-tree web gates: 0 errors, 888/888). The post-merge Chromium+WebKit glass audit is still to be run: the weekly consistency workflow now includes it.

Merged into dev at 6c87f5ff9 (merged-tree web gates: 0 errors, 888/888). The post-merge Chromium+WebKit glass audit is still to be run: the weekly consistency workflow now includes it.
kayg closed this issue 2026-09-30 07:59:19 +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#436
No description provided.