Audit: remove local restyling of shared components and hand-rolled controls app-wide #1190

Open
opened 2026-10-06 08:07:40 +00:00 by kayg · 102 comments
Owner

Audit: local restyling and hand-rolled controls (owner, 2026-10-06: "why so many instances of custom components again?")

Example found: apps/web/src/lib/editor/format/BlockHoverActions.svelte wraps the shared PillGroup frosted but adds its own ProgressiveBlur+wash slab and a hand-styled ⋯ button with px literals (#1189 fixes that file).

Do (whole repo, apps/web + packages):

  1. Find every place that (a) renders a shared primitive (Pill, PillGroup, PrimaryPill, StatusPill, TagPill, Menu/MenuItem, FloatingSurface, Card/metric cards, Kbd, ItemPreview, ProgressiveBlur, scroll-edge blur, Inspector rows) and then overrides its look locally (:global(...) selectors into it, extra background/backdrop-filter/border/shadow/radius/hover colours, wrapper overlays); (b) draws its own button/pill/chip/menu/card/toggle instead of the shared one; (c) uses size/colour/radius/duration literals outside token files.
  2. Write the full list with file:line, category (a/b/c) and the shared component that should be used to artifacts/restyle-audit.md and post it on this issue, grouped by Tab.
  3. Fix them mechanically in small commits per area, by EXTENDING the shared primitive (new prop/variant + tests + doc) where a needed look is missing, then deleting the local overrides. No visual redesigns beyond restoring the shared look.
  4. Add a lint/design-rule test that fails on new :global overrides into shared primitive classes and on new hand-rolled <button class=…> controls in feature folders (with an allow-list for justified exceptions, each with a comment and issue link).
    Screenshots before/after of each changed surface at ACTUAL size (1x/2x), light + dark. Gates: bun run check + bun run test quoted. Commit; comment with head SHA. Do not push.
## Audit: local restyling and hand-rolled controls (owner, 2026-10-06: "why so many instances of custom components again?") Example found: apps/web/src/lib/editor/format/BlockHoverActions.svelte wraps the shared `PillGroup frosted` but adds its own ProgressiveBlur+wash slab and a hand-styled ⋯ button with px literals (#1189 fixes that file). Do (whole repo, apps/web + packages): 1. Find every place that (a) renders a shared primitive (Pill, PillGroup, PrimaryPill, StatusPill, TagPill, Menu/MenuItem, FloatingSurface, Card/metric cards, Kbd, ItemPreview, ProgressiveBlur, scroll-edge blur, Inspector rows) and then overrides its look locally (`:global(...)` selectors into it, extra background/backdrop-filter/border/shadow/radius/hover colours, wrapper overlays); (b) draws its own button/pill/chip/menu/card/toggle instead of the shared one; (c) uses size/colour/radius/duration literals outside token files. 2. Write the full list with file:line, category (a/b/c) and the shared component that should be used to `artifacts/restyle-audit.md` and post it on this issue, grouped by Tab. 3. Fix them mechanically in small commits per area, by EXTENDING the shared primitive (new prop/variant + tests + doc) where a needed look is missing, then deleting the local overrides. No visual redesigns beyond restoring the shared look. 4. Add a lint/design-rule test that fails on new `:global` overrides into shared primitive classes and on new hand-rolled `<button class=…>` controls in feature folders (with an allow-list for justified exceptions, each with a comment and issue link). Screenshots before/after of each changed surface at ACTUAL size (1x/2x), light + dark. Gates: `bun run check` + `bun run test` quoted. Commit; comment with head SHA. Do not push.
Author
Owner

Starting #1190 in job/restyle-1190, based on origin/dev at 5301e020859c1d61b4a7f812a5049a64241203e8. I have read CLAUDE.md, docs/DESIGN.md, and CONTEXT.md. I am mapping shared primitive overrides, hand-rolled controls, and non-token visual literals across apps/web and packages before making small area commits.

Starting #1190 in `job/restyle-1190`, based on `origin/dev` at `5301e020859c1d61b4a7f812a5049a64241203e8`. I have read `CLAUDE.md`, `docs/DESIGN.md`, and `CONTEXT.md`. I am mapping shared primitive overrides, hand-rolled controls, and non-token visual literals across `apps/web` and `packages` before making small area commits.
Author
Owner

Initial full inventory from 5301e020859c1d61b4a7f812a5049a64241203e8. It groups findings by Tab and lists file, line, category, and the shared primitive or token family. The BlockHoverActions wash slab is assigned to #1189.

Restyle audit — Forgejo #1190

Inventory from 2026-10-06 in apps/web and packages. Each entry has a file and line. Category (a) is a local style override of a shared primitive class or an extra surface around one. Category (b) is app-owned button, pill, chip, menu, card, or toggle markup and names the shared control to use. Category (c) is a literal control size, colour, radius, or duration outside token files and names the shared primitive.

Calendar (0 a, 1 b, 7 c)

(b)

  • [apps/web/src/routes/calendar/[view]/[date]/+page.svelte:3096] — Pill (or PillGroup for adjacent actions).

(c)

  • [packages/ui/src/components/calendar/ActivityStack.svelte:141] — .card → border: 1px solid color-mix(in srgb, var(--hair) 80%, transparent); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); use Card and shared tokens.
  • [packages/ui/src/components/calendar/AttachmentDeck.svelte:969] — :global(.attachment-actions .pg-btn) → gap: 4px; padding-inline: 8px; use PillGroup and shared tokens.
  • [packages/ui/src/components/calendar/TaskCheckbox.svelte:51] — :global(.task-checkbox-wrap > .checkbox-control) → width: var(--hit, 44px); height: var(--hit, 44px); use Checkbox and shared tokens.
  • [packages/ui/src/components/calendar/TaskCheckbox.svelte:57] — :global(.task-checkbox-wrap .checkbox-indicator.editor) → width: 16px; height: 16px; use Checkbox and shared tokens.
  • [packages/ui/src/components/calendar/TimeGrid.svelte:1983] — .chip → gap: 5px; height: 22px; padding: 0 7px; use Pill / TagPill and shared tokens.
  • [packages/ui/src/components/calendar/TimeGrid.svelte:2006] — .chip :global(svg) → width: 13px; height: 13px; use Pill / TagPill and shared tokens.
  • [packages/ui/src/components/calendar/YearHeatmap.svelte:197] — button.d:hover → box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--ink) 40%, transparent); use Pill and shared tokens.

Tasks (6 a, 10 b, 3 c)

(a)

  • [apps/web/src/lib/tasks/TaskCard.svelte:75] — .card.task-card → box-sizing: border-box; position: relative; display: block; width: 100%; height: auto; min-height: 0; padding: 0.55rem 0.65rem; text-shadow: none;; extend Card.
  • [apps/web/src/lib/tasks/TaskCard.svelte:89] — .checkbox-input-wrap → margin-block-start: 0.2rem;; extend Checkbox.
  • [apps/web/src/lib/tasks/TaskCard.svelte:97] — .status-pill-frame.task-status-pill .status-pill → --pill-nav-height: 1.4rem; --pill-nav-padding: 0.08rem 0.45rem; --pill-nav-font-size: var(--text-caption); min-height: 1.4rem; max-width: none;; extend StatusPill.
  • [apps/web/src/lib/tasks/TaskColumn.svelte:186] — .card.task-card → outline: 1px dashed var(--accent); outline-offset: -2px;; extend Card.
  • [apps/web/src/lib/tasks/TaskList.svelte:69] — .card.task-list-card → min-width: 0; overflow: hidden; text-shadow: none;; extend Card.
  • [apps/web/src/lib/tasks/TaskList.svelte:90] — .status-pill-frame.task-status-pill .status-pill → --pill-nav-height: 1.4rem; --pill-nav-padding: 0.08rem 0.45rem; --pill-nav-font-size: var(--text-caption); min-height: 1.4rem; max-width: none;; extend StatusPill.

(b)

  • [apps/web/src/lib/tasks/TaskColumn.svelte:131] — Card.
  • [apps/web/src/lib/tasks/TaskColumn.svelte:172] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:632] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:638] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:646] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:655] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:657] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:659] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:672] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/tasks/TaskSection.svelte:679] — Pill (or PillGroup for adjacent actions).

(c)

  • [apps/web/src/lib/tasks/TaskCard.svelte:74] — :global(.card.task-card) → padding: 0.55rem 0.65rem; use Card and shared tokens.
  • [apps/web/src/lib/tasks/TasksWorkspace.svelte:486] — .view-add button → min-height: 2.65rem; border: 1px solid var(--hair); padding: 0 1rem; use Pill and shared tokens.
  • [apps/web/src/lib/tasks/TasksWorkspace.svelte:489] — .tasks-state button → min-height: 2.5rem; border: 1px solid var(--hair); padding: 0 0.8rem; use Pill and shared tokens.

Notes (8 a, 27 b, 11 c)

(a)

  • [apps/web/src/lib/editor/format/BlockHoverActions.svelte:250] — extra ProgressiveBlur wash slab behind PillGroup; remove the slab and keep the shared capsule material (#1189).
  • [apps/web/src/lib/notes/NoteContents.svelte:364] — .surface.note-contents-sheet .sheet-scroll → overscroll-behavior: contain;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notes/NoteContents.svelte:370] — .surface.note-contents-sheet .sheet-chrome → background: transparent;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notes/NoteContents.svelte:372] — .surface.note-contents-sheet .sheet-title-row → grid-template-columns: minmax(0, 1fr); justify-items: center;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notes/NoteContents.svelte:376] — .surface.note-contents-sheet .sheet-leading → grid-column: 1; justify-self: center;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notes/NoteContents.svelte:383] — .surface.note-contents-sheet .sheet-title → position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notes/NoteView.svelte:2566] — .card.glass-card → box-shadow: none;; extend Card.
  • [apps/web/src/lib/notes/NoteView.svelte:2674] — .note-stack .note-card.card.note-card--segmented → background: transparent; border-color: transparent; box-shadow: none;; extend Card.

(b)

  • [apps/web/src/lib/canvas/CanvasItemCard.svelte:56] — Card.
  • [apps/web/src/lib/canvas/CanvasItemCard.svelte:57] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/canvas/CanvasItemCard.svelte:69] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/canvas/CanvasItemCard.svelte:70] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/canvas/CanvasItemCard.svelte:72] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/canvas/CanvasPreview.svelte:92] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/BlockHoverActions.svelte:260] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:284] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:302] — Pill or TagPill.
  • [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:308] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:315] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:321] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/editor/format/FormatButton.svelte:64] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notes/NoteContents.svelte:166] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notes/NoteContents.svelte:211] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notes/NoteImageView.svelte:121] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notes/NoteView.svelte:2211] — Card.
  • [apps/web/src/lib/notes/NoteView.svelte:2216] — Card.
  • [apps/web/src/lib/notes/NoteView.svelte:2223] — Card.
  • [apps/web/src/lib/notes/NoteView.svelte:2226] — Card.
  • [apps/web/src/lib/notes/NoteView.svelte:2234] — Card.
  • [apps/web/src/lib/notes/NotesExplorer.svelte:463] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notes/NotesExplorer.svelte:507] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/journal/+page.svelte:78] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/notes/+page.svelte:175] — Pill (or PillGroup for adjacent actions).
  • [packages/editor/src/components/CalloutView.svelte:27] — Pill (or PillGroup for adjacent actions).
  • [packages/editor/src/components/TaskItemView.svelte:66] — Checkbox.

(c)

  • [apps/web/src/lib/canvas/CanvasView.svelte:486] — .canvas-elements-row :global(button) → min-height:44px; use Pill and shared tokens.
  • [apps/web/src/lib/canvas/DrawingBlock.svelte:469] — :global(.drawing-block .App-toolbar--mobile button), :global(.drawing-block .App-toolbar--mobile .ToolIcon) → min-width: 44px; min-height: 44px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:124] — .format-button.wide → gap: 7px; padding-inline: 8px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:151] — .format-button → width: 28px; min-width: 28px; height: 28px; min-height: 28px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:157] — .format-button.wide → height: 28px; min-height: 28px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:161] — .format-button → width: 44px; min-width: 44px; height: 44px; min-height: 44px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:169] — .format-button.wide → min-width: 44px; min-height: 44px; padding-inline: 10px; use Pill and shared tokens.
  • [apps/web/src/lib/editor/format/FormatButton.svelte:97] — .format-button → width: 28px; min-width: 28px; height: 28px; min-height: 28px; use Pill and shared tokens.
  • [apps/web/src/lib/notes/NoteView.svelte:2937] — .note-state-actions a, .note-state-actions button → min-height: 40px; padding: 0 16px; use Pill and shared tokens.
  • [packages/ui/src/components/notes/NoteMentionsCard.svelte:320] — :global(.mention-count.pill.count) → width: 24px; min-width: 24px; height: 24px; min-height: 24px; padding: 0 3px; use Card and shared tokens.
  • [packages/ui/src/components/notes/NoteProperties.svelte:294] — :global(.properties-count.pill.count) → width: 20px; min-width: 20px; height: 20px; min-height: 20px; padding: 0 3px; use Pill and shared tokens.

Files (6 a, 58 b, 1 c)

(a)

  • [apps/web/src/lib/files/FilesBrowser.svelte:1826] — .surface.dialog.paste-upload-conflict → width: min(460px, calc(100vw - 32px)); translate: -50% -50%;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/files/ShareDialog.svelte:493] — .surface.sheet.share-sheet → max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/files/ShareDialog.svelte:495] — .surface.dialog.share-sheet → width: min(580px, calc(100vw - 32px)); max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/files/ShareDialog.svelte:641] — .pg-btn → display: grid; width: var(--control-h); height: var(--control-h); place-items: center; border: 0; border-radius: var(--radius-circle); background: transparent; color: var(--ink-muted); cursor: pointer; --pill-group-glyph-size: var(--icon);; extend PillGroup.
  • [apps/web/src/lib/files/ShareDialog.svelte:653] — .pg-btn:hover → background: color-mix(in srgb, var(--ink) 7%, transparent); color: var(--ink);; extend PillGroup.
  • [apps/web/src/lib/files/SharedByYou.svelte:165] — .pg-btn → display: grid; width: var(--control-h); height: var(--control-h); place-items: center; border: 0; border-radius: var(--radius-circle); background: transparent; color: var(--ink-muted); cursor: pointer; --pill-group-glyph-size: var(--icon);; extend PillGroup.

(b)

  • [apps/web/src/lib/files/FilesBrowser.svelte:1620] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1621] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1628] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1633] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1645] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1646] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesBrowser.svelte:1700] — Card.
  • [apps/web/src/lib/files/FilesBrowser.svelte:1762] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesSidebar.svelte:196] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesSidebar.svelte:216] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesSidebar.svelte:217] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/FilesSidebar.svelte:218] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:613] — Card.
  • [apps/web/src/lib/files/InfoPanel.svelte:664] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:665] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:671] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:679] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:688] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:722] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:728] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:758] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:825] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/InfoPanel.svelte:840] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:467] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:473] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:476] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:481] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:483] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:512] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:514] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:521] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:523] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:529] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:532] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:540] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:553] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:580] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:585] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:593] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:600] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:603] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:609] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:620] — Card.
  • [apps/web/src/lib/files/PublicLinkPage.svelte:628] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/PublicLinkPage.svelte:635] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/ShareDialog.svelte:323] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/ShareDialog.svelte:341] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/ShareDialog.svelte:374] — Pill.
  • [apps/web/src/lib/files/ShareDialog.svelte:391] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/ShareDialog.svelte:392] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/SharedByYou.svelte:86] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:130] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:136] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:146] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:163] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:165] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:167] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/files/UploadToast.svelte:170] — Pill (or PillGroup for adjacent actions).

(c)

  • [apps/web/src/lib/files/ShareDialog.svelte:746] — .pill-icon-label → gap: 6px; use Pill and shared tokens.

Photos (0 a, 7 b, 1 c)

(b)

  • [apps/web/src/lib/photos/PhotoViewer.svelte:372] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/photos/PhotoViewer.svelte:387] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/photos/PhotosView.svelte:857] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/photos/PhotosView.svelte:894] — Card.
  • [apps/web/src/lib/photos/PhotosView.svelte:913] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/photos/PhotosView.svelte:926] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/photos/PhotosView.svelte:928] — Pill (or PillGroup for adjacent actions).

(c)

  • [apps/web/src/lib/photos/BackgroundsFolderView.svelte:167] — .empty button → padding: 0 14px; use Pill and shared tokens.

Mail (2 a, 8 b, 0 c)

(a)

  • [apps/web/src/lib/mail/MailView.svelte:1534] — .pill → grid-area: action;; extend Pill.
  • [apps/web/src/lib/mail/MailView.svelte:1539] — .pill → justify-self: start;; extend Pill.

(b)

  • [apps/web/src/lib/mail/MailMorphCard.svelte:61] — Card.
  • [apps/web/src/lib/mail/MailView.svelte:1389] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1411] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1421] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1442] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1456] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1477] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/mail/MailView.svelte:1478] — Pill (or PillGroup for adjacent actions).

Money (0 a, 7 b, 0 c)

(b)

  • [apps/web/src/routes/money/[budget]/[month]/+page.svelte:278] — Card.
  • [apps/web/src/routes/money/[budget]/[month]/+page.svelte:301] — Card.
  • [apps/web/src/routes/money/[budget]/[month]/+page.svelte:364] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/money/[budget]/accounts/account/+page.svelte:328] — Card.
  • [apps/web/src/routes/money/[budget]/accounts/account/+page.svelte:334] — Card.
  • [apps/web/src/routes/money/[budget]/accounts/account/+page.svelte:385] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/money/[budget]/accounts/account/+page.svelte:410] — Pill (or PillGroup for adjacent actions).

Search (9 a, 20 b, 14 c)

(a)

  • [apps/web/src/lib/components/search-dialog.svelte:1145] — .surface.pill.search-window → display: flex; flex-direction: column; width: var(--palette-width); /* The top stays at --palette-top; the bottom stops at two-thirds height. */ max-height: max(0px, min(calc(66.666dvh - var(--palette-top)), 44rem)); transition: height var(--dur-morph) var(--ease-spring), width var(--dur-search) var(--ease-out), max-height var(--dur-search) var(--ease-out);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/search-dialog.svelte:1158] — .surface.pill.search-window.has-preview → width: var(--palette-width-preview);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/search-dialog.svelte:1163] — .surface.pill.search-window.is-expanded → top: max(24px, 4dvh); width: min(76rem, calc(100vw - 32px)); height: min(92dvh, 64rem); max-height: min(92dvh, 64rem);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/search-dialog.svelte:1175] — :root .surface.pill.search-window.is-expanded → --search-band: calc(var(--search-vv-height, 100dvh) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 16px); width: calc(100vw - 16px); max-height: var(--search-band);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/search-dialog.svelte:1183] — :root .surface.pill.search-window.is-expanded → top: calc(var(--search-vv-top, 0px) + var(--search-vv-height, 100dvh) / 2); translate: 0 -50%; height: auto;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/search-dialog.svelte:1199] — .surface.pill.search-window → transition: none;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/search/SearchPreview.svelte:1061] — .actions > .pill-group → min-width: 0; max-width: 100%; flex-wrap: wrap;; extend PillGroup.
  • [apps/web/src/lib/search/SearchPreview.svelte:1066] — .actions > .pill-group:last-child → margin-left: 0;; extend PillGroup.
  • [apps/web/src/lib/search/SearchResultRow.svelte:261] — .item-card → gap: var(--search-result-icon-gap);; extend ItemCard.

(b)

  • [apps/web/src/lib/components/search-dialog.svelte:868] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:869] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:878] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:899] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:909] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:919] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:928] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/search-dialog.svelte:939] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/search/SavedSearchList.svelte:184] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/search/SearchField.svelte:281] — Pill or TagPill.
  • [apps/web/src/lib/search/SearchField.svelte:282] — Pill or TagPill.
  • [apps/web/src/lib/search/SearchField.svelte:287] — Pill or TagPill.
  • [apps/web/src/lib/search/SearchField.svelte:293] — Pill.
  • [apps/web/src/lib/search/SearchField.svelte:300] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/search/SearchField.svelte:313] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/search/SearchPreview.svelte:683] — Card.
  • [apps/web/src/lib/search/SearchPreview.svelte:770] — Pill.
  • [apps/web/src/lib/search/SearchPreview.svelte:795] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/search/SearchPreview.svelte:799] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/tag/[tag]/+page.svelte:205] — Pill (or PillGroup for adjacent actions).

(c)

  • [apps/web/src/lib/components/search-dialog.svelte:1141] — :global(.surface.pill.search-window) → max-height: max(0px, min(calc(66.666dvh - var(--palette-top)), 44rem)); use Pill and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1163] — :global(.surface.pill.search-window.is-expanded) → width: min(76rem, calc(100vw - 32px)); height: min(92dvh, 64rem); max-height: min(92dvh, 64rem); use Pill and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1173] — :global(:root .surface.pill.search-window), :global(:root .surface.pill.search-window.is-expanded) → width: calc(100vw - 16px); use Pill and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1192] — :global(:root .surface.pill.search-window.is-expanded) .sw → max-height: calc(var(--search-band) - 2px); use Pill and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1220] — :global(.surface.pill.search-window) .sw → --search-edge-blur-height: 2rem; use Pill and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1284] — .expanded .results-list :global(.row:not(.card)) → height: 58px; use Card and shared tokens.
  • [apps/web/src/lib/components/search-dialog.svelte:1305] — :global(.surface.pill.search-window.preview-resized) .preview-pane → width: var(--palette-preview-width, var(--search-preview-width, 300px)); use Pill and shared tokens.
  • [apps/web/src/lib/search/SearchField.svelte:496] — .q-pill button, .scope-chip button → width: 20px; height: 20px; use Pill and shared tokens.
  • [apps/web/src/lib/search/SearchField.svelte:524] — .q-pill button :global(svg), .scope-chip button :global(svg) → width: 12px; height: 12px; use Pill and shared tokens.
  • [apps/web/src/lib/search/SearchField.svelte:532] — .q-pill button, .scope-chip button → width: 44px; height: 44px; use Pill and shared tokens.
  • [apps/web/src/lib/search/SearchField.svelte:547] — .action-trailing → gap: 6px; use shared control primitive and shared tokens.
  • [apps/web/src/lib/search/SearchPreview.svelte:1118] — .action → width: 34px; height: 34px; border: 1px solid var(--control-boundary); use shared control primitive and shared tokens.
  • [apps/web/src/lib/search/SearchResultRow.svelte:339] — .row.card → min-height: 52px; padding: 11px 14px 11px calc(var(--search-column-inset, 18px) - var(--search-row-inset, 6px) - 1px); use Card and shared tokens.
  • [apps/web/src/lib/search/SearchResultRow.svelte:351] — .row.card .line1 → row-gap: 1px; use Card and shared tokens.

Settings (18 a, 34 b, 10 c)

(a)

  • [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:1216] — .surface.sheet #opt-app-passwords > .app-passwords-sheet-card → padding: 0; border-color: transparent; background: transparent; box-shadow: none;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:116] — .surface-background.sheet.rotate-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:118] — .surface.dialog.rotate-sheet → width: min(480px, calc(100vw - 32px));; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:121] — .surface-background.dialog.rotate-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:139] — .surface-background.sheet.unsplash-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:141] — .surface.dialog.unsplash-sheet → width: min(720px, calc(100vw - 32px)); max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:145] — .surface-background.dialog.unsplash-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/apps/CalendarFeedsGroup.svelte:251] — html.scrim-open body .surface-background.glass-overlay.feed-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:821] — .surface.dialog.connected-account-provider-sheet → /* OverlaySurface owns both center coordinates and the Settings pane offset. */ translate: -50% -50%; width: min(560px, calc(100vw - 32px)); max-height: min(88dvh, 820px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:837] — .surface.sheet.connected-account-provider-sheet → --sheet-chrome-height: calc(1.5rem + var(--header-reserve));; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:838] — .surface.sheet.connected-account-provider-sheet .sheet-scroll → /* header-reserve already includes the title-to-content gap. */ padding-block-start: var(--sheet-chrome-height); scroll-padding-top: var(--sheet-chrome-height);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:863] — .surface.sheet.connected-account-provider-sheet .provider-sheet → padding-top: 0;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/routes/settings/jobs/JobDetails.svelte:98] — .pill.row-action → padding-inline-start: 0;; extend Pill.
  • [apps/web/src/routes/settings/parts/RowAction.svelte:24] — .pill.row-action.danger → --pill-color: var(--now); --pill-color-hover: var(--now); --pill-bg-hover: color-mix(in srgb, var(--now) 10%, transparent);; extend Pill.
  • [apps/web/src/routes/settings/parts/RowAction.svelte:28] — .pill.row-action:disabled → opacity: 0.5; cursor: default;; extend Pill.
  • [apps/web/src/routes/settings/parts/StateChip.svelte:21] — .pill.state-chip → --pill-bg: var(--paper-2); --pill-border: transparent; --pill-color: var(--muted);; extend Pill.
  • [apps/web/src/routes/settings/parts/StateChip.svelte:25] — .pill.state-chip.accent → --pill-bg: var(--accent-soft); --pill-border: color-mix(in srgb, var(--accent) 25%, transparent); --pill-color: var(--accent);; extend Pill.
  • [apps/web/src/routes/settings/parts/StateChip.svelte:30] — .pill.state-chip.attention → --pill-bg: color-mix(in srgb, var(--now) 14%, var(--surface)); --pill-border: color-mix(in srgb, var(--now) 25%, transparent); --pill-color: color-mix(in srgb, var(--now) 78%, var(--ink));; extend Pill.

(b)

  • [apps/web/src/lib/auth/components/AuthCard.svelte:24] — Card.
  • [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:184] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:205] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:234] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoverFlow.svelte:146] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoverFlow.svelte:162] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoverFlow.svelte:173] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoveryKeyEntry.svelte:286] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:65] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:72] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/[...path]/+page.svelte:392] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/[...path]/+page.svelte:400] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/[...path]/+page.svelte:406] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/[...path]/+page.svelte:419] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:884] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:963] — Card.
  • [apps/web/src/routes/settings/account/PasskeysGroup.svelte:271] — Card.
  • [apps/web/src/routes/settings/account/SessionsGroup.svelte:104] — Card.
  • [apps/web/src/routes/settings/admin/InvitationsGroup.svelte:185] — Card.
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1044] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1058] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1099] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:907] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:929] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:942] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:955] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:988] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:120] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/calendars/CalendarsSection.svelte:401] — Card.
  • [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:614] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:172] — Card.
  • [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:184] — Card.
  • [apps/web/src/routes/settings/plugins/PluginsSection.svelte:176] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/settings/voice/VoiceSection.svelte:170] — Card.

(c)

  • [apps/web/src/lib/auth/components/AuthCard.svelte:34] — .card → width: min(420px, 100%); border: 1px solid var(--hair); padding: 26px 22px; gap: 12px; use Card and shared tokens.
  • [apps/web/src/lib/auth/components/AuthCard.svelte:46] — .card.wide → width: min(480px, 100%); use Card and shared tokens.
  • [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:87] — .btn-row → gap: 8px; use shared control primitive and shared tokens.
  • [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:91] — .btn-row .btn → min-width: 8rem; use shared control primitive and shared tokens.
  • [apps/web/src/routes/settings/admin/SignInGroup.svelte:76] — .toggle-row → gap: 16px; use Toggle and shared tokens.
  • [apps/web/src/routes/settings/admin/SignInGroup.svelte:81] — .toggle-text → gap: 2px; use Toggle and shared tokens.
  • [apps/web/src/routes/settings/apps/CalendarFeedsGroup.svelte:268] — .toggle-row → gap: 12px; min-height: 44px; use Toggle and shared tokens.
  • [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:190] — .toggle-slot → min-height: 34px; use Toggle and shared tokens.
  • [apps/web/src/routes/settings/parts/settings-forms.css:29] — :is(.settings-shell, .money-form) :where(.card-footer) → gap: 10px 8px; use Card and shared tokens.
  • [apps/web/src/routes/settings/voice/VoiceSection.svelte:242] — .toggle-slot → min-height: 34px; use Toggle and shared tokens.

Analytics (2 a, 5 b, 2 c)

(a)

  • [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:334] — .card → display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 2px;; extend Card.
  • [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:344] — .card → grid-row: auto; display: flex; flex-direction: column; min-height: calc(var(--stat-card-min-height) + 32px);; extend Card.

(b)

  • [apps/web/src/lib/components/analytics/Dashboard.svelte:86] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/analytics/RangePicker.svelte:323] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/analytics/RangePicker.svelte:335] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/analytics/RangePicker.svelte:406] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/analytics/[period]/[date]/+page.svelte:134] — Card.

(c)

  • [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:328] — .grid > :global(.card) → row-gap: 2px; use Card and shared tokens.
  • [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:342] — .grid > :global(.card) → min-height: calc(var(--stat-card-min-height) + 32px); use Card and shared tokens.

Notifications (5 a, 3 b, 0 c)

(a)

  • [apps/web/src/lib/notifications/InboxPanel.svelte:427] — .surface.panel.inbox-surface → top: var(--inbox-top, calc(env(safe-area-inset-top, 0px) + 64px)); right: var(--inbox-right, 16px); bottom: auto; width: min(400px, calc(100vw - 24px)); max-height: min(640px, calc(100dvh - var(--inbox-top, 64px) - 24px)); padding: 0; border: 1px solid var(--glass-border); border-radius: var(--radius-dialog); background: var(--cal-sheet-material); box-shadow: var(--glass-shadow);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notifications/InboxPanel.svelte:441] — .surface.sheet.inbox-surface → padding-inline: 0;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notifications/InboxPanel.svelte:443] — .surface.sheet.inbox-surface .sheet-scroll → padding-inline: 8px;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/notifications/InboxPanel.svelte:495] — .inbox-actions .pg-btn[aria-disabled='true'] → opacity: 0.4; cursor: default;; extend PillGroup.
  • [apps/web/src/lib/notifications/InboxPanel.svelte:499] — .inbox-actions .pg-btn[aria-disabled='true'] → opacity: 0.4; cursor: default;; extend PillGroup.

(b)

  • [apps/web/src/lib/notifications/InboxPanel.svelte:389] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notifications/InboxPanel.svelte:393] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/notifications/InboxPanel.svelte:399] — Pill (or PillGroup for adjacent actions).

Shared UI (16 a, 40 b, 53 c)

(a)

  • [apps/web/src/lib/ai/TurnPanel.svelte:302] — .surface.dialog.turn-panel → width: min(var(--turn-panel-width, 460px), calc(100vw - 24px)); height: min(780px, 82dvh); max-height: 82dvh; padding: 0; overflow: hidden; background: var(--surface); border: 1px solid color-mix(in srgb, var(--hair) 65%, transparent); box-shadow: 0 24px 50px -22px rgba(20, 30, 24, 0.42);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/ai/TurnPanel.svelte:311] — .surface.sheet.turn-panel → padding: 0; overflow: hidden; background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/AppToaster.svelte:533] — .cal-toaster .cal-toast .cal-toast-btn .pill-content → pointer-events: none;; extend Pill.
  • [apps/web/src/lib/components/ConfirmSheet.svelte:113] — .surface-background.sheet.confirm-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/ConfirmSheet.svelte:115] — .surface-background.dialog.confirm-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/ConfirmSheet.svelte:118] — .surface.dialog.confirm-sheet → width: min(440px, calc(100vw - 32px)); /* OverlaySurface owns the vertical centring; this confirmation also needs the matching horizontal offset at tablet and desktop widths. */ translate: -50% -50%;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/ConfirmSheet.svelte:172] — .pill.confirm-danger → --pill-bg: var(--now); --pill-bg-hover: color-mix(in srgb, var(--now) 88%, var(--ink));; extend Pill.
  • [apps/web/src/lib/components/ShortcutList.svelte:128] — .kbd-caps → grid-column: 2; grid-row: 1; align-self: center;; extend Kbd.
  • [apps/web/src/lib/components/TagEditor.svelte:191] — .surface.sheet.tag-sheet → max-height: min(80dvh, 620px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/TagEditor.svelte:193] — .surface-background.sheet.tag-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/TagEditor.svelte:196] — .surface.dialog.tag-sheet → width: min(500px, calc(100vw - 32px)); max-height: min(80dvh, 620px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/TagEditor.svelte:200] — .surface-background.dialog.tag-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/components/app-sidebar.svelte:724] — .sidebar-month-card.glass-card → background: var(--glass-card-inner-bg); border-color: var(--glass-border);; extend Card.
  • [apps/web/src/lib/composer/Composer.svelte:2386] — .surface.pill.viewport-fit.composer-window → /* The Composer is the centered member of the shared pill family. Keep its center attached to the visible area as the software keyboard moves it. */ top: calc(var(--vv-top, 0px) + var(--vv-height, 100dvh) / 2); translate: 0 -50%; max-height: calc(var(--vv-height, 100dvh) - 24px);; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/composer/Composer.svelte:2392] — .surface.pill.composer-window → overflow: hidden;; extend FloatingSurface / OverlaySurface.
  • [apps/web/src/lib/history/VersionHistory.svelte:418] — .pill svg → width: var(--icon); height: var(--icon);; extend Pill.

(b)

  • [apps/web/src/lib/components/KeyboardShortcutsCard.svelte:54] — Card.
  • [apps/web/src/lib/components/KeyboardShortcutsCard.svelte:72] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/TagEditor.svelte:135] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/TagEditor.svelte:141] — Pill or TagPill.
  • [apps/web/src/lib/components/TagEditor.svelte:143] — Pill or TagPill.
  • [apps/web/src/lib/components/app-sidebar.svelte:577] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/components/empty-state.svelte:25] — Card.
  • [apps/web/src/lib/composer/Composer.svelte:2068] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2074] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2076] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2081] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2096] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2099] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2100] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2105] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2106] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2113] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2115] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2118] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2122] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2125] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2128] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2132] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2132] — TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2136] — TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2145] — Pill or TagPill.
  • [apps/web/src/lib/composer/Composer.svelte:2248] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2254] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2264] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2267] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2273] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2280] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2281] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/composer/Composer.svelte:2320] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/lib/history/VersionHistory.svelte:345] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/+layout.svelte:1425] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/login/+page.svelte:168] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/login/+page.svelte:173] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/login/+page.svelte:191] — Pill (or PillGroup for adjacent actions).
  • [apps/web/src/routes/login/+page.svelte:200] — Pill (or PillGroup for adjacent actions).

(c)

  • [apps/web/src/lib/components/TagEditor.svelte:262] — .chip → gap: 1px; use Pill / TagPill and shared tokens.
  • [apps/web/src/lib/composer/Composer.svelte:2383] — :global(.surface.pill.viewport-fit.composer-window) → max-height: calc(var(--vv-height, 100dvh) - 24px); use Pill and shared tokens.
  • [apps/web/src/lib/composer/Composer.svelte:2492] — .chip → border: 1px solid color-mix(in srgb, var(--hair) 60%, transparent); use Pill / TagPill and shared tokens.
  • [apps/web/src/lib/composer/Composer.svelte:2584] — .chip.tag → max-width: min(15rem, 52vw); use Pill / TagPill and shared tokens.
  • [apps/web/src/lib/composer/Composer.svelte:2596] — .chip.tag.inferred → border: 1px dashed color-mix(in srgb, var(--tfg) 55%, transparent); use Pill / TagPill and shared tokens.
  • [apps/web/src/lib/styles/auth-ui.css:117] — .auth-ui :where(.btn) → padding: 12px 16px; min-height: 44px; gap: 8px; use shared control primitive and shared tokens.
  • [apps/web/src/lib/styles/auth-ui.css:137] — .auth-ui :where(.btn.primary) → color: #fff; use shared control primitive and shared tokens.
  • [packages/ui/src/components/Card.svelte:59] — .card → padding: 16px 18px; use Card and shared tokens.
  • [packages/ui/src/components/Card.svelte:65] — .card.column → gap: var(--card-gap, 4px); use Card and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:225] — .checkbox-glyph → width: 16px; height: 16px; use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:249] — .checkbox-indicator.file, .checkbox-indicator.tile → width: 22px; height: 22px; box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 35%, transparent); use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:281] — .checkbox-control.fc-check-control:active:not(:disabled) .checkbox-indicator:not(.checked):not(.mixed) → box-shadow: inset 0 0 0 1.5px var(--accent); use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:285] — .checkbox-indicator.form, .checkbox-indicator.editor → width: var(--checkbox-size, 13px); height: var(--checkbox-size, 13px); box-shadow: inset 0 0 0 1.5px var(--control-boundary); use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:295] — .checkbox-indicator.editor → width: 16px; height: 16px; use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:304] — .checkbox-control.editor:hover:not(:disabled) .checkbox-indicator:not(.checked):not(.mixed) → box-shadow: inset 0 0 0 1.5px var(--accent); use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:308] — .checkbox-indicator.photo → width: 20px; height: 20px; border: 1.5px solid color-mix(in srgb, var(--ink) 38%, transparent); use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:316] — .checkbox-indicator.photo .checkbox-glyph → width: 13px; height: 13px; use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:321] — .checkbox-indicator.menu → width: 16px; height: 16px; use Checkbox and shared tokens.
  • [packages/ui/src/components/Checkbox.svelte:330] — .checkbox-indicator.menu .checkbox-glyph → width: 16px; height: 16px; use Checkbox and shared tokens.
  • [packages/ui/src/components/OverlaySurface.svelte:1241] — .surface.pill.viewport-fit → max-height: calc(var(--vv-height, 100dvh) - 24px); use OverlaySurface and shared tokens.
  • [packages/ui/src/components/Pill.svelte:146] — .pill → border: 1px solid var(--pill-border, var(--glass-border)); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:175] — .pill.label → padding: 0 calc(var(--control-h) / 2 - 2px); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:199] — .pill.icon.btn::before → width: calc(100% + 2px + var(--pill-hit-outset) + var(--pill-hit-outset)); height: calc(100% + 2px + var(--pill-hit-outset) + var(--pill-hit-outset)); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:281] — .pill.nav → gap: var(--pill-nav-gap, 6px); padding: var(--pill-nav-padding, 0 14px 0 10px); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:299] — .pill.count → padding: 0 6px; use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:324] — .pill.count.hours, .pill.count:has(:global([torph-exiting])) → width: var(--hours-width, calc((var(--hours-chars) + 1) * 1ch + 12px)); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:329] — .pill.chip → height: 24px; min-height: 24px; gap: 3px; padding: 0 var(--pill-chip-padding, 7px); use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:364] — .pill.select → min-width: 112px; use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:385] — .pill-select-native → padding: 0 30px 0 14px; use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:406] — .pill-select-chevron → width: 16px; height: 16px; use Pill and shared tokens.
  • [packages/ui/src/components/Pill.svelte:460] — .pill :global(svg:not(.pill-select-chevron)) → width: var(--pill-glyph-size, 24px); height: var(--pill-glyph-size, 24px); use Pill and shared tokens.
  • [packages/ui/src/components/PillGroup.svelte:336] — .pill-group--reveal :global([data-pill-reveal]:focus-visible) → gap: 6px; padding-inline: 12px; use Pill and shared tokens.
  • [packages/ui/src/components/PillGroup.svelte:352] — .pill-group--reveal :global([data-pill-reveal]:hover) → gap: 6px; padding-inline: 12px; use Pill and shared tokens.
  • [packages/ui/src/components/PillGroup.svelte:457] — .pill-group--single :global(.pg-btn) → height: var(--island-hit, 38px); width: var(--island-hit, 38px); min-width: var(--island-hit, 38px); use Pill and shared tokens.
  • [packages/ui/src/components/PillGroup.svelte:469] — .pill-group :global(.pg-btn svg) → width: var(--pill-group-glyph-size, var(--pill-glyph-size, 24px)); height: var(--pill-group-glyph-size, var(--pill-glyph-size, 24px)); use Pill and shared tokens.
  • [packages/ui/src/components/TodayButton.svelte:46] — .today-button.today-button → min-width: 78px; padding-inline: 14px; use Pill and shared tokens.
  • [packages/ui/src/components/Toggle.svelte:76] — .toggle → border: 1.5px solid var(--control-boundary); use Toggle and shared tokens.
  • [packages/ui/src/components/Toggle.svelte:94] — .toggle::after → width: calc(var(--switch-h) - 7px); height: calc(var(--switch-h) - 7px); use Toggle and shared tokens.
  • [packages/ui/src/components/composer/FieldPopover.svelte:110] — .toggle → gap: 8px; use Toggle and shared tokens.
  • [packages/ui/src/components/composer/FieldPopover.svelte:136] — .btn → padding: 0 14px; use shared control primitive and shared tokens.
  • [packages/ui/src/components/composer/VoiceRecordingPill.svelte:226] — :global(.pill-group .voice-recording-pill.expanded) → width: var(--voice-pill-open-size, 12.75rem); use Pill and shared tokens.
  • [packages/ui/src/components/composer/VoiceRecordingPill.svelte:335] — .action-icon → width: 16px; height: 16px; use Pill and shared tokens.
  • [packages/ui/src/components/menu/Menu.svelte:518] — .menu-list → gap: 1px; --menu-icon-gap: 9px; use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/Menu.svelte:546] — :global([data-density='touch']) .menu-list → --menu-icon-gap: 12px; use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/Menu.svelte:556] — .menu-header → padding: 6px var(--menu-pad-x) 4px var(--menu-label-x); use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/MenuItem.svelte:157] — .menu-item → gap: var(--menu-icon-gap, 9px); height: var(--menu-row, 28px); padding: 0 var(--menu-pad-x, 10px); use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/MenuItem.svelte:180] — .menu-item.drop-target → box-shadow: inset 0 0 0 2px var(--accent); use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/MenuItem.svelte:232] — .menu-swatch → width: 14px; height: 14px; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 14%, transparent); use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/MenuSeparator.svelte:11] — .menu-separator → height: var(--menu-sep-block, 10px); use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/menu/MenuSeparator.svelte:15] — .menu-separator::before → height: 1px; use Menu / MenuItem and shared tokens.
  • [packages/ui/src/components/modeIsland.css:86] — .island-segment, .pill-group .pg-btn → gap: 6px; use PillGroup and shared tokens.
  • [packages/ui/src/components/viewer/QuickLook.svelte:363] — :global(.pill.label.ql-title-pill) → max-width: min(38rem, calc(100% - 60px)); gap: 8px; padding: 6px calc(var(--control-h) / 2 - 2px); use Pill and shared tokens.
  • [packages/ui/src/components/viewer/QuickLook.svelte:508] — :global(.pill.label.ql-title-pill) → max-width: calc(100% - 46px); use Pill and shared tokens.
Initial full inventory from `5301e020859c1d61b4a7f812a5049a64241203e8`. It groups findings by Tab and lists file, line, category, and the shared primitive or token family. The BlockHoverActions wash slab is assigned to #1189. # Restyle audit — Forgejo #1190 Inventory from 2026-10-06 in apps/web and packages. Each entry has a file and line. Category **(a)** is a local style override of a shared primitive class or an extra surface around one. Category **(b)** is app-owned button, pill, chip, menu, card, or toggle markup and names the shared control to use. Category **(c)** is a literal control size, colour, radius, or duration outside token files and names the shared primitive. ## Calendar (0 a, 1 b, 7 c) ### (b) - [apps/web/src/routes/calendar/[view]/[date]/+page.svelte:3096] — Pill (or PillGroup for adjacent actions). ### (c) - [packages/ui/src/components/calendar/ActivityStack.svelte:141] — .card → border: 1px solid color-mix(in srgb, var(--hair) 80%, transparent); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); use Card and shared tokens. - [packages/ui/src/components/calendar/AttachmentDeck.svelte:969] — :global(.attachment-actions .pg-btn) → gap: 4px; padding-inline: 8px; use PillGroup and shared tokens. - [packages/ui/src/components/calendar/TaskCheckbox.svelte:51] — :global(.task-checkbox-wrap > .checkbox-control) → width: var(--hit, 44px); height: var(--hit, 44px); use Checkbox and shared tokens. - [packages/ui/src/components/calendar/TaskCheckbox.svelte:57] — :global(.task-checkbox-wrap .checkbox-indicator.editor) → width: 16px; height: 16px; use Checkbox and shared tokens. - [packages/ui/src/components/calendar/TimeGrid.svelte:1983] — .chip → gap: 5px; height: 22px; padding: 0 7px; use Pill / TagPill and shared tokens. - [packages/ui/src/components/calendar/TimeGrid.svelte:2006] — .chip :global(svg) → width: 13px; height: 13px; use Pill / TagPill and shared tokens. - [packages/ui/src/components/calendar/YearHeatmap.svelte:197] — button.d:hover → box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--ink) 40%, transparent); use Pill and shared tokens. ## Tasks (6 a, 10 b, 3 c) ### (a) - [apps/web/src/lib/tasks/TaskCard.svelte:75] — .card.task-card → box-sizing: border-box; position: relative; display: block; width: 100%; height: auto; min-height: 0; padding: 0.55rem 0.65rem; text-shadow: none;; extend Card. - [apps/web/src/lib/tasks/TaskCard.svelte:89] — .checkbox-input-wrap → margin-block-start: 0.2rem;; extend Checkbox. - [apps/web/src/lib/tasks/TaskCard.svelte:97] — .status-pill-frame.task-status-pill .status-pill → --pill-nav-height: 1.4rem; --pill-nav-padding: 0.08rem 0.45rem; --pill-nav-font-size: var(--text-caption); min-height: 1.4rem; max-width: none;; extend StatusPill. - [apps/web/src/lib/tasks/TaskColumn.svelte:186] — .card.task-card → outline: 1px dashed var(--accent); outline-offset: -2px;; extend Card. - [apps/web/src/lib/tasks/TaskList.svelte:69] — .card.task-list-card → min-width: 0; overflow: hidden; text-shadow: none;; extend Card. - [apps/web/src/lib/tasks/TaskList.svelte:90] — .status-pill-frame.task-status-pill .status-pill → --pill-nav-height: 1.4rem; --pill-nav-padding: 0.08rem 0.45rem; --pill-nav-font-size: var(--text-caption); min-height: 1.4rem; max-width: none;; extend StatusPill. ### (b) - [apps/web/src/lib/tasks/TaskColumn.svelte:131] — Card. - [apps/web/src/lib/tasks/TaskColumn.svelte:172] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:632] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:638] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:646] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:655] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:657] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:659] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:672] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/tasks/TaskSection.svelte:679] — Pill (or PillGroup for adjacent actions). ### (c) - [apps/web/src/lib/tasks/TaskCard.svelte:74] — :global(.card.task-card) → padding: 0.55rem 0.65rem; use Card and shared tokens. - [apps/web/src/lib/tasks/TasksWorkspace.svelte:486] — .view-add button → min-height: 2.65rem; border: 1px solid var(--hair); padding: 0 1rem; use Pill and shared tokens. - [apps/web/src/lib/tasks/TasksWorkspace.svelte:489] — .tasks-state button → min-height: 2.5rem; border: 1px solid var(--hair); padding: 0 0.8rem; use Pill and shared tokens. ## Notes (8 a, 27 b, 11 c) ### (a) - [apps/web/src/lib/editor/format/BlockHoverActions.svelte:250] — extra ProgressiveBlur wash slab behind PillGroup; remove the slab and keep the shared capsule material (#1189). - [apps/web/src/lib/notes/NoteContents.svelte:364] — .surface.note-contents-sheet .sheet-scroll → overscroll-behavior: contain;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notes/NoteContents.svelte:370] — .surface.note-contents-sheet .sheet-chrome → background: transparent;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notes/NoteContents.svelte:372] — .surface.note-contents-sheet .sheet-title-row → grid-template-columns: minmax(0, 1fr); justify-items: center;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notes/NoteContents.svelte:376] — .surface.note-contents-sheet .sheet-leading → grid-column: 1; justify-self: center;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notes/NoteContents.svelte:383] — .surface.note-contents-sheet .sheet-title → position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notes/NoteView.svelte:2566] — .card.glass-card → box-shadow: none;; extend Card. - [apps/web/src/lib/notes/NoteView.svelte:2674] — .note-stack .note-card.card.note-card--segmented → background: transparent; border-color: transparent; box-shadow: none;; extend Card. ### (b) - [apps/web/src/lib/canvas/CanvasItemCard.svelte:56] — Card. - [apps/web/src/lib/canvas/CanvasItemCard.svelte:57] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/canvas/CanvasItemCard.svelte:69] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/canvas/CanvasItemCard.svelte:70] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/canvas/CanvasItemCard.svelte:72] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/canvas/CanvasPreview.svelte:92] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/BlockHoverActions.svelte:260] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:284] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:302] — Pill or TagPill. - [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:308] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:315] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/BlockReminderPicker.svelte:321] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/editor/format/FormatButton.svelte:64] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notes/NoteContents.svelte:166] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notes/NoteContents.svelte:211] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notes/NoteImageView.svelte:121] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notes/NoteView.svelte:2211] — Card. - [apps/web/src/lib/notes/NoteView.svelte:2216] — Card. - [apps/web/src/lib/notes/NoteView.svelte:2223] — Card. - [apps/web/src/lib/notes/NoteView.svelte:2226] — Card. - [apps/web/src/lib/notes/NoteView.svelte:2234] — Card. - [apps/web/src/lib/notes/NotesExplorer.svelte:463] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notes/NotesExplorer.svelte:507] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/journal/+page.svelte:78] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/notes/+page.svelte:175] — Pill (or PillGroup for adjacent actions). - [packages/editor/src/components/CalloutView.svelte:27] — Pill (or PillGroup for adjacent actions). - [packages/editor/src/components/TaskItemView.svelte:66] — Checkbox. ### (c) - [apps/web/src/lib/canvas/CanvasView.svelte:486] — .canvas-elements-row :global(button) → min-height:44px; use Pill and shared tokens. - [apps/web/src/lib/canvas/DrawingBlock.svelte:469] — :global(.drawing-block .App-toolbar--mobile button), :global(.drawing-block .App-toolbar--mobile .ToolIcon) → min-width: 44px; min-height: 44px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:124] — .format-button.wide → gap: 7px; padding-inline: 8px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:151] — .format-button → width: 28px; min-width: 28px; height: 28px; min-height: 28px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:157] — .format-button.wide → height: 28px; min-height: 28px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:161] — .format-button → width: 44px; min-width: 44px; height: 44px; min-height: 44px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:169] — .format-button.wide → min-width: 44px; min-height: 44px; padding-inline: 10px; use Pill and shared tokens. - [apps/web/src/lib/editor/format/FormatButton.svelte:97] — .format-button → width: 28px; min-width: 28px; height: 28px; min-height: 28px; use Pill and shared tokens. - [apps/web/src/lib/notes/NoteView.svelte:2937] — .note-state-actions a, .note-state-actions button → min-height: 40px; padding: 0 16px; use Pill and shared tokens. - [packages/ui/src/components/notes/NoteMentionsCard.svelte:320] — :global(.mention-count.pill.count) → width: 24px; min-width: 24px; height: 24px; min-height: 24px; padding: 0 3px; use Card and shared tokens. - [packages/ui/src/components/notes/NoteProperties.svelte:294] — :global(.properties-count.pill.count) → width: 20px; min-width: 20px; height: 20px; min-height: 20px; padding: 0 3px; use Pill and shared tokens. ## Files (6 a, 58 b, 1 c) ### (a) - [apps/web/src/lib/files/FilesBrowser.svelte:1826] — .surface.dialog.paste-upload-conflict → width: min(460px, calc(100vw - 32px)); translate: -50% -50%;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/files/ShareDialog.svelte:493] — .surface.sheet.share-sheet → max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/files/ShareDialog.svelte:495] — .surface.dialog.share-sheet → width: min(580px, calc(100vw - 32px)); max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/files/ShareDialog.svelte:641] — .pg-btn → display: grid; width: var(--control-h); height: var(--control-h); place-items: center; border: 0; border-radius: var(--radius-circle); background: transparent; color: var(--ink-muted); cursor: pointer; --pill-group-glyph-size: var(--icon);; extend PillGroup. - [apps/web/src/lib/files/ShareDialog.svelte:653] — .pg-btn:hover → background: color-mix(in srgb, var(--ink) 7%, transparent); color: var(--ink);; extend PillGroup. - [apps/web/src/lib/files/SharedByYou.svelte:165] — .pg-btn → display: grid; width: var(--control-h); height: var(--control-h); place-items: center; border: 0; border-radius: var(--radius-circle); background: transparent; color: var(--ink-muted); cursor: pointer; --pill-group-glyph-size: var(--icon);; extend PillGroup. ### (b) - [apps/web/src/lib/files/FilesBrowser.svelte:1620] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1621] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1628] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1633] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1645] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1646] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesBrowser.svelte:1700] — Card. - [apps/web/src/lib/files/FilesBrowser.svelte:1762] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesSidebar.svelte:196] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesSidebar.svelte:216] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesSidebar.svelte:217] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/FilesSidebar.svelte:218] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:613] — Card. - [apps/web/src/lib/files/InfoPanel.svelte:664] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:665] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:671] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:679] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:688] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:722] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:728] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:758] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:825] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/InfoPanel.svelte:840] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:467] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:473] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:476] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:481] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:483] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:512] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:514] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:521] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:523] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:529] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:532] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:540] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:553] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:580] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:585] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:593] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:600] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:603] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:609] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:620] — Card. - [apps/web/src/lib/files/PublicLinkPage.svelte:628] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/PublicLinkPage.svelte:635] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/ShareDialog.svelte:323] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/ShareDialog.svelte:341] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/ShareDialog.svelte:374] — Pill. - [apps/web/src/lib/files/ShareDialog.svelte:391] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/ShareDialog.svelte:392] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/SharedByYou.svelte:86] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:130] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:136] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:146] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:163] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:165] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:167] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/files/UploadToast.svelte:170] — Pill (or PillGroup for adjacent actions). ### (c) - [apps/web/src/lib/files/ShareDialog.svelte:746] — .pill-icon-label → gap: 6px; use Pill and shared tokens. ## Photos (0 a, 7 b, 1 c) ### (b) - [apps/web/src/lib/photos/PhotoViewer.svelte:372] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/photos/PhotoViewer.svelte:387] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/photos/PhotosView.svelte:857] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/photos/PhotosView.svelte:894] — Card. - [apps/web/src/lib/photos/PhotosView.svelte:913] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/photos/PhotosView.svelte:926] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/photos/PhotosView.svelte:928] — Pill (or PillGroup for adjacent actions). ### (c) - [apps/web/src/lib/photos/BackgroundsFolderView.svelte:167] — .empty button → padding: 0 14px; use Pill and shared tokens. ## Mail (2 a, 8 b, 0 c) ### (a) - [apps/web/src/lib/mail/MailView.svelte:1534] — .pill → grid-area: action;; extend Pill. - [apps/web/src/lib/mail/MailView.svelte:1539] — .pill → justify-self: start;; extend Pill. ### (b) - [apps/web/src/lib/mail/MailMorphCard.svelte:61] — Card. - [apps/web/src/lib/mail/MailView.svelte:1389] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1411] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1421] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1442] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1456] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1477] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/mail/MailView.svelte:1478] — Pill (or PillGroup for adjacent actions). ## Money (0 a, 7 b, 0 c) ### (b) - [apps/web/src/routes/money/[budget]/[month]/+page.svelte:278] — Card. - [apps/web/src/routes/money/[budget]/[month]/+page.svelte:301] — Card. - [apps/web/src/routes/money/[budget]/[month]/+page.svelte:364] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte:328] — Card. - [apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte:334] — Card. - [apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte:385] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte:410] — Pill (or PillGroup for adjacent actions). ## Search (9 a, 20 b, 14 c) ### (a) - [apps/web/src/lib/components/search-dialog.svelte:1145] — .surface.pill.search-window → display: flex; flex-direction: column; width: var(--palette-width); /* The top stays at --palette-top; the bottom stops at two-thirds height. */ max-height: max(0px, min(calc(66.666dvh - var(--palette-top)), 44rem)); transition: height var(--dur-morph) var(--ease-spring), width var(--dur-search) var(--ease-out), max-height var(--dur-search) var(--ease-out);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/search-dialog.svelte:1158] — .surface.pill.search-window.has-preview → width: var(--palette-width-preview);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/search-dialog.svelte:1163] — .surface.pill.search-window.is-expanded → top: max(24px, 4dvh); width: min(76rem, calc(100vw - 32px)); height: min(92dvh, 64rem); max-height: min(92dvh, 64rem);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/search-dialog.svelte:1175] — :root .surface.pill.search-window.is-expanded → --search-band: calc(var(--search-vv-height, 100dvh) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 16px); width: calc(100vw - 16px); max-height: var(--search-band);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/search-dialog.svelte:1183] — :root .surface.pill.search-window.is-expanded → top: calc(var(--search-vv-top, 0px) + var(--search-vv-height, 100dvh) / 2); translate: 0 -50%; height: auto;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/search-dialog.svelte:1199] — .surface.pill.search-window → transition: none;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/search/SearchPreview.svelte:1061] — .actions > .pill-group → min-width: 0; max-width: 100%; flex-wrap: wrap;; extend PillGroup. - [apps/web/src/lib/search/SearchPreview.svelte:1066] — .actions > .pill-group:last-child → margin-left: 0;; extend PillGroup. - [apps/web/src/lib/search/SearchResultRow.svelte:261] — .item-card → gap: var(--search-result-icon-gap);; extend ItemCard. ### (b) - [apps/web/src/lib/components/search-dialog.svelte:868] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:869] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:878] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:899] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:909] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:919] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:928] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/search-dialog.svelte:939] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/search/SavedSearchList.svelte:184] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/search/SearchField.svelte:281] — Pill or TagPill. - [apps/web/src/lib/search/SearchField.svelte:282] — Pill or TagPill. - [apps/web/src/lib/search/SearchField.svelte:287] — Pill or TagPill. - [apps/web/src/lib/search/SearchField.svelte:293] — Pill. - [apps/web/src/lib/search/SearchField.svelte:300] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/search/SearchField.svelte:313] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/search/SearchPreview.svelte:683] — Card. - [apps/web/src/lib/search/SearchPreview.svelte:770] — Pill. - [apps/web/src/lib/search/SearchPreview.svelte:795] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/search/SearchPreview.svelte:799] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/tag/[tag]/+page.svelte:205] — Pill (or PillGroup for adjacent actions). ### (c) - [apps/web/src/lib/components/search-dialog.svelte:1141] — :global(.surface.pill.search-window) → max-height: max(0px, min(calc(66.666dvh - var(--palette-top)), 44rem)); use Pill and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1163] — :global(.surface.pill.search-window.is-expanded) → width: min(76rem, calc(100vw - 32px)); height: min(92dvh, 64rem); max-height: min(92dvh, 64rem); use Pill and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1173] — :global(:root .surface.pill.search-window), :global(:root .surface.pill.search-window.is-expanded) → width: calc(100vw - 16px); use Pill and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1192] — :global(:root .surface.pill.search-window.is-expanded) .sw → max-height: calc(var(--search-band) - 2px); use Pill and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1220] — :global(.surface.pill.search-window) .sw → --search-edge-blur-height: 2rem; use Pill and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1284] — .expanded .results-list :global(.row:not(.card)) → height: 58px; use Card and shared tokens. - [apps/web/src/lib/components/search-dialog.svelte:1305] — :global(.surface.pill.search-window.preview-resized) .preview-pane → width: var(--palette-preview-width, var(--search-preview-width, 300px)); use Pill and shared tokens. - [apps/web/src/lib/search/SearchField.svelte:496] — .q-pill button, .scope-chip button → width: 20px; height: 20px; use Pill and shared tokens. - [apps/web/src/lib/search/SearchField.svelte:524] — .q-pill button :global(svg), .scope-chip button :global(svg) → width: 12px; height: 12px; use Pill and shared tokens. - [apps/web/src/lib/search/SearchField.svelte:532] — .q-pill button, .scope-chip button → width: 44px; height: 44px; use Pill and shared tokens. - [apps/web/src/lib/search/SearchField.svelte:547] — .action-trailing → gap: 6px; use shared control primitive and shared tokens. - [apps/web/src/lib/search/SearchPreview.svelte:1118] — .action → width: 34px; height: 34px; border: 1px solid var(--control-boundary); use shared control primitive and shared tokens. - [apps/web/src/lib/search/SearchResultRow.svelte:339] — .row.card → min-height: 52px; padding: 11px 14px 11px calc(var(--search-column-inset, 18px) - var(--search-row-inset, 6px) - 1px); use Card and shared tokens. - [apps/web/src/lib/search/SearchResultRow.svelte:351] — .row.card .line1 → row-gap: 1px; use Card and shared tokens. ## Settings (18 a, 34 b, 10 c) ### (a) - [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:1216] — .surface.sheet #opt-app-passwords > .app-passwords-sheet-card → padding: 0; border-color: transparent; background: transparent; box-shadow: none;; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:116] — .surface-background.sheet.rotate-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:118] — .surface.dialog.rotate-sheet → width: min(480px, calc(100vw - 32px));; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/account/RecoveryKeySheet.svelte:121] — .surface-background.dialog.rotate-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:139] — .surface-background.sheet.unsplash-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:141] — .surface.dialog.unsplash-sheet → width: min(720px, calc(100vw - 32px)); max-height: min(88dvh, 860px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:145] — .surface-background.dialog.unsplash-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/apps/CalendarFeedsGroup.svelte:251] — html.scrim-open body .surface-background.glass-overlay.feed-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:821] — .surface.dialog.connected-account-provider-sheet → /* OverlaySurface owns both center coordinates and the Settings pane offset. */ translate: -50% -50%; width: min(560px, calc(100vw - 32px)); max-height: min(88dvh, 820px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:837] — .surface.sheet.connected-account-provider-sheet → --sheet-chrome-height: calc(1.5rem + var(--header-reserve));; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:838] — .surface.sheet.connected-account-provider-sheet .sheet-scroll → /* header-reserve already includes the title-to-content gap. */ padding-block-start: var(--sheet-chrome-height); scroll-padding-top: var(--sheet-chrome-height);; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:863] — .surface.sheet.connected-account-provider-sheet .provider-sheet → padding-top: 0;; extend FloatingSurface / OverlaySurface. - [apps/web/src/routes/settings/jobs/JobDetails.svelte:98] — .pill.row-action → padding-inline-start: 0;; extend Pill. - [apps/web/src/routes/settings/parts/RowAction.svelte:24] — .pill.row-action.danger → --pill-color: var(--now); --pill-color-hover: var(--now); --pill-bg-hover: color-mix(in srgb, var(--now) 10%, transparent);; extend Pill. - [apps/web/src/routes/settings/parts/RowAction.svelte:28] — .pill.row-action:disabled → opacity: 0.5; cursor: default;; extend Pill. - [apps/web/src/routes/settings/parts/StateChip.svelte:21] — .pill.state-chip → --pill-bg: var(--paper-2); --pill-border: transparent; --pill-color: var(--muted);; extend Pill. - [apps/web/src/routes/settings/parts/StateChip.svelte:25] — .pill.state-chip.accent → --pill-bg: var(--accent-soft); --pill-border: color-mix(in srgb, var(--accent) 25%, transparent); --pill-color: var(--accent);; extend Pill. - [apps/web/src/routes/settings/parts/StateChip.svelte:30] — .pill.state-chip.attention → --pill-bg: color-mix(in srgb, var(--now) 14%, var(--surface)); --pill-border: color-mix(in srgb, var(--now) 25%, transparent); --pill-color: color-mix(in srgb, var(--now) 78%, var(--ink));; extend Pill. ### (b) - [apps/web/src/lib/auth/components/AuthCard.svelte:24] — Card. - [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:184] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:205] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/CreateAccountFlow.svelte:234] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoverFlow.svelte:146] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoverFlow.svelte:162] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoverFlow.svelte:173] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoveryKeyEntry.svelte:286] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:65] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:72] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/[...path]/+page.svelte:392] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/[...path]/+page.svelte:400] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/[...path]/+page.svelte:406] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/[...path]/+page.svelte:419] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:884] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:963] — Card. - [apps/web/src/routes/settings/account/PasskeysGroup.svelte:271] — Card. - [apps/web/src/routes/settings/account/SessionsGroup.svelte:104] — Card. - [apps/web/src/routes/settings/admin/InvitationsGroup.svelte:185] — Card. - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1044] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1058] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:1099] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:907] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:929] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:942] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:955] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/BackgroundGroup.svelte:988] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/appearance/UnsplashSheet.svelte:120] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/calendars/CalendarsSection.svelte:401] — Card. - [apps/web/src/routes/settings/connected-accounts/ConnectedAccountsSection.svelte:614] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:172] — Card. - [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:184] — Card. - [apps/web/src/routes/settings/plugins/PluginsSection.svelte:176] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/settings/voice/VoiceSection.svelte:170] — Card. ### (c) - [apps/web/src/lib/auth/components/AuthCard.svelte:34] — .card → width: min(420px, 100%); border: 1px solid var(--hair); padding: 26px 22px; gap: 12px; use Card and shared tokens. - [apps/web/src/lib/auth/components/AuthCard.svelte:46] — .card.wide → width: min(480px, 100%); use Card and shared tokens. - [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:87] — .btn-row → gap: 8px; use shared control primitive and shared tokens. - [apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:91] — .btn-row .btn → min-width: 8rem; use shared control primitive and shared tokens. - [apps/web/src/routes/settings/admin/SignInGroup.svelte:76] — .toggle-row → gap: 16px; use Toggle and shared tokens. - [apps/web/src/routes/settings/admin/SignInGroup.svelte:81] — .toggle-text → gap: 2px; use Toggle and shared tokens. - [apps/web/src/routes/settings/apps/CalendarFeedsGroup.svelte:268] — .toggle-row → gap: 12px; min-height: 44px; use Toggle and shared tokens. - [apps/web/src/routes/settings/notifications/NotificationsSection.svelte:190] — .toggle-slot → min-height: 34px; use Toggle and shared tokens. - [apps/web/src/routes/settings/parts/settings-forms.css:29] — :is(.settings-shell, .money-form) :where(.card-footer) → gap: 10px 8px; use Card and shared tokens. - [apps/web/src/routes/settings/voice/VoiceSection.svelte:242] — .toggle-slot → min-height: 34px; use Toggle and shared tokens. ## Analytics (2 a, 5 b, 2 c) ### (a) - [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:334] — .card → display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 2px;; extend Card. - [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:344] — .card → grid-row: auto; display: flex; flex-direction: column; min-height: calc(var(--stat-card-min-height) + 32px);; extend Card. ### (b) - [apps/web/src/lib/components/analytics/Dashboard.svelte:86] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/analytics/RangePicker.svelte:323] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/analytics/RangePicker.svelte:335] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/analytics/RangePicker.svelte:406] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/analytics/[period]/[date]/+page.svelte:134] — Card. ### (c) - [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:328] — .grid > :global(.card) → row-gap: 2px; use Card and shared tokens. - [apps/web/src/lib/components/analytics/widgets/StatRow.svelte:342] — .grid > :global(.card) → min-height: calc(var(--stat-card-min-height) + 32px); use Card and shared tokens. ## Notifications (5 a, 3 b, 0 c) ### (a) - [apps/web/src/lib/notifications/InboxPanel.svelte:427] — .surface.panel.inbox-surface → top: var(--inbox-top, calc(env(safe-area-inset-top, 0px) + 64px)); right: var(--inbox-right, 16px); bottom: auto; width: min(400px, calc(100vw - 24px)); max-height: min(640px, calc(100dvh - var(--inbox-top, 64px) - 24px)); padding: 0; border: 1px solid var(--glass-border); border-radius: var(--radius-dialog); background: var(--cal-sheet-material); box-shadow: var(--glass-shadow);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notifications/InboxPanel.svelte:441] — .surface.sheet.inbox-surface → padding-inline: 0;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notifications/InboxPanel.svelte:443] — .surface.sheet.inbox-surface .sheet-scroll → padding-inline: 8px;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/notifications/InboxPanel.svelte:495] — .inbox-actions .pg-btn[aria-disabled='true'] → opacity: 0.4; cursor: default;; extend PillGroup. - [apps/web/src/lib/notifications/InboxPanel.svelte:499] — .inbox-actions .pg-btn[aria-disabled='true'] → opacity: 0.4; cursor: default;; extend PillGroup. ### (b) - [apps/web/src/lib/notifications/InboxPanel.svelte:389] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notifications/InboxPanel.svelte:393] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/notifications/InboxPanel.svelte:399] — Pill (or PillGroup for adjacent actions). ## Shared UI (16 a, 40 b, 53 c) ### (a) - [apps/web/src/lib/ai/TurnPanel.svelte:302] — .surface.dialog.turn-panel → width: min(var(--turn-panel-width, 460px), calc(100vw - 24px)); height: min(780px, 82dvh); max-height: 82dvh; padding: 0; overflow: hidden; background: var(--surface); border: 1px solid color-mix(in srgb, var(--hair) 65%, transparent); box-shadow: 0 24px 50px -22px rgba(20, 30, 24, 0.42);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/ai/TurnPanel.svelte:311] — .surface.sheet.turn-panel → padding: 0; overflow: hidden; background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/AppToaster.svelte:533] — .cal-toaster .cal-toast .cal-toast-btn .pill-content → pointer-events: none;; extend Pill. - [apps/web/src/lib/components/ConfirmSheet.svelte:113] — .surface-background.sheet.confirm-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/ConfirmSheet.svelte:115] — .surface-background.dialog.confirm-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/ConfirmSheet.svelte:118] — .surface.dialog.confirm-sheet → width: min(440px, calc(100vw - 32px)); /* OverlaySurface owns the vertical centring; this confirmation also needs the matching horizontal offset at tablet and desktop widths. */ translate: -50% -50%;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/ConfirmSheet.svelte:172] — .pill.confirm-danger → --pill-bg: var(--now); --pill-bg-hover: color-mix(in srgb, var(--now) 88%, var(--ink));; extend Pill. - [apps/web/src/lib/components/ShortcutList.svelte:128] — .kbd-caps → grid-column: 2; grid-row: 1; align-self: center;; extend Kbd. - [apps/web/src/lib/components/TagEditor.svelte:191] — .surface.sheet.tag-sheet → max-height: min(80dvh, 620px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/TagEditor.svelte:193] — .surface-background.sheet.tag-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/TagEditor.svelte:196] — .surface.dialog.tag-sheet → width: min(500px, calc(100vw - 32px)); max-height: min(80dvh, 620px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/TagEditor.svelte:200] — .surface-background.dialog.tag-sheet → background: var(--surface);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/components/app-sidebar.svelte:724] — .sidebar-month-card.glass-card → background: var(--glass-card-inner-bg); border-color: var(--glass-border);; extend Card. - [apps/web/src/lib/composer/Composer.svelte:2386] — .surface.pill.viewport-fit.composer-window → /* The Composer is the centered member of the shared pill family. Keep its center attached to the visible area as the software keyboard moves it. */ top: calc(var(--vv-top, 0px) + var(--vv-height, 100dvh) / 2); translate: 0 -50%; max-height: calc(var(--vv-height, 100dvh) - 24px);; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/composer/Composer.svelte:2392] — .surface.pill.composer-window → overflow: hidden;; extend FloatingSurface / OverlaySurface. - [apps/web/src/lib/history/VersionHistory.svelte:418] — .pill svg → width: var(--icon); height: var(--icon);; extend Pill. ### (b) - [apps/web/src/lib/components/KeyboardShortcutsCard.svelte:54] — Card. - [apps/web/src/lib/components/KeyboardShortcutsCard.svelte:72] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/TagEditor.svelte:135] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/TagEditor.svelte:141] — Pill or TagPill. - [apps/web/src/lib/components/TagEditor.svelte:143] — Pill or TagPill. - [apps/web/src/lib/components/app-sidebar.svelte:577] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/components/empty-state.svelte:25] — Card. - [apps/web/src/lib/composer/Composer.svelte:2068] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2074] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2076] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2081] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2096] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2099] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2100] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2105] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2106] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2113] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2115] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2118] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2122] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2125] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2128] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2132] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2132] — TagPill. - [apps/web/src/lib/composer/Composer.svelte:2136] — TagPill. - [apps/web/src/lib/composer/Composer.svelte:2145] — Pill or TagPill. - [apps/web/src/lib/composer/Composer.svelte:2248] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2254] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2264] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2267] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2273] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2280] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2281] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/composer/Composer.svelte:2320] — Pill (or PillGroup for adjacent actions). - [apps/web/src/lib/history/VersionHistory.svelte:345] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/+layout.svelte:1425] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/login/+page.svelte:168] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/login/+page.svelte:173] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/login/+page.svelte:191] — Pill (or PillGroup for adjacent actions). - [apps/web/src/routes/login/+page.svelte:200] — Pill (or PillGroup for adjacent actions). ### (c) - [apps/web/src/lib/components/TagEditor.svelte:262] — .chip → gap: 1px; use Pill / TagPill and shared tokens. - [apps/web/src/lib/composer/Composer.svelte:2383] — :global(.surface.pill.viewport-fit.composer-window) → max-height: calc(var(--vv-height, 100dvh) - 24px); use Pill and shared tokens. - [apps/web/src/lib/composer/Composer.svelte:2492] — .chip → border: 1px solid color-mix(in srgb, var(--hair) 60%, transparent); use Pill / TagPill and shared tokens. - [apps/web/src/lib/composer/Composer.svelte:2584] — .chip.tag → max-width: min(15rem, 52vw); use Pill / TagPill and shared tokens. - [apps/web/src/lib/composer/Composer.svelte:2596] — .chip.tag.inferred → border: 1px dashed color-mix(in srgb, var(--tfg) 55%, transparent); use Pill / TagPill and shared tokens. - [apps/web/src/lib/styles/auth-ui.css:117] — .auth-ui :where(.btn) → padding: 12px 16px; min-height: 44px; gap: 8px; use shared control primitive and shared tokens. - [apps/web/src/lib/styles/auth-ui.css:137] — .auth-ui :where(.btn.primary) → color: #fff; use shared control primitive and shared tokens. - [packages/ui/src/components/Card.svelte:59] — .card → padding: 16px 18px; use Card and shared tokens. - [packages/ui/src/components/Card.svelte:65] — .card.column → gap: var(--card-gap, 4px); use Card and shared tokens. - [packages/ui/src/components/Checkbox.svelte:225] — .checkbox-glyph → width: 16px; height: 16px; use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:249] — .checkbox-indicator.file, .checkbox-indicator.tile → width: 22px; height: 22px; box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 35%, transparent); use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:281] — .checkbox-control.fc-check-control:active:not(:disabled) .checkbox-indicator:not(.checked):not(.mixed) → box-shadow: inset 0 0 0 1.5px var(--accent); use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:285] — .checkbox-indicator.form, .checkbox-indicator.editor → width: var(--checkbox-size, 13px); height: var(--checkbox-size, 13px); box-shadow: inset 0 0 0 1.5px var(--control-boundary); use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:295] — .checkbox-indicator.editor → width: 16px; height: 16px; use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:304] — .checkbox-control.editor:hover:not(:disabled) .checkbox-indicator:not(.checked):not(.mixed) → box-shadow: inset 0 0 0 1.5px var(--accent); use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:308] — .checkbox-indicator.photo → width: 20px; height: 20px; border: 1.5px solid color-mix(in srgb, var(--ink) 38%, transparent); use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:316] — .checkbox-indicator.photo .checkbox-glyph → width: 13px; height: 13px; use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:321] — .checkbox-indicator.menu → width: 16px; height: 16px; use Checkbox and shared tokens. - [packages/ui/src/components/Checkbox.svelte:330] — .checkbox-indicator.menu .checkbox-glyph → width: 16px; height: 16px; use Checkbox and shared tokens. - [packages/ui/src/components/OverlaySurface.svelte:1241] — .surface.pill.viewport-fit → max-height: calc(var(--vv-height, 100dvh) - 24px); use OverlaySurface and shared tokens. - [packages/ui/src/components/Pill.svelte:146] — .pill → border: 1px solid var(--pill-border, var(--glass-border)); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:175] — .pill.label → padding: 0 calc(var(--control-h) / 2 - 2px); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:199] — .pill.icon.btn::before → width: calc(100% + 2px + var(--pill-hit-outset) + var(--pill-hit-outset)); height: calc(100% + 2px + var(--pill-hit-outset) + var(--pill-hit-outset)); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:281] — .pill.nav → gap: var(--pill-nav-gap, 6px); padding: var(--pill-nav-padding, 0 14px 0 10px); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:299] — .pill.count → padding: 0 6px; use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:324] — .pill.count.hours, .pill.count:has(:global([torph-exiting])) → width: var(--hours-width, calc((var(--hours-chars) + 1) * 1ch + 12px)); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:329] — .pill.chip → height: 24px; min-height: 24px; gap: 3px; padding: 0 var(--pill-chip-padding, 7px); use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:364] — .pill.select → min-width: 112px; use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:385] — .pill-select-native → padding: 0 30px 0 14px; use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:406] — .pill-select-chevron → width: 16px; height: 16px; use Pill and shared tokens. - [packages/ui/src/components/Pill.svelte:460] — .pill :global(svg:not(.pill-select-chevron)) → width: var(--pill-glyph-size, 24px); height: var(--pill-glyph-size, 24px); use Pill and shared tokens. - [packages/ui/src/components/PillGroup.svelte:336] — .pill-group--reveal :global([data-pill-reveal]:focus-visible) → gap: 6px; padding-inline: 12px; use Pill and shared tokens. - [packages/ui/src/components/PillGroup.svelte:352] — .pill-group--reveal :global([data-pill-reveal]:hover) → gap: 6px; padding-inline: 12px; use Pill and shared tokens. - [packages/ui/src/components/PillGroup.svelte:457] — .pill-group--single :global(.pg-btn) → height: var(--island-hit, 38px); width: var(--island-hit, 38px); min-width: var(--island-hit, 38px); use Pill and shared tokens. - [packages/ui/src/components/PillGroup.svelte:469] — .pill-group :global(.pg-btn svg) → width: var(--pill-group-glyph-size, var(--pill-glyph-size, 24px)); height: var(--pill-group-glyph-size, var(--pill-glyph-size, 24px)); use Pill and shared tokens. - [packages/ui/src/components/TodayButton.svelte:46] — .today-button.today-button → min-width: 78px; padding-inline: 14px; use Pill and shared tokens. - [packages/ui/src/components/Toggle.svelte:76] — .toggle → border: 1.5px solid var(--control-boundary); use Toggle and shared tokens. - [packages/ui/src/components/Toggle.svelte:94] — .toggle::after → width: calc(var(--switch-h) - 7px); height: calc(var(--switch-h) - 7px); use Toggle and shared tokens. - [packages/ui/src/components/composer/FieldPopover.svelte:110] — .toggle → gap: 8px; use Toggle and shared tokens. - [packages/ui/src/components/composer/FieldPopover.svelte:136] — .btn → padding: 0 14px; use shared control primitive and shared tokens. - [packages/ui/src/components/composer/VoiceRecordingPill.svelte:226] — :global(.pill-group .voice-recording-pill.expanded) → width: var(--voice-pill-open-size, 12.75rem); use Pill and shared tokens. - [packages/ui/src/components/composer/VoiceRecordingPill.svelte:335] — .action-icon → width: 16px; height: 16px; use Pill and shared tokens. - [packages/ui/src/components/menu/Menu.svelte:518] — .menu-list → gap: 1px; --menu-icon-gap: 9px; use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/Menu.svelte:546] — :global([data-density='touch']) .menu-list → --menu-icon-gap: 12px; use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/Menu.svelte:556] — .menu-header → padding: 6px var(--menu-pad-x) 4px var(--menu-label-x); use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/MenuItem.svelte:157] — .menu-item → gap: var(--menu-icon-gap, 9px); height: var(--menu-row, 28px); padding: 0 var(--menu-pad-x, 10px); use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/MenuItem.svelte:180] — .menu-item.drop-target → box-shadow: inset 0 0 0 2px var(--accent); use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/MenuItem.svelte:232] — .menu-swatch → width: 14px; height: 14px; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 14%, transparent); use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/MenuSeparator.svelte:11] — .menu-separator → height: var(--menu-sep-block, 10px); use Menu / MenuItem and shared tokens. - [packages/ui/src/components/menu/MenuSeparator.svelte:15] — .menu-separator::before → height: 1px; use Menu / MenuItem and shared tokens. - [packages/ui/src/components/modeIsland.css:86] — .island-segment, .pill-group .pg-btn → gap: 6px; use PillGroup and shared tokens. - [packages/ui/src/components/viewer/QuickLook.svelte:363] — :global(.pill.label.ql-title-pill) → max-width: min(38rem, calc(100% - 60px)); gap: 8px; padding: 6px calc(var(--control-h) / 2 - 2px); use Pill and shared tokens. - [packages/ui/src/components/viewer/QuickLook.svelte:508] — :global(.pill.label.ql-title-pill) → max-width: calc(100% - 46px); use Pill and shared tokens.
Author
Owner

Tasks audit finding fixed at d15075e81: TaskCard and TaskList styled shared Card/StatusPill internals through :global selectors, and TaskColumn hand-drew Add task. Card now owns compact padding, clipping, and DnD outline; StatusPill owns compact sizing; Pill owns the muted Add task control. Focused primitive and Tasks component tests passed. Exact #1058 hashes were refreshed for changed Task list sites; the ratchet did not change.

Tasks audit finding fixed at d15075e81: TaskCard and TaskList styled shared Card/StatusPill internals through :global selectors, and TaskColumn hand-drew Add task. Card now owns compact padding, clipping, and DnD outline; StatusPill owns compact sizing; Pill owns the muted Add task control. Focused primitive and Tasks component tests passed. Exact #1058 hashes were refreshed for changed Task list sites; the ratchet did not change.
Author
Owner

Tasks workspace finding fixed at cf1775319: List/Matrix Add task and the Task index Retry action used local button CSS. Both now use the shared muted Pill; the parent keeps only layout. TaskBoard/TaskList tests passed (7 tests), and the design-rule test passed against origin/dev.

Tasks workspace finding fixed at cf1775319: List/Matrix Add task and the Task index Retry action used local button CSS. Both now use the shared muted Pill; the parent keeps only layout. TaskBoard/TaskList tests passed (7 tests), and the design-rule test passed against origin/dev.
Author
Owner

Finding: Task Inspector values and Task card overflow counts had local button/chip treatments instead of shared primitives. Replaced Inspector value buttons with Pill shape="text" and shared semantic tones, and replaced the +N count span with Pill shape="chip" tone="inset". Extended Pill with these shared variants, tests, and docs; local value paint and chip CSS are removed.

Evidence: bun run check passed (performance/token/type checks and Svelte check); focused Pill, Card, StatusPill, TaskBoard and TaskList tests passed: 5 files, 16 tests. node scripts/design-rules.test.mjs passed.

Commit: b95e6c04a6.

Finding: Task Inspector values and Task card overflow counts had local button/chip treatments instead of shared primitives. Replaced Inspector value buttons with `Pill shape="text"` and shared semantic tones, and replaced the `+N` count span with `Pill shape="chip" tone="inset"`. Extended Pill with these shared variants, tests, and docs; local value paint and chip CSS are removed. Evidence: `bun run check` passed (performance/token/type checks and Svelte check); focused Pill, Card, StatusPill, TaskBoard and TaskList tests passed: 5 files, 16 tests. `node scripts/design-rules.test.mjs` passed. Commit: b95e6c04a67a6c75b88b46b63006b57a3c605fb1.
Author
Owner

Finding: Task List repeated the same local status sizing already represented by StatusPill size="compact" and drew the hidden-tag count as a custom span. Removed the override and now render the count with the shared inset Pill used by Task cards.

Evidence: TaskList.svelte.test.ts: 1 file, 4 tests passed; node scripts/design-rules.test.mjs passed; exact performance contract pins refreshed, without raising the ratchet. Commit: c74086679b.

Finding: Task List repeated the same local status sizing already represented by `StatusPill size="compact"` and drew the hidden-tag count as a custom span. Removed the override and now render the count with the shared inset `Pill` used by Task cards. Evidence: `TaskList.svelte.test.ts`: 1 file, 4 tests passed; `node scripts/design-rules.test.mjs` passed; exact performance contract pins refreshed, without raising the ratchet. Commit: c74086679b4d294e21889ea180b0a0e5ec656859.
Author
Owner

The design-rule regression test now scans changed Svelte/CSS in apps/web/src/lib, apps/web/src/routes, packages/editor/src, and packages/ui/src. It rejects new local primitive overrides in feature consumers and new hand-rolled classed buttons across those roots. packages/ui is excluded from the override check because a shared primitive must style its own composed internals; its native control markup remains guarded. node scripts/design-rules.test.mjs passes.

Commit: 2b27975324.

The design-rule regression test now scans changed Svelte/CSS in `apps/web/src/lib`, `apps/web/src/routes`, `packages/editor/src`, and `packages/ui/src`. It rejects new local primitive overrides in feature consumers and new hand-rolled classed buttons across those roots. `packages/ui` is excluded from the override check because a shared primitive must style its own composed internals; its native control markup remains guarded. `node scripts/design-rules.test.mjs` passes. Commit: 2b27975324bb1df94103b37cf8f90562390483e2.
Author
Owner

Coordination: #1200 owns SegmentedControl and all single-choice selector call sites; this audit leaves them alone and lists findings for them.

Coordination: #1200 owns SegmentedControl and all single-choice selector call sites; this audit leaves them alone and lists findings for them.
Author
Owner

Final report — Forgejo #1190

Head SHA: 2b27975324bb1df94103b37cf8f90562390483e2
Branch: job/restyle-1190
Status: The Tasks area and regression guard are implemented. The wider repo audit is not complete, so this branch is not ready to merge.

What changed

  • Added the 512-line, tab-grouped inventory to artifacts/restyle-audit.md and posted the full inventory in the earlier issue comment.
  • Replaced the audited Task Board, Task List and Task Inspector controls with shared Card, Checkbox, Pill, StatusPill and TagPill controls. TasksWorkspace also uses Pill for its Add and Retry actions. Existing action callbacks, task writes, tag filters and drag/drop behavior stay in place.
  • Extended Card with overflow and dropPreview; Pill with the Inspector text shape, shared hit floor and muted, danger and inset tones; and StatusPill with a compact size. Added component tests and package documentation.
  • Added apps/web/scripts/design-rules.test.mjs to reject new shared-primitive :global overrides in web and Editor feature code, and new classed native buttons across web, Editor and shared UI source. A local exception needs an adjacent comment with an issue number and reason. The rule compares changes with origin/dev so the existing inventory does not fail the gate.
  • Refreshed exact live performance pins for the changed source; no ratchet was raised.

Files

  • apps/web/scripts/design-rules.test.mjs, apps/web/package.json
  • apps/web/src/lib/tasks/TaskCard.svelte, TaskColumn.svelte, TaskList.svelte, TaskList.svelte.test.ts, TaskSection.svelte, TasksWorkspace.svelte
  • apps/web/src/lib/components/Card.svelte.test.ts, Pill.svelte.test.ts, StatusPill.svelte.test.ts
  • packages/ui/src/components/Card.svelte, Pill.svelte, StatusPill.svelte, packages/ui/src/tokens.css, packages/ui/README.md
  • contracts/perf/adoption-1058.json, contracts/perf/exceptions.json

The six commits are aef181c, d15075e, cf17753, b95e6c0, c740866 and 2b27975. The worktree is clean. No Rust source changed. cargo clean completed at the end and the web build output was removed.

UX gaps closed

  • Task controls use shared focus, hover, pressed and hit-area behavior. The Inspector's text actions use the shared 44 px hit floor.
  • Task status, tag count, card clipping and drag-preview paint now come from shared primitives instead of feature-local styles.
  • The Task actions continue to update the same server-backed records; this change adds no API requests or per-item data work. Render cost remains proportional to the visible Task rows and their controls.

UX gaps left

  • This job only remediated the Tasks findings. The Calendar, Notes, Files, Photos, Mail, Money, Search, Settings, Analytics, Notifications and Shared UI findings in the posted inventory still need triage and fixes. The #1189 BlockHoverActions.svelte item remains with #1189.
  • Codex attached evidence and did not judge its visual quality. The reviewer should inspect the screenshots below.

Decisions not stated in DESIGN.md

  • Shared primitive extensions own the missing Task treatments: Card owns clipping and drag preview; Pill owns compact Inspector text actions and semantic tones; StatusPill owns compact status sizing.
  • The regression test uses the fetched origin/dev tree as its baseline and only rejects new signatures. Existing inventory entries remain visible for follow-up instead of being silently grandfathered as individual exceptions.
  • This visual refactor adds no new user operation, route or IO path; no feature benchmark was added.

Web gate output

bun run check:

perf-lint: PASS; 0 violations; 22359 scoped exceptions
svelte-check found 0 errors and 2 warnings in 2 files

The two warnings are existing empty CSS rulesets in packages/ui/src/components/calendar/AttachmentDeck.svelte and AgendaList.svelte.

bun run test:

8 pass
0 fail
16 expect() calls
Ran 8 tests across 1 file. [1.62s]
design rules: no new shared primitive overrides or hand-rolled buttons (origin/dev baseline)

 Test Files  276 passed (276)
      Tests  1914 passed (1914)
   Duration  651.27s (transform 28%, environment 27%, import 21%, tests 18%, setup 6%)

Production screenshots

72 PNGs are attached to this issue: before and after for Tasks Board, Tasks List and Calendar Task Inspector at 390, 820 and 1440 px, in Paper light and Tokyo Night dark, at 1× and 2×. The production app used real server data and macOS platform emulation.

Open the 72-image screenshot index

Before

Tasks Board

Tasks List

Calendar Task Inspector

After

Tasks Board

Tasks List

Calendar Task Inspector

## Final report — Forgejo #1190 **Head SHA:** `2b27975324bb1df94103b37cf8f90562390483e2` **Branch:** `job/restyle-1190` **Status:** The Tasks area and regression guard are implemented. The wider repo audit is not complete, so this branch is not ready to merge. ### What changed - Added the 512-line, tab-grouped inventory to `artifacts/restyle-audit.md` and posted the full inventory in the earlier issue comment. - Replaced the audited Task Board, Task List and Task Inspector controls with shared `Card`, `Checkbox`, `Pill`, `StatusPill` and `TagPill` controls. `TasksWorkspace` also uses `Pill` for its Add and Retry actions. Existing action callbacks, task writes, tag filters and drag/drop behavior stay in place. - Extended `Card` with `overflow` and `dropPreview`; `Pill` with the Inspector `text` shape, shared hit floor and `muted`, `danger` and `inset` tones; and `StatusPill` with a `compact` size. Added component tests and package documentation. - Added `apps/web/scripts/design-rules.test.mjs` to reject new shared-primitive `:global` overrides in web and Editor feature code, and new classed native buttons across web, Editor and shared UI source. A local exception needs an adjacent comment with an issue number and reason. The rule compares changes with `origin/dev` so the existing inventory does not fail the gate. - Refreshed exact live performance pins for the changed source; no ratchet was raised. ### Files - `apps/web/scripts/design-rules.test.mjs`, `apps/web/package.json` - `apps/web/src/lib/tasks/TaskCard.svelte`, `TaskColumn.svelte`, `TaskList.svelte`, `TaskList.svelte.test.ts`, `TaskSection.svelte`, `TasksWorkspace.svelte` - `apps/web/src/lib/components/Card.svelte.test.ts`, `Pill.svelte.test.ts`, `StatusPill.svelte.test.ts` - `packages/ui/src/components/Card.svelte`, `Pill.svelte`, `StatusPill.svelte`, `packages/ui/src/tokens.css`, `packages/ui/README.md` - `contracts/perf/adoption-1058.json`, `contracts/perf/exceptions.json` The six commits are `aef181c`, `d15075e`, `cf17753`, `b95e6c0`, `c740866` and `2b27975`. The worktree is clean. No Rust source changed. `cargo clean` completed at the end and the web build output was removed. ### UX gaps closed - Task controls use shared focus, hover, pressed and hit-area behavior. The Inspector's text actions use the shared 44 px hit floor. - Task status, tag count, card clipping and drag-preview paint now come from shared primitives instead of feature-local styles. - The Task actions continue to update the same server-backed records; this change adds no API requests or per-item data work. Render cost remains proportional to the visible Task rows and their controls. ### UX gaps left - This job only remediated the Tasks findings. The Calendar, Notes, Files, Photos, Mail, Money, Search, Settings, Analytics, Notifications and Shared UI findings in the posted inventory still need triage and fixes. The #1189 `BlockHoverActions.svelte` item remains with #1189. - Codex attached evidence and did not judge its visual quality. The reviewer should inspect the screenshots below. ### Decisions not stated in DESIGN.md - Shared primitive extensions own the missing Task treatments: `Card` owns clipping and drag preview; `Pill` owns compact Inspector text actions and semantic tones; `StatusPill` owns compact status sizing. - The regression test uses the fetched `origin/dev` tree as its baseline and only rejects new signatures. Existing inventory entries remain visible for follow-up instead of being silently grandfathered as individual exceptions. - This visual refactor adds no new user operation, route or IO path; no feature benchmark was added. ### Web gate output `bun run check`: ```text perf-lint: PASS; 0 violations; 22359 scoped exceptions svelte-check found 0 errors and 2 warnings in 2 files ``` The two warnings are existing empty CSS rulesets in `packages/ui/src/components/calendar/AttachmentDeck.svelte` and `AgendaList.svelte`. `bun run test`: ```text 8 pass 0 fail 16 expect() calls Ran 8 tests across 1 file. [1.62s] design rules: no new shared primitive overrides or hand-rolled buttons (origin/dev baseline) Test Files 276 passed (276) Tests 1914 passed (1914) Duration 651.27s (transform 28%, environment 27%, import 21%, tests 18%, setup 6%) ``` ### Production screenshots 72 PNGs are attached to this issue: before and after for Tasks Board, Tasks List and Calendar Task Inspector at 390, 820 and 1440 px, in Paper light and Tokyo Night dark, at 1× and 2×. The production app used real server data and macOS platform emulation. <details> <summary>Open the 72-image screenshot index</summary> #### Before **Tasks Board** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/07b11341-5a44-423a-ae83-806fe5eb3e82) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/3cd4122a-acde-483c-b009-659abed0d480) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/ed64698b-04bf-47b3-aba2-6cac56a0e715) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/fbe3d98e-ad06-42ed-91dc-200e9ad0276b) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/4ec5ada6-3be5-4394-91fa-a4a7ff66e129) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/ba2ea082-1816-42a2-b35e-3c9dfd560486) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/6d7bbbde-5a54-45d2-94f2-9ba6de6c65f2) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/1ced2a42-e580-4494-a6ec-52dae64fb385) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/763873aa-6c0e-4ce9-a259-455b53041ef5) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/6287d09a-eaa1-42c6-825f-f0676b74b0a4) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/22cfd9c6-f742-4fc2-a736-372143be990d) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/56f113ce-9149-4c4d-b8d2-12c7da0f7322) **Tasks List** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/b40c55b6-2118-41a6-8d54-0358026e5657) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/58456a50-b39c-46d6-b9b4-6a86d6a63915) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/33a4004e-7163-402d-b4cd-db3dfd51a30f) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/0d7e697b-9d55-4b63-81ec-a343dc20ac26) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/0709106f-4090-43b1-9af1-727c572d590e) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/94b2f397-ca3a-4e4c-a853-4241b44d8d87) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/51b063b1-1d53-46db-8c22-ffc74691b70f) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/6b7e3d0a-70dc-4999-800a-2bedf72ef4a9) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/f029e4a3-bf28-4e1e-b863-7e9659d9bbc1) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/81d62dcd-d436-4b55-89cb-c43d3993e03d) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/94e7bc12-2a47-48fc-8fff-1e137d23777c) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/d177b9fa-4c0f-4961-bf7e-02847c459ba1) **Calendar Task Inspector** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/9d686dc6-e58e-4245-9c73-84291dc57f9d) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/4a1ad8ca-3284-4388-8327-6b0f173885e9) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/48695018-5175-47b9-8a62-4c804056badb) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/ae05ba2f-ebc9-4476-aae0-e8662a1c7417) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/9c45ce93-a066-450d-9ce9-dd3179eef92b) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/17ba309e-35e1-41b5-b5bd-28f6c983618a) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/57b0f8f4-b086-4ae7-b323-86bc56cf0bfc) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/72477a3b-a2d7-4db9-8019-25b03d20f789) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/77c5cca7-c9b7-42b3-a242-63f71dd6246e) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/10b24ef8-25aa-4a56-8552-d03b74921c32) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/e55180cf-da8e-4aa1-b59a-ce127c5f4cb6) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/53c8967c-0ead-4a08-8bde-60cfb5c5f37a) #### After **Tasks Board** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/4e598d99-1a04-48b3-9b71-1b5b5327adfb) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/a3574c20-aff4-410d-82a9-cfd7b2986aee) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/c1513690-06a1-4af4-a073-b94ddae30c6a) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/6d15d169-5f14-401a-b9e6-733c9740f209) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/3678cdd5-6a54-4778-92b4-c39b1d1bd393) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/3298b836-70ec-485a-98bb-86d014a80500) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/917f80b8-71ed-423d-9f55-450f73ab5dbc) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/e543c585-1604-4162-a4e6-dd4062f5cd57) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/a57ac85e-0053-419e-a6fe-c39253f21e32) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/7dbcc0bf-18b2-4c57-965b-64bac9291d9a) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/4ba1218b-ce94-40b2-af55-05e15d3f64d9) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/484aa365-39a5-45f3-8194-87fc4c9be002) **Tasks List** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/c6d61fc3-4f44-4f12-bbdd-4104104a198e) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/5cd5e2d5-38f9-4fc0-b3be-092bc6ce5d0d) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/502c2e6b-6559-499d-9de1-758620827484) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/dba74b46-c475-4ab9-9367-cb28739f6059) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/cec0077b-afc2-418f-9138-5fa7219dfe12) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/35eb8e45-6a64-4728-b5b9-d3830fb5d4fd) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/f265f709-f0ce-409d-992a-ebcd44bd1c40) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/adb53670-21fc-4508-9a45-a20806c6fdfb) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/80c0fd67-2229-4fea-9524-a8c5dd226e32) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/c444f93a-4074-481c-8852-ae935c6ee185) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/c27b47b8-fe04-4fd8-8fda-2cecc81a99e4) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/9a482ba7-c38a-41bf-941f-19ebe471ebb2) **Calendar Task Inspector** - [1x · 390 px · Paper light](https://git.kayg.org/attachments/e51c11ed-ae52-461f-a9d2-580913147d03) - [1x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/69abdf9b-b1e4-4722-82bc-755611bb2076) - [1x · 820 px · Paper light](https://git.kayg.org/attachments/9e017dbc-ff61-4c04-a91d-fa10f56d5b86) - [1x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/f13d9a74-648a-4422-9ce4-7ce44289f067) - [1x · 1440 px · Paper light](https://git.kayg.org/attachments/c6e745ad-4c49-4665-bfe0-882e9795a217) - [1x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/5b98eb86-6a87-46ff-8ea9-3ba4fcba7eca) - [2x · 390 px · Paper light](https://git.kayg.org/attachments/c25a99e4-e125-4510-8bd2-a6cdb4ba440f) - [2x · 390 px · Tokyo Night dark](https://git.kayg.org/attachments/b913cfb3-b236-44fe-9614-2ab82b98c45f) - [2x · 820 px · Paper light](https://git.kayg.org/attachments/b69bdb5f-cf53-49d4-8eb3-c8abb0b728aa) - [2x · 820 px · Tokyo Night dark](https://git.kayg.org/attachments/71827295-1111-49eb-876c-07f34b0ff7de) - [2x · 1440 px · Paper light](https://git.kayg.org/attachments/e2743085-bd07-46a3-bc23-4a356b72d0ec) - [2x · 1440 px · Tokyo Night dark](https://git.kayg.org/attachments/5d22ad20-267e-4109-a8c6-a26f7553ebc0) </details>
Author
Owner

Starting Notes restyle audit on branch job/restyle-notes, base 2b27975324. I’m locating the Notes inventory and surfaces now.

Starting Notes restyle audit on branch job/restyle-notes, base 2b27975324bb1df94103b37cf8f90562390483e2. I’m locating the Notes inventory and surfaces now.
Author
Owner

Starting Files+Photos pass on job/restyle-files, based on 2b27975324. I am locating the audit inventory and mapping its findings to the shared UI primitives before editing.

Starting Files+Photos pass on job/restyle-files, based on 2b27975324bb1df94103b37cf8f90562390483e2. I am locating the audit inventory and mapping its findings to the shared UI primitives before editing.
Author
Owner

Starting Calendar + Mail + Money findings for #1190.
Branch: job/restyle-mailmoney
Base SHA: 2b27975324
I have read CLAUDE.md, CONTEXT.md, and the relevant Calendar, Mail, Money, Chrome, and Connected Account decisions in docs/DESIGN.md.

Starting Calendar + Mail + Money findings for #1190. Branch: job/restyle-mailmoney Base SHA: 2b27975324bb1df94103b37cf8f90562390483e2 I have read CLAUDE.md, CONTEXT.md, and the relevant Calendar, Mail, Money, Chrome, and Connected Account decisions in docs/DESIGN.md.
Author
Owner

Starting Search-area restyle in job/restyle-search, based at 2b27975324.

Starting Search-area restyle in job/restyle-search, based at 2b27975324bb1df94103b37cf8f90562390483e2.
Author
Owner

Starting #1190 Settings area in job/restyle-settings, based at 2b27975324bb1df94103b37cf8f90562390483e2.

The prompt references artifacts/restyle-audit.md, but that file is not present in the worktree or HEAD. I am checking the issue's recorded inventory and the Settings-specific design guard to recover the exact findings before editing.

Starting #1190 Settings area in `job/restyle-settings`, based at `2b27975324bb1df94103b37cf8f90562390483e2`. The prompt references `artifacts/restyle-audit.md`, but that file is not present in the worktree or HEAD. I am checking the issue's recorded inventory and the Settings-specific design guard to recover the exact findings before editing.
Author
Owner

Evidence: test -f artifacts/restyle-audit.md returns false, and git ls-tree -r HEAD -- artifacts/restyle-audit.md returns no path. The initial inventory is present in the #1190 issue comments, so I am using it as the checklist for this pass.

Evidence: test -f artifacts/restyle-audit.md returns false, and git ls-tree -r HEAD -- artifacts/restyle-audit.md returns no path. The initial inventory is present in the #1190 issue comments, so I am using it as the checklist for this pass.
Author
Owner

Finding: artifacts/restyle-audit.md and the claimed top-level copy are absent from this worktree (git ls-tree and rg --files show no match). The issue's inventory comment contains the full Notes section, so I’m using that as the source list.

Finding: artifacts/restyle-audit.md and the claimed top-level copy are absent from this worktree (git ls-tree and rg --files show no match). The issue's inventory comment contains the full Notes section, so I’m using that as the source list.
Author
Owner

The first web check surfaced one stale exact performance pin: coverage.surfaces for apps/web/src/lib/canvas/CanvasView.svelte#each:3a4cbef6167607e4:1 reports “unused or changed exception.” This surface's action controls changed from native buttons to shared Pills and the local 44 px sizing rule was removed. I will refresh only the live syntax hash for the changed scope, keeping its owner, reason, replacement test, expiry, and limit unchanged, then rerun the guard.

The first web check surfaced one stale exact performance pin: `coverage.surfaces` for `apps/web/src/lib/canvas/CanvasView.svelte#each:3a4cbef6167607e4:1` reports “unused or changed exception.” This surface's action controls changed from native buttons to shared Pills and the local 44 px sizing rule was removed. I will refresh only the live syntax hash for the changed scope, keeping its owner, reason, replacement test, expiry, and limit unchanged, then rerun the guard.
Author
Owner

Inventory finding for Settings: artifacts/restyle-audit.md is absent from HEAD and the file history, but the #1190 audit comment records 18 shared-style overrides, 34 hand-rolled controls/cards, and 10 literal sizing/layout findings under Settings. I will use that posted inventory as the source.

Scope boundary: the listed BackgroundGroup swatches and Unsplash photo choices are single-choice selectors. I will leave those controls to #1200 as requested, while fixing the ordinary action controls and shared surfaces in the same files.

Inventory finding for Settings: `artifacts/restyle-audit.md` is absent from HEAD and the file history, but the #1190 audit comment records 18 shared-style overrides, 34 hand-rolled controls/cards, and 10 literal sizing/layout findings under Settings. I will use that posted inventory as the source. Scope boundary: the listed BackgroundGroup swatches and Unsplash photo choices are single-choice selectors. I will leave those controls to #1200 as requested, while fixing the ordinary action controls and shared surfaces in the same files.
Author
Owner

Notes implementation decisions where DESIGN was silent:

  • Card now has additive material="clear", edge="none", shadow="none", and radius="control" props. This lets the Note editor keep its existing host geometry and lets embedded Canvas cards use Card without consumer selectors on .card.
  • Pill adds shape="row" for full-width label/value actions and tone="accent-soft" for the parsed reminder status. Pressed and expanded action Pills use their real ARIA state for the shared selected tint.
  • OverlaySurface adds sheetHeaderLayout="centered-leading" so the phone Contents control stays centered while the changing sheet title remains in the accessibility tree.
  • The performance guard pins for the three existing CanvasView lists were refreshed only to their live syntax hashes; the owner, reason, replacement test, expiry and limit are unchanged.
  • The design-rule guard has no Notes allow-list entries; it compares the live design source against origin/dev.

The selector-owned surfaces stayed with their owners: Callout's kind selector and reminder audience selectors remain unchanged; PillGroup and BlockHoverActions remain untouched for #1189. No single-choice selector was changed.

Notes implementation decisions where DESIGN was silent: - Card now has additive `material="clear"`, `edge="none"`, `shadow="none"`, and `radius="control"` props. This lets the Note editor keep its existing host geometry and lets embedded Canvas cards use Card without consumer selectors on `.card`. - Pill adds `shape="row"` for full-width label/value actions and `tone="accent-soft"` for the parsed reminder status. Pressed and expanded action Pills use their real ARIA state for the shared selected tint. - OverlaySurface adds `sheetHeaderLayout="centered-leading"` so the phone Contents control stays centered while the changing sheet title remains in the accessibility tree. - The performance guard pins for the three existing CanvasView lists were refreshed only to their live syntax hashes; the owner, reason, replacement test, expiry and limit are unchanged. - The design-rule guard has no Notes allow-list entries; it compares the live design source against `origin/dev`. The selector-owned surfaces stayed with their owners: Callout's kind selector and reminder audience selectors remain unchanged; PillGroup and BlockHoverActions remain untouched for #1189. No single-choice selector was changed.
Author
Owner

Source review findings from the posted Settings inventory:

  • The eight entries labeled Card resolve to .card-footer layout wrappers inside existing SettingsCard groups. They are not private card shells; wrapping each footer in another Card would add nested surfaces. App Passwords also already uses the shared Card for its instruction sub-cards.
  • The UnsplashSheet photo choice button and ConnectedAccountsSection provider choice buttons select a single option/provider. I will leave them to #1200, along with the BackgroundGroup swatches and SegmentedControl.
  • BackgroundGroup's centre handle and stop controls are drag/slider controls, not action buttons. I will preserve their specialized interaction and only migrate plain actions in that group.
Source review findings from the posted Settings inventory: - The eight entries labeled `Card` resolve to `.card-footer` layout wrappers inside existing `SettingsCard` groups. They are not private card shells; wrapping each footer in another Card would add nested surfaces. App Passwords also already uses the shared `Card` for its instruction sub-cards. - The `UnsplashSheet` photo choice button and `ConnectedAccountsSection` provider choice buttons select a single option/provider. I will leave them to #1200, along with the BackgroundGroup swatches and SegmentedControl. - BackgroundGroup's centre handle and stop controls are drag/slider controls, not action buttons. I will preserve their specialized interaction and only migrate plain actions in that group.
Author
Owner

Finding during the Files restyle: bun run check reported an unused or changed exact render.bound pin for FilesBrowser.svelte#each:c469e9f9e005d61c:1. The Files menu row now uses the shared Pill, which changed the pinned loop syntax. I will refresh only this exact live pin and keep the existing performance rule and ratchet.

Finding during the Files restyle: `bun run check` reported an unused or changed exact `render.bound` pin for `FilesBrowser.svelte#each:c469e9f9e005d61c:1`. The Files menu row now uses the shared Pill, which changed the pinned loop syntax. I will refresh only this exact live pin and keep the existing performance rule and ratchet.
Author
Owner

Correction: the menu loop hash is shared by 12 exact performance-contract entries, not one. The source parser reports the live syntax digest as 93ca91d2cd4239a4edfab625a6074dfa70cba3907da5a7be04a94a8b455e6aa6. I will update those 12 existing entries to that digest only; their rules, limits, owners, and ratchet counts stay unchanged.

Correction: the menu loop hash is shared by 12 exact performance-contract entries, not one. The source parser reports the live syntax digest as `93ca91d2cd4239a4edfab625a6074dfa70cba3907da5a7be04a94a8b455e6aa6`. I will update those 12 existing entries to that digest only; their rules, limits, owners, and ratchet counts stay unchanged.
Author
Owner

The initial bun run check then reported two implicit-any event parameters in the shared Files pinned-row Pill, one in the shared Card form on PublicLinkPage, and an unused .drop-name rule after replacing that local control. I added DragEvent, KeyboardEvent, and SubmitEvent annotations and removed the dead selector. The full check will run again after the required origin/dev merge.

The initial `bun run check` then reported two implicit-`any` event parameters in the shared Files pinned-row Pill, one in the shared Card form on PublicLinkPage, and an unused `.drop-name` rule after replacing that local control. I added `DragEvent`, `KeyboardEvent`, and `SubmitEvent` annotations and removed the dead selector. The full check will run again after the required `origin/dev` merge.
Author
Owner

Finding and fix: the focused Card/Pill tests first failed because the shared primitives did not expose the Settings variants. I added status tones, shared sizing flags, solid Card material, sheet flattening, and a semantic drop-target Card mode, with component tests and prop documentation. Focused result: Test Files 2 passed (2); Tests 10 passed (10). The initial test invocation also found missing worktree dependencies; bun install --frozen-lockfile restored them without a lockfile change. Commit: 3b412851c.

Finding and fix: the focused Card/Pill tests first failed because the shared primitives did not expose the Settings variants. I added status tones, shared sizing flags, solid Card material, sheet flattening, and a semantic drop-target Card mode, with component tests and prop documentation. Focused result: `Test Files 2 passed (2); Tests 10 passed (10)`. The initial test invocation also found missing worktree dependencies; `bun install --frozen-lockfile` restored them without a lockfile change. Commit: `3b412851c`.
Author
Owner

Finding and fix: Settings StateChip and RowAction had feature-scoped global rules that painted generic Pill tones and disabled state. They now select shared Pill tones; Jobs detail actions use the shared flushStart prop. Focused result: Test Files 2 passed (2); Tests 9 passed (9). Commit: 7438aa832.

Finding and fix: Settings `StateChip` and `RowAction` had feature-scoped global rules that painted generic Pill tones and disabled state. They now select shared `Pill` tones; Jobs detail actions use the shared `flushStart` prop. Focused result: `Test Files 2 passed (2); Tests 9 passed (9)`. Commit: `7438aa832`.
Author
Owner

Finding and fix: Recovery Key, Unsplash and Calendar Feeds had local solid overlay paint; Recovery Key, Unsplash and Connected Accounts also carried local dialog sizes, and provider setup repeated the Settings sheet inset. OverlaySurface now owns solid, compact/standard/wide dialog sizes and the Settings chrome option. Focused result: Test Files 1 passed (1); Tests 24 passed (24). Commit: f169d5716.

Finding and fix: Recovery Key, Unsplash and Calendar Feeds had local solid overlay paint; Recovery Key, Unsplash and Connected Accounts also carried local dialog sizes, and provider setup repeated the Settings sheet inset. OverlaySurface now owns `solid`, compact/standard/wide dialog sizes and the Settings chrome option. Focused result: `Test Files 1 passed (1); Tests 24 passed (24)`. Commit: `f169d5716`.
Author
Owner

Finding: the App Password expiry trigger is a date-popover button with the same field material as a text input, but the shared Select owns a single-choice menu and is outside this issue's scope. I added the additive Pill field shape for anchored form triggers; it does not alter Select. The focused Card/Pill tests pass: Test Files 2 passed (2); Tests 11 passed (11). Commit: be81f469b.

Finding: the App Password expiry trigger is a date-popover button with the same field material as a text input, but the shared Select owns a single-choice menu and is outside this issue's scope. I added the additive `Pill` field shape for anchored form triggers; it does not alter Select. The focused Card/Pill tests pass: `Test Files 2 passed (2); Tests 11 passed (11)`. Commit: `be81f469b`.
Author
Owner

Finding and fix: Plugins used a native button with a local 44px shell and local grab/touch styles. The handle now uses shared Pill icon geometry and shared drag affordance while retaining the existing feature-owned drag action on the primitive root. Focused result: Test Files 2 passed (2); Tests 12 passed (12). Commit: 4bd206287.

Finding and fix: Plugins used a native button with a local 44px shell and local grab/touch styles. The handle now uses shared `Pill` icon geometry and shared drag affordance while retaining the existing feature-owned drag action on the primitive root. Focused result: `Test Files 2 passed (2); Tests 12 passed (12)`. Commit: `4bd206287`.
Author
Owner

Finding and fix: App Passwords had a sheet-only local Card override and a hand-built expiry button. SettingsCard now forwards flatOnSheet to shared Card, and the expiry date popover uses shared Pill field geometry. The new forwarding regression test passes: Test Files 1 passed (1); Tests 4 passed (4). Commit: 111b59bf6.

Finding and fix: App Passwords had a sheet-only local Card override and a hand-built expiry button. `SettingsCard` now forwards `flatOnSheet` to shared Card, and the expiry date popover uses shared Pill field geometry. The new forwarding regression test passes: `Test Files 1 passed (1); Tests 4 passed (4)`. Commit: `111b59bf6`.
Author
Owner

Finding and fix: the shared AuthCard hand-built its shell, and auth flows styled native .btn controls around it. AuthCard now delegates surface, dimensions, padding and stack gap to shared Card; the flow actions use shared Pills and auth-ui.css excludes Pills from its native-button recipe. Commit: 9b7717808.

Finding and fix: the shared AuthCard hand-built its shell, and auth flows styled native `.btn` controls around it. AuthCard now delegates surface, dimensions, padding and stack gap to shared Card; the flow actions use shared Pills and auth-ui.css excludes Pills from its native-button recipe. Commit: `9b7717808`.
Author
Owner

Finding and fix: Background picture upload used a feature-local dashed button, and its error retry used a hand-styled native button. The upload now uses shared Card dropTarget, and Retry uses the shared text Pill; file selection and drag-and-drop handlers are unchanged. Commit: 6df41be2a.

Finding and fix: Background picture upload used a feature-local dashed button, and its error retry used a hand-styled native button. The upload now uses shared Card `dropTarget`, and Retry uses the shared text Pill; file selection and drag-and-drop handlers are unchanged. Commit: `6df41be2a`.
Author
Owner

Finding and fix: the Settings route's account, Admin-data, Plugin-catalog and Shortcuts retry actions used a locally styled native button. They now use the shared text Pill with its shared focus and touch behavior. Commit: a303750dd.

Finding and fix: the Settings route's account, Admin-data, Plugin-catalog and Shortcuts retry actions used a locally styled native button. They now use the shared text Pill with its shared focus and touch behavior. Commit: `a303750dd`.
Author
Owner

Settings follow-up findings: Admin Sign-in and Calendar Feeds had local toggle row spacing; they now use the shared Settings gap and hit-area tokens. Notifications and Voice wrapped shared Toggles in extra 34 px wrappers; those wrappers are removed because Toggle owns the target. Settings form footers now use the shared toolbar gap while Money retains its own existing footer gap.

Commits: 57776d5e9, 1849d5c68, f1b077cfa, a84fbaf3d. git diff --check passed. The final web gates and production screenshots are still in progress.

Settings follow-up findings: Admin Sign-in and Calendar Feeds had local toggle row spacing; they now use the shared Settings gap and hit-area tokens. Notifications and Voice wrapped shared Toggles in extra 34 px wrappers; those wrappers are removed because Toggle owns the target. Settings form footers now use the shared toolbar gap while Money retains its own existing footer gap. Commits: `57776d5e9`, `1849d5c68`, `f1b077cfa`, `a84fbaf3d`. `git diff --check` passed. The final web gates and production screenshots are still in progress.
Author
Owner

Build finding: the local calternal-server target embeds apps/web/build, which was absent from this worktree. The server compile stopped at that embed step after dependency compilation. I am building this branch’s production web assets and will rerun cargo build -p calternal-server; no Rust source change is needed.

Build finding: the local calternal-server target embeds apps/web/build, which was absent from this worktree. The server compile stopped at that embed step after dependency compilation. I am building this branch’s production web assets and will rerun cargo build -p calternal-server; no Rust source change is needed.
Author
Owner

Evidence finding: the first baseline screenshot runner exited before browser launch because Bun sharp could not resolve libstdc++.so.6. The Nix runtime library at /nix/store/z0n70pxyzi87why1bcq81zgd7b924nfj-gcc-15.2.0-lib/lib resolves it, and a sharp import check passes with that LD_LIBRARY_PATH. I am retrying the captures with this runtime path.

Evidence finding: the first baseline screenshot runner exited before browser launch because Bun sharp could not resolve libstdc++.so.6. The Nix runtime library at /nix/store/z0n70pxyzi87why1bcq81zgd7b924nfj-gcc-15.2.0-lib/lib resolves it, and a sharp import check passes with that LD_LIBRARY_PATH. I am retrying the captures with this runtime path.
Author
Owner

Evidence finding: the existing Contents rail runner reached the baseline production page but failed its unchanged geometry assertion at 1440 px light: the hover title pill intersects Note body text (pill x=292.80–526.39 px). I am preserving the test expectation and checking the after build for this overlap; I will capture the full viewport/theme matrix with a capture-only fallback if the assertion aborts early.

Evidence finding: the existing Contents rail runner reached the baseline production page but failed its unchanged geometry assertion at 1440 px light: the hover title pill intersects Note body text (pill x=292.80–526.39 px). I am preserving the test expectation and checking the after build for this overlap; I will capture the full viewport/theme matrix with a capture-only fallback if the assertion aborts early.
Author
Owner

After-build finding: the Contents tick's offset parent is a zero-sized .pill-content; the shared magnetic action creates that positioning context, so the tick starts 15 px from the rail origin and the 1440 px hover pill begins 3 px before the tick ends. The preview container was also 233.6 px wide while Note text starts 182.8 px after its left edge. I am adding a Pill magnetic opt-out for positional markers and including both route paddings in the preview offset; the existing geometry assertions stay unchanged.

After-build finding: the Contents tick's offset parent is a zero-sized .pill-content; the shared magnetic action creates that positioning context, so the tick starts 15 px from the rail origin and the 1440 px hover pill begins 3 px before the tick ends. The preview container was also 233.6 px wide while Note text starts 182.8 px after its left edge. I am adding a Pill magnetic opt-out for positional markers and including both route paddings in the preview offset; the existing geometry assertions stay unchanged.
Author
Owner

Baseline evidence before code changes: CALTERNAL_SERVER_BIN=/home/kayg/build/targets/restyle-mailmoney/debug/calternal-server CALTERNAL_E2E_MAC=1 bun e2e/agenda-decks-822.mjs built the local production route and passed the media contract checks, then timed out after 90 seconds waiting for the Week/Day attachment list to become visible. The captured DOM showed .attachment-list.is-fan with aria-hidden="true" and the is-stack is-fan classes. The script emitted partial Agenda screenshots, then exited 1. I did not change the existing assertion; I am keeping this restyle scoped to #1190 and will capture the affected Calendar surfaces with a focused screenshot flow.

Baseline evidence before code changes: `CALTERNAL_SERVER_BIN=/home/kayg/build/targets/restyle-mailmoney/debug/calternal-server CALTERNAL_E2E_MAC=1 bun e2e/agenda-decks-822.mjs` built the local production route and passed the media contract checks, then timed out after 90 seconds waiting for the Week/Day attachment list to become visible. The captured DOM showed `.attachment-list.is-fan` with `aria-hidden="true"` and the `is-stack is-fan` classes. The script emitted partial Agenda screenshots, then exited 1. I did not change the existing assertion; I am keeping this restyle scoped to #1190 and will capture the affected Calendar surfaces with a focused screenshot flow.
Author
Owner

Screenshot evidence finding: the after build's real Settings theme-save API returned HTTP 507 with Home storage quota or server free-space reserve reached. df -h showed 23 GB available on /dev/sdb1. The screenshot fixture stopped before the after matrix completed. I am freeing this job's Rust build output, then I will rerun the production captures.

Screenshot evidence finding: the after build's real Settings theme-save API returned HTTP 507 with `Home storage quota or server free-space reserve reached`. `df -h` showed 23 GB available on `/dev/sdb1`. The screenshot fixture stopped before the after matrix completed. I am freeing this job's Rust build output, then I will rerun the production captures.
Author
Owner

After-fix finding: magnetic opt-out and padded route offset now pass the horizontal and prose-overlap assertions. The remaining centering assertion showed the rail's one-class placement selector losing to shared positioning, leaving the root 7 px above its row center. I strengthened the layout selector to target the rail row; the existing centering expectation is unchanged.

After-fix finding: magnetic opt-out and padded route offset now pass the horizontal and prose-overlap assertions. The remaining centering assertion showed the rail's one-class placement selector losing to shared positioning, leaving the root 7 px above its row center. I strengthened the layout selector to target the rail row; the existing centering expectation is unchanged.
Author
Owner

Clarification: after the prior fix, the remaining Contents tick centering issue came from selector specificity. The shared icon pill rule uses two classes, so the rail's one-class position rule did not win. I strengthened the Notes rail selector; the test expectation remains unchanged.

Clarification: after the prior fix, the remaining Contents tick centering issue came from selector specificity. The shared icon pill rule uses two classes, so the rail's one-class position rule did not win. I strengthened the Notes rail selector; the test expectation remains unchanged.
Author
Owner

After-fix finding: the 1440 px hover geometry now passes, including tick clearance and no prose overlap. The next assertion found the visible tick extends 1 px into the editor Card at 820 px because the shared Pill border moves its child marker inward. I am offsetting the decorative tick by the shared hairline token so it aligns with the rail's outer edge; assertions remain unchanged.

After-fix finding: the 1440 px hover geometry now passes, including tick clearance and no prose overlap. The next assertion found the visible tick extends 1 px into the editor Card at 820 px because the shared Pill border moves its child marker inward. I am offsetting the decorative tick by the shared hairline token so it aligns with the rail's outer edge; assertions remain unchanged.
Author
Owner

Notes Contents follow-up: the real-server tablet geometry assertion measured the visible tick 0.078 px inside the editor Card after the shared Pill border inset. I increased the decorative marker offset by one shared hairline. The unchanged tocrail-636 assertion now passes across desktop, tablet, and phone in light and dark at 1x; committing this Contents surface fix.

Notes Contents follow-up: the real-server tablet geometry assertion measured the visible tick 0.078 px inside the editor Card after the shared Pill border inset. I increased the decorative marker offset by one shared hairline. The unchanged tocrail-636 assertion now passes across desktop, tablet, and phone in light and dark at 1x; committing this Contents surface fix.
Author
Owner

Resuming #1190 in job/restyle-search. Base/head at resume: 2b27975324. Working tree is clean; I am locating the Search audit inventory and continuing the Search-only fixes.

Resuming #1190 in job/restyle-search. Base/head at resume: 2b27975324bb1df94103b37cf8f90562390483e2. Working tree is clean; I am locating the Search audit inventory and continuing the Search-only fixes.
Author
Owner

Files+Photos visual verification update (2026-10-06)

  • The broad Files screenshot-only run stopped before capture while waiting for thumbnail-cache-547.txt to produce a PDF thumbnail. The API entry reported mime=application/pdf and has_thumbnail=true, but the harness timed out after 120 seconds. I left the assertion unchanged and added a focused real-API Files Browser/Sidebar capture path. Baseline and current each passed the six Mac captures at 390/820/1440 in light/dark (phone/tablet 2×, desktop 1×).
  • The broad Photos screenshot-only run exposed an existing strict locator ambiguity: the empty state and toolbar both provide an “Upload photos” button. I left that expectation unchanged. Its 36-group seed then stalled with SQLx pool waits; server diagnostics recorded acquired_after_secs=5175.653340628 and Index-busy errors. I stopped that SLOW-only run and added an opt-in capture path that reuses the same real five-frame burst fixture from the full test. Baseline and current each passed empty-state and key-photo action captures at all three review widths and both themes.
  • The root filesystem fell below the server’s five-percent free-space reserve during the clean server build (27 GB available on a 591 GB filesystem), so the real API correctly returned HTTP 507 for fixture writes. I preserved the built server binary, ran cargo clean (7.3 GiB removed), and pointed the required worktree target/tmp path at a job-specific directory on /mnt/hdd. The reserve guard stayed enabled and subsequent fixture writes succeeded.
Files+Photos visual verification update (2026-10-06) - The broad Files screenshot-only run stopped before capture while waiting for `thumbnail-cache-547.txt` to produce a PDF thumbnail. The API entry reported `mime=application/pdf` and `has_thumbnail=true`, but the harness timed out after 120 seconds. I left the assertion unchanged and added a focused real-API Files Browser/Sidebar capture path. Baseline and current each passed the six Mac captures at 390/820/1440 in light/dark (phone/tablet 2×, desktop 1×). - The broad Photos screenshot-only run exposed an existing strict locator ambiguity: the empty state and toolbar both provide an “Upload photos” button. I left that expectation unchanged. Its 36-group seed then stalled with SQLx pool waits; server diagnostics recorded `acquired_after_secs=5175.653340628` and Index-busy errors. I stopped that SLOW-only run and added an opt-in capture path that reuses the same real five-frame burst fixture from the full test. Baseline and current each passed empty-state and key-photo action captures at all three review widths and both themes. - The root filesystem fell below the server’s five-percent free-space reserve during the clean server build (27 GB available on a 591 GB filesystem), so the real API correctly returned HTTP 507 for fixture writes. I preserved the built server binary, ran `cargo clean` (7.3 GiB removed), and pointed the required worktree `target/tmp` path at a job-specific directory on `/mnt/hdd`. The reserve guard stayed enabled and subsequent fixture writes succeeded.
Author
Owner

Baseline screenshot finding: the existing Notes section-card geometry assertion reports a 9 px overlap (gap = -9 px) on the pre-restyle build. I will retain the normal assertion unchanged; for before images only, a temporary capture runner bypasses assertions so the actual baseline rendering can be attached. The failing pre-restyle flow is isolated from the production changes.

Baseline screenshot finding: the existing Notes section-card geometry assertion reports a 9 px overlap (gap = -9 px) on the pre-restyle build. I will retain the normal assertion unchanged; for before images only, a temporary capture runner bypasses assertions so the actual baseline rendering can be attached. The failing pre-restyle flow is isolated from the production changes.
Author
Owner

Final web gate finding from cd apps/web && bun run check:

  • perf-lint: INVALID reports an unused or changed render.bound exception for apps/web/src/lib/auth/components/RecoveryKeyEntry.svelte#each:a69de360f4657485:1.
  • The glass token guard reports backdrop-filter literals in packages/ui/src/components/Card.svelte:97 and OverlaySurface.svelte:1015.
  • The shape token guard reports border-radius numeric literal 0 in packages/ui/src/components/Card.svelte:106.

I am tracing each report against the current source and live guard entries before changing code.

Final web gate finding from `cd apps/web && bun run check`: - `perf-lint: INVALID` reports an unused or changed `render.bound` exception for `apps/web/src/lib/auth/components/RecoveryKeyEntry.svelte#each:a69de360f4657485:1`. - The glass token guard reports `backdrop-filter` literals in `packages/ui/src/components/Card.svelte:97` and `OverlaySurface.svelte:1015`. - The shape token guard reports `border-radius` numeric literal `0` in `packages/ui/src/components/Card.svelte:106`. I am tracing each report against the current source and live guard entries before changing code.
Author
Owner

Finding: the required post-merge bun run check found the MailView.svelte exact render.bound pin no longer matched. I compared the loop hashes at the original audit base, the incoming origin/dev parent, and this branch parent: the four MailView loops match at the base and origin/dev, while this branch's Pill/Card action markup changes the enclosing component hash. I am refreshing only those four exact live hashes in the performance registry, exceptions, and adoption records. Owners, reasons, limits, replacement tests and ratchets remain unchanged. svelte-check found 0 errors and 4 existing warnings (AgendaList empty ruleset; three MailView swipe selectors).

Finding: the required post-merge `bun run check` found the `MailView.svelte` exact `render.bound` pin no longer matched. I compared the loop hashes at the original audit base, the incoming `origin/dev` parent, and this branch parent: the four `MailView` loops match at the base and `origin/dev`, while this branch's Pill/Card action markup changes the enclosing component hash. I am refreshing only those four exact live hashes in the performance registry, exceptions, and adoption records. Owners, reasons, limits, replacement tests and ratchets remain unchanged. `svelte-check` found 0 errors and 4 existing warnings (AgendaList empty ruleset; three MailView swipe selectors).
Author
Owner

Search audit finding: the branch tree and HEAD contain no artifacts/restyle-audit.md; git ls-tree -r HEAD confirms it is absent. The full Search inventory is in the existing #1190 inventory comment (9 shared-style overrides, 20 controls, 14 literal findings). I am using that posted list as the checklist. The required origin/dev merge also had StatusPill component/test and UI README conflicts; I kept the dev inline feedback variant and the branch's compact StatusPill size, with their tests and docs.

Search audit finding: the branch tree and HEAD contain no `artifacts/restyle-audit.md`; `git ls-tree -r HEAD` confirms it is absent. The full Search inventory is in the existing #1190 inventory comment (9 shared-style overrides, 20 controls, 14 literal findings). I am using that posted list as the checklist. The required `origin/dev` merge also had StatusPill component/test and UI README conflicts; I kept the `dev` inline feedback variant and the branch's compact StatusPill size, with their tests and docs.
Author
Owner

Merge integration finding: after the exact MailView refresh, the required check exposed 11 stale TaskColumn loop pins. The merged UI keeps the base branch's shared Pill and Card implementation; the incoming exception/adoption entries had an adapter hash for the alternate source version. I verified the live visibleItems list AST hash is ab66631596991438470a60606ae91b83b42a16b9d660acabc5ac5175625a776b, which matches the registry and current render.bound entry. I refreshed only the 11 related exception/adoption hashes. TaskColumn source behavior, limits, owners and ratchets did not change. Commit: 6cf73b060.

Merge integration finding: after the exact MailView refresh, the required check exposed 11 stale TaskColumn loop pins. The merged UI keeps the base branch's shared Pill and Card implementation; the incoming exception/adoption entries had an adapter hash for the alternate source version. I verified the live `visibleItems` list AST hash is `ab66631596991438470a60606ae91b83b42a16b9d660acabc5ac5175625a776b`, which matches the registry and current `render.bound` entry. I refreshed only the 11 related exception/adoption hashes. TaskColumn source behavior, limits, owners and ratchets did not change. Commit: `6cf73b060`.
Author
Owner

Finding: after the Mail pins were refreshed, the check found a stale Calendar route render.bound identity. I compared live Svelte syntax against the exact registry, exception, and adoption entries in every Calendar, Mail, Money, and shared primitive file changed by this branch. Fourteen changed list identities needed new exact hashes. I updated their 14 registry hashes, 168 exception hashes, and 132 adoption hashes. The 3 YearHeatmap loops have no adoption record. No performance limits, exception rules, owners, reasons, or ratchets changed. Commit: 9e2318686.

Finding: after the Mail pins were refreshed, the check found a stale Calendar route `render.bound` identity. I compared live Svelte syntax against the exact registry, exception, and adoption entries in every Calendar, Mail, Money, and shared primitive file changed by this branch. Fourteen changed list identities needed new exact hashes. I updated their 14 registry hashes, 168 exception hashes, and 132 adoption hashes. The 3 YearHeatmap loops have no adoption record. No performance limits, exception rules, owners, reasons, or ratchets changed. Commit: `9e2318686`.
Author
Owner

Files+Photos evidence update: the first UploadToast capture path found that the completed toast stays in Sonner's stack after Close, so waiting for DOM detachment was invalid. A later after-build attempt also missed the card's four-second read window while the shared host logged 2–4 second SQLx waits. I changed the evidence path to hold the real Tus PATCH, capture the collapsed in-progress toast, expand by keyboard, release the upload, and capture the completed row. The focused rerun is pending.

The after-build Share capture produced all 18 Share and outgoing-grant screenshots, then made no progress for 191 seconds while fetching the newly created link list. The baseline visitor-page capture passed. I removed that extra API lookup and now read the slug from the URL displayed in the real Share dialog before opening the public page. I will rerun both builds.

Files+Photos evidence update: the first UploadToast capture path found that the completed toast stays in Sonner's stack after Close, so waiting for DOM detachment was invalid. A later after-build attempt also missed the card's four-second read window while the shared host logged 2–4 second SQLx waits. I changed the evidence path to hold the real Tus PATCH, capture the collapsed in-progress toast, expand by keyboard, release the upload, and capture the completed row. The focused rerun is pending. The after-build Share capture produced all 18 Share and outgoing-grant screenshots, then made no progress for 191 seconds while fetching the newly created link list. The baseline visitor-page capture passed. I removed that extra API lookup and now read the slug from the URL displayed in the real Share dialog before opening the public page. I will rerun both builds.
Author
Owner

Pin-refresh finding: the live parser identified two changed list identities in RecoveryKeyEntry.svelte, and the exact 24 pins for those identities now match their current source hashes. The next perf-lint run exposed another stale exact pin at RecoveryKeyWords.svelte#each:a69de360f4657485:1. I am checking every changed Svelte file for the same source-hash change; exception limits and ratchet counts remain unchanged.

Pin-refresh finding: the live parser identified two changed list identities in `RecoveryKeyEntry.svelte`, and the exact 24 pins for those identities now match their current source hashes. The next perf-lint run exposed another stale exact pin at `RecoveryKeyWords.svelte#each:a69de360f4657485:1`. I am checking every changed Svelte file for the same source-hash change; exception limits and ratchet counts remain unchanged.
Author
Owner

Finding: the next post-merge check reached Calendar's route-level blocked-network exception after the list pins were refreshed. The Calendar page and both restyled Money routes also carry route-level snapshot/readiness contracts pinned to each complete Svelte component. I recomputed the live component hashes and updated 3 route registry hashes plus the 12 matching exception and 12 adoption hashes. This records the current shared-control markup; it changes no route behavior, rule, limit, owner, or ratchet. Commit: e6127aea0.

Finding: the next post-merge check reached Calendar's route-level `blocked-network` exception after the list pins were refreshed. The Calendar page and both restyled Money routes also carry route-level snapshot/readiness contracts pinned to each complete Svelte component. I recomputed the live component hashes and updated 3 route registry hashes plus the 12 matching exception and 12 adoption hashes. This records the current shared-control markup; it changes no route behavior, rule, limit, owner, or ratchet. Commit: `e6127aea0`.
Author
Owner

The broad live-hash refresh now covers 298 existing exact pins across 24 changed Svelte files, plus 21 surface hashes and one route hash. The next perf-lint check reached the separate #1058 adoption checkpoint and reports that one checkpoint row no longer matches its exact live ledger entry. I am aligning only checkpoint rows that still have a current exception identity; no new rows or counts are planned.

The broad live-hash refresh now covers 298 existing exact pins across 24 changed Svelte files, plus 21 surface hashes and one route hash. The next perf-lint check reached the separate #1058 adoption checkpoint and reports that one checkpoint row no longer matches its exact live ledger entry. I am aligning only checkpoint rows that still have a current exception identity; no new rows or counts are planned.
Author
Owner

Files+Photos evidence update: the new focused Files Inspector matrix did not produce a screenshot during a two-minute baseline attempt. The process check showed its local calternal-server in D state with jbd2_log_wait_commit; I stopped the browser run. No UI assertion or 5xx result was reported. This is SLOW host filesystem pressure. The focused --restyle-screenshots-only runner is in apps/web/e2e/info-inspector.mjs for a rerun on the merge host.

Files+Photos evidence update: the new focused Files Inspector matrix did not produce a screenshot during a two-minute baseline attempt. The process check showed its local calternal-server in D state with `jbd2_log_wait_commit`; I stopped the browser run. No UI assertion or 5xx result was reported. This is SLOW host filesystem pressure. The focused `--restyle-screenshots-only` runner is in `apps/web/e2e/info-inspector.mjs` for a rerun on the merge host.
Author
Owner

Gate finding: Search list markup changed exact render-bound syntax hashes. I refreshed only the live hashes for the touched Search lists in contracts/perf/{registry,adoption-1058,exceptions}.json. The merged origin/dev tree also had a stale TaskColumn render pin, so I refreshed that one live hash without changing its rule, bound, owner, replacement test or ratchet. The web check is running again against these exact entries.

Gate finding: Search list markup changed exact render-bound syntax hashes. I refreshed only the live hashes for the touched Search lists in contracts/perf/{registry,adoption-1058,exceptions}.json. The merged origin/dev tree also had a stale TaskColumn render pin, so I refreshed that one live hash without changing its rule, bound, owner, replacement test or ratchet. The web check is running again against these exact entries.
Author
Owner

Calendar/Mail/Money finding: after refreshing the exact route and list pins, bun run check identified one remaining stale material.inline-style-resolution hash for apps/web/src/routes/calendar/[view]/[date]/+page.svelte (style:b2b7ef5bfe5a1a28). The base commit had the pinned hash 29ee0065…; the live AST hash is 14eced58…, verified against the perf-source syntax/hash calculation. Updated the matching exact entry in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json. No budgets, owners, reasons, or rule behavior changed. Commit: 15d0d67b88f390eb6dc384e08b339ba1527145c4.

Calendar/Mail/Money finding: after refreshing the exact route and list pins, `bun run check` identified one remaining stale `material.inline-style-resolution` hash for `apps/web/src/routes/calendar/[view]/[date]/+page.svelte` (`style:b2b7ef5bfe5a1a28`). The base commit had the pinned hash `29ee0065…`; the live AST hash is `14eced58…`, verified against the perf-source syntax/hash calculation. Updated the matching exact entry in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`. No budgets, owners, reasons, or rule behavior changed. Commit: `15d0d67b88f390eb6dc384e08b339ba1527145c4`.
Author
Owner

Calendar/Mail/Money finding: the next bun run check surfaced a stale material.inline-style-resolution hash in shared packages/ui/src/components/calendar/ActivityStack.svelte (style:217bb7d1d4cb1c92). The current parsed Svelte syntax hash is 1e6ed8e9…, replacing the exact prior hash 2f024a11… in the matching rows of contracts/perf/exceptions.json and contracts/perf/adoption-1058.json. Budgets, owners, reasons, and rule behavior are unchanged. Commit: 75788f8c3a3f02cbc64476188f760bae96750301.

Calendar/Mail/Money finding: the next `bun run check` surfaced a stale `material.inline-style-resolution` hash in shared `packages/ui/src/components/calendar/ActivityStack.svelte` (`style:217bb7d1d4cb1c92`). The current parsed Svelte syntax hash is `1e6ed8e9…`, replacing the exact prior hash `2f024a11…` in the matching rows of `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`. Budgets, owners, reasons, and rule behavior are unchanged. Commit: `75788f8c3a3f02cbc64476188f760bae96750301`.
Author
Owner

Calendar/Mail/Money finding: perf-lint then identified a second ActivityStack style exception whose identity changed when the hand-built stack layer became a shared Card. The old style:2486fb050ad813df attribute no longer exists; the live Card style binding is style:60ec4ccb0f079c8a with exact current syntax hash be04de23…. Updated that paired exception/adoption record. No limits, ownership, reasons, or rule behavior changed. Commit: f7a51c334dbdc83d054674a56c72db0275ba6a24.

Calendar/Mail/Money finding: perf-lint then identified a second ActivityStack style exception whose identity changed when the hand-built stack layer became a shared `Card`. The old `style:2486fb050ad813df` attribute no longer exists; the live Card style binding is `style:60ec4ccb0f079c8a` with exact current syntax hash `be04de23…`. Updated that paired exception/adoption record. No limits, ownership, reasons, or rule behavior changed. Commit: `f7a51c334dbdc83d054674a56c72db0275ba6a24`.
Author
Owner

Calendar/Mail/Money finding: after the shared ActivityStack pins were aligned, perf-lint surfaced TimeGrid's existing layout.observer-purpose record. Its scope hash changed because the Calendar script now imports shared Pill; the resize observer itself is unchanged. Reproduced the old hash (46c3faf2…) from the starting commit and computed the current Tree-sitter scope hash (b96c78ea…). Updated only the paired exact entry in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json. Commit: 69b2f611d6e5cbffd3a3a6b691adfb7e00782246.

Calendar/Mail/Money finding: after the shared ActivityStack pins were aligned, perf-lint surfaced TimeGrid's existing `layout.observer-purpose` record. Its scope hash changed because the Calendar script now imports shared `Pill`; the resize observer itself is unchanged. Reproduced the old hash (`46c3faf2…`) from the starting commit and computed the current Tree-sitter scope hash (`b96c78ea…`). Updated only the paired exact entry in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`. Commit: `69b2f611d6e5cbffd3a3a6b691adfb7e00782246`.
Author
Owner

Calendar/Mail/Money finding: perf-lint found the existing YearHeatmap month-position inline-style exception after the date-cell markup changed to shared Pill. The style-site identity remains style:ea4ea4ad3d5ec4c8; its current exact AST hash is 9ea2c2ab…. Updated the single matching entry in contracts/perf/exceptions.json; no limit, owner, reason, or rule behavior changed. Commit: f6b861c71c600ad53e7f5d3f323e755d7634a735.

Calendar/Mail/Money finding: perf-lint found the existing YearHeatmap month-position inline-style exception after the date-cell markup changed to shared `Pill`. The style-site identity remains `style:ea4ea4ad3d5ec4c8`; its current exact AST hash is `9ea2c2ab…`. Updated the single matching entry in `contracts/perf/exceptions.json`; no limit, owner, reason, or rule behavior changed. Commit: `f6b861c71c600ad53e7f5d3f323e755d7634a735`.
Author
Owner

The final production recapture stopped at the 820 px 2× dark recovery-key flow. After clicking Create new key, the screenshot helper timed out after 15 seconds while waiting for the Save your new recovery key heading. The earlier final-build 390 px and 820 px captures remain present. I am tracing the recovery API action and will resume from 820 px 2× with status-only diagnostics; no recovery key text is logged or captured before redaction.

The final production recapture stopped at the 820 px 2× dark recovery-key flow. After clicking **Create new key**, the screenshot helper timed out after 15 seconds while waiting for the `Save your new recovery key` heading. The earlier final-build 390 px and 820 px captures remain present. I am tracing the recovery API action and will resume from 820 px 2× with status-only diagnostics; no recovery key text is logged or captured before redaction.
Author
Owner

Calendar/Mail/Money finding: adding the shared square heatmap swatch token changed the whole packages/ui/src/tokens.css syntax hash. The 18 existing material.local-filter sites remain unchanged, but each combined exact pin includes that file hash. Verified the old first pin against the starting commit, recomputed all 18 live facts with the Svelte parser, and updated only their paired hashes in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json. No filter, budget, owner, reason, or rule behavior changed. Commit: bac20fea2c3ea998854e7c027d0ee2336f83d569.

Calendar/Mail/Money finding: adding the shared square heatmap swatch token changed the whole `packages/ui/src/tokens.css` syntax hash. The 18 existing `material.local-filter` sites remain unchanged, but each combined exact pin includes that file hash. Verified the old first pin against the starting commit, recomputed all 18 live facts with the Svelte parser, and updated only their paired hashes in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`. No filter, budget, owner, reason, or rule behavior changed. Commit: `bac20fea2c3ea998854e7c027d0ee2336f83d569`.
Author
Owner

Files+Photos post-merge check finding: the live performance scan found stale exact hashes on existing list-rendering scopes in branch-touched Svelte files. It found no removed or new scopes. I refreshed only matching hash fields in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json; limits, owners, reasons, counts and contracts/perf/ratchet.json stayed unchanged.

perf-lint now reports perf-lint: PASS; 0 violations; 22615 scoped exceptions. The required cd apps/web && bun run check also passes with svelte-check found 0 errors and 0 warnings. It exposed two empty Calendar focus rulesets in merged sources; I removed those no-op selectors so the whole-web check passes.

Commits: 09fb4a988 (exact pin refresh), d33cbb38f (empty selector cleanup). The full bun run test is running. I have attached 49 safe Files/Photos/UploadToast before/after PNG assets to this issue; share-folder screenshots remain withheld because their rendered state includes public-link URLs.

Files+Photos post-merge check finding: the live performance scan found stale exact hashes on existing list-rendering scopes in branch-touched Svelte files. It found no removed or new scopes. I refreshed only matching `hash` fields in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`; limits, owners, reasons, counts and `contracts/perf/ratchet.json` stayed unchanged. `perf-lint` now reports `perf-lint: PASS; 0 violations; 22615 scoped exceptions`. The required `cd apps/web && bun run check` also passes with `svelte-check found 0 errors and 0 warnings`. It exposed two empty Calendar focus rulesets in merged sources; I removed those no-op selectors so the whole-web check passes. Commits: `09fb4a988` (exact pin refresh), `d33cbb38f` (empty selector cleanup). The full `bun run test` is running. I have attached 49 safe Files/Photos/UploadToast before/after PNG assets to this issue; share-folder screenshots remain withheld because their rendered state includes public-link URLs.
Author
Owner

The final 1440 px 2× recapture stopped after the auth screens. waitForAppearanceLoad in the production screenshot helper timed out at 15 seconds while awaiting the Settings Appearance response; the error contained no HTTP status. I am extending only the ignored capture helper's page action/navigation timeouts to 60 seconds and resuming this desktop 2× set.

The final 1440 px 2× recapture stopped after the auth screens. `waitForAppearanceLoad` in the production screenshot helper timed out at 15 seconds while awaiting the Settings Appearance response; the error contained no HTTP status. I am extending only the ignored capture helper's page action/navigation timeouts to 60 seconds and resuming this desktop 2× set.
Author
Owner

The first full post-merge bun run test completed with 3 failures (280 files passed, 3 failed; 1,987 tests passed, 3 failed). Two are source-contract assertions that no longer follow the shared owners in this branch: themes.test.ts expects Card's old literal class string after Card gained the material variant, and sidebar-weight.test.ts expects a local .pin-link rule after FilesSidebar moved that row to shared Pill shape="row". I will update those checks to keep the existing rendered contract on the shared primitives. The remaining EditorFormatBar.svelte.test.ts test timed out at 5,948 ms against its 5,000 ms limit; I will check it in isolation without changing its timeout or expectations.

The first full post-merge `bun run test` completed with 3 failures (280 files passed, 3 failed; 1,987 tests passed, 3 failed). Two are source-contract assertions that no longer follow the shared owners in this branch: `themes.test.ts` expects Card's old literal class string after Card gained the `material` variant, and `sidebar-weight.test.ts` expects a local `.pin-link` rule after FilesSidebar moved that row to shared `Pill shape="row"`. I will update those checks to keep the existing rendered contract on the shared primitives. The remaining `EditorFormatBar.svelte.test.ts` test timed out at 5,948 ms against its 5,000 ms limit; I will check it in isolation without changing its timeout or expectations.
Author
Owner

The desktop 2× retry timed out on a /readyz page navigation after 60 seconds. Playwright reported that it was waiting for the navigation load event; it did not report an HTTP failure status. The capture helper only uses this endpoint to stage the next theme, so I am changing that one navigation to wait for the response commit and then continue with the real Appearance save and Settings route.

The desktop 2× retry timed out on a `/readyz` page navigation after 60 seconds. Playwright reported that it was waiting for the navigation `load` event; it did not report an HTTP failure status. The capture helper only uses this endpoint to stage the next theme, so I am changing that one navigation to wait for the response commit and then continue with the real Appearance save and Settings route.
Author
Owner

Resolved the full-suite findings without changing rendered expectations or timeouts:

  • Shared Pill shape="row" now uses --sidebar-row-weight. The Files sidebar continues to use the shared row primitive, and its weight no longer lives in local CSS.
  • The theme contract now checks Card's page and overlay material directives. A runtime Card test confirms the default still renders as glass-card.
  • The EditorFormatBar timeout was load-sensitive: the isolated focused run passed with the original 5-second timeout.

Focused command: bunx vitest run src/lib/components/Pill.svelte.test.ts src/lib/styles/sidebar-weight.test.ts src/lib/themes.test.ts src/lib/components/Card.svelte.test.ts src/lib/editor/format/EditorFormatBar.svelte.test.ts --maxWorkers=2

Output: Test Files 5 passed (5) and Tests 97 passed (97). Commits: 9bbac94f4 and 3b007f3bb. I will run the full post-fix web check and test suite before finishing.

Resolved the full-suite findings without changing rendered expectations or timeouts: - Shared `Pill shape="row"` now uses `--sidebar-row-weight`. The Files sidebar continues to use the shared row primitive, and its weight no longer lives in local CSS. - The theme contract now checks Card's page and overlay material directives. A runtime Card test confirms the default still renders as `glass-card`. - The EditorFormatBar timeout was load-sensitive: the isolated focused run passed with the original 5-second timeout. Focused command: `bunx vitest run src/lib/components/Pill.svelte.test.ts src/lib/styles/sidebar-weight.test.ts src/lib/themes.test.ts src/lib/components/Card.svelte.test.ts src/lib/editor/format/EditorFormatBar.svelte.test.ts --maxWorkers=2` Output: `Test Files 5 passed (5)` and `Tests 97 passed (97)`. Commits: `9bbac94f4` and `3b007f3bb`. I will run the full post-fix web check and test suite before finishing.
Author
Owner

#1190 Search restyle — complete

Branch: job/restyle-search
Head: 18b791864eebcc8d7e772f91cd262c9bb54f877f
Merged origin/dev at 1a9729f96 before the final checks. No push or merge was made.

Built

  • Replaced local Search control paint with shared Pill actions and TagPill filters in the query field, palette actions, preview actions, saved-search menu trigger, and Tag page Load more action. The existing PillGroup and BlockHoverActions remain untouched.
  • Moved Search palette shell geometry into OverlaySurface, its shared owner.
  • Added the optional ItemCard.gap token API (default stays 6px) so Search result icon alignment no longer styles ItemCard’s private root. Added a unit test and package docs.
  • Refreshed only exact live performance source pins for changed Search files and the inherited TaskColumn pin from origin/dev.

Files

apps/web/src/lib/components/search-dialog.svelte, apps/web/src/lib/search/{SavedSearchList,SearchField,SearchPreview,SearchResultRow}.svelte, apps/web/src/routes/tag/[tag]/+page.svelte, packages/ui/src/components/{ItemCard,OverlaySurface}.svelte, packages/ui/src/components/ItemCard.svelte.test.ts, packages/ui/README.md, and contracts/perf/{registry,adoption-1058,exceptions}.json.

Gates and evidence

cd apps/web && bun run check exited 0:

perf-lint: PASS; 0 violations; 22615 scoped exceptions
svelte-check found 0 errors and 2 warnings in 2 files

The two warnings are empty CSS rules in untouched AttachmentDeck.svelte and AgendaList.svelte.

cd apps/web && bun run test exited 0:

Test Files  283 passed (283)
      Tests  1985 passed (1985)
   Duration  444.44s (transform 29%, environment 27%, import 23%, tests 15%, setup 5%)

bun run build exited 0. The real-server Search review passed with macOS platform signals and no CSP reports:

PASS #1093 row labels, focus edge and preview action bounds across the four review themes
CSP REPORTS search: 0 across 2 pages

Tag page screenshots were captured from the real-server production build. Search palette/preview and Tag page captures cover 390, 820, and 1440 px at 1× and 2×, light and dark; Search captures emulate macOS. Artifacts are in ignored artifacts/restyle-search/ (97 PNGs total). Saved-search sidebar captures are partial: 1× light at all widths and 1× dark at desktop. A repeated saved-sidebar capture hit a Playwright navigation race at tablet width.

cargo build -p calternal-server was used only to run the local screenshot server. No Rust source changed, so Rust fmt/clippy/test crate gates were not applicable. Cleanup output:

Removed 8648 files, 7.3GiB total

UX gaps and known gaps

  • Closed: visible Search actions now use shared controls; Search result spacing uses a shared API; the Search palette no longer reaches into OverlaySurface with feature-level shell selectors. The #1093 run checked row names, focus edge, preview action bounds, and the 44px touch preview path.
  • Left: one #1123/#1137 screenshot run timed out while waiting for the sticky top-edge blur after scrolling the atlas results at 1440px mono. The #1093 production review passed on retry. Rerun SEARCH_E2E_MACOS=1 SEARCH_E2E_1123_ONLY=1 bun e2e/search.mjs --screenshots artifacts/restyle-search/merge-round in the merge round to verify that scroll state.
  • The Forgejo fj issue comment CLI accepts text and --body-file but has no file-attachment option. Screenshots remain in the ignored local artifact directory and are not attached to this comment.
  • The audit file named in the brief (artifacts/restyle-audit.md) was absent in this worktree; I used the Search inventory posted in the issue comments.

Decisions not spelled out in DESIGN.md

  • Put Search shell geometry in OverlaySurface because it owns the surface, while leaving Search body layout in Search.
  • Add a narrow ItemCard.gap property for host alignment. It uses a private CSS variable internally and preserves the existing default.
  • Use TagPill for colored tag filters and generic Pill for other Search controls. No new control variant was needed.
  • No benchmark profile was added: this is a control/surface restyle with no new user operation or IO path. Existing virtualized result rendering remains in place.

Commits

  • 3c9dd62c8 expose shared Search surface alignment tokens
  • 549ca713d use shared controls in the Search palette
  • f1a3529df use shared actions in Search results
  • 18b791864 refresh exact Search source pins
## #1190 Search restyle — complete Branch: `job/restyle-search` Head: `18b791864eebcc8d7e772f91cd262c9bb54f877f` Merged `origin/dev` at `1a9729f96` before the final checks. No push or merge was made. ### Built - Replaced local Search control paint with shared `Pill` actions and `TagPill` filters in the query field, palette actions, preview actions, saved-search menu trigger, and Tag page Load more action. The existing `PillGroup` and `BlockHoverActions` remain untouched. - Moved Search palette shell geometry into `OverlaySurface`, its shared owner. - Added the optional `ItemCard.gap` token API (default stays 6px) so Search result icon alignment no longer styles ItemCard’s private root. Added a unit test and package docs. - Refreshed only exact live performance source pins for changed Search files and the inherited `TaskColumn` pin from `origin/dev`. ### Files `apps/web/src/lib/components/search-dialog.svelte`, `apps/web/src/lib/search/{SavedSearchList,SearchField,SearchPreview,SearchResultRow}.svelte`, `apps/web/src/routes/tag/[tag]/+page.svelte`, `packages/ui/src/components/{ItemCard,OverlaySurface}.svelte`, `packages/ui/src/components/ItemCard.svelte.test.ts`, `packages/ui/README.md`, and `contracts/perf/{registry,adoption-1058,exceptions}.json`. ### Gates and evidence `cd apps/web && bun run check` exited 0: ```text perf-lint: PASS; 0 violations; 22615 scoped exceptions svelte-check found 0 errors and 2 warnings in 2 files ``` The two warnings are empty CSS rules in untouched `AttachmentDeck.svelte` and `AgendaList.svelte`. `cd apps/web && bun run test` exited 0: ```text Test Files 283 passed (283) Tests 1985 passed (1985) Duration 444.44s (transform 29%, environment 27%, import 23%, tests 15%, setup 5%) ``` `bun run build` exited 0. The real-server Search review passed with macOS platform signals and no CSP reports: ```text PASS #1093 row labels, focus edge and preview action bounds across the four review themes CSP REPORTS search: 0 across 2 pages ``` Tag page screenshots were captured from the real-server production build. Search palette/preview and Tag page captures cover 390, 820, and 1440 px at 1× and 2×, light and dark; Search captures emulate macOS. Artifacts are in ignored `artifacts/restyle-search/` (97 PNGs total). Saved-search sidebar captures are partial: 1× light at all widths and 1× dark at desktop. A repeated saved-sidebar capture hit a Playwright navigation race at tablet width. `cargo build -p calternal-server` was used only to run the local screenshot server. No Rust source changed, so Rust fmt/clippy/test crate gates were not applicable. Cleanup output: ```text Removed 8648 files, 7.3GiB total ``` ### UX gaps and known gaps - Closed: visible Search actions now use shared controls; Search result spacing uses a shared API; the Search palette no longer reaches into `OverlaySurface` with feature-level shell selectors. The #1093 run checked row names, focus edge, preview action bounds, and the 44px touch preview path. - Left: one #1123/#1137 screenshot run timed out while waiting for the sticky top-edge blur after scrolling the `atlas` results at 1440px mono. The #1093 production review passed on retry. Rerun `SEARCH_E2E_MACOS=1 SEARCH_E2E_1123_ONLY=1 bun e2e/search.mjs --screenshots artifacts/restyle-search/merge-round` in the merge round to verify that scroll state. - The Forgejo `fj issue comment` CLI accepts text and `--body-file` but has no file-attachment option. Screenshots remain in the ignored local artifact directory and are not attached to this comment. - The audit file named in the brief (`artifacts/restyle-audit.md`) was absent in this worktree; I used the Search inventory posted in the issue comments. ### Decisions not spelled out in DESIGN.md - Put Search shell geometry in `OverlaySurface` because it owns the surface, while leaving Search body layout in Search. - Add a narrow `ItemCard.gap` property for host alignment. It uses a private CSS variable internally and preserves the existing default. - Use `TagPill` for colored tag filters and generic `Pill` for other Search controls. No new control variant was needed. - No benchmark profile was added: this is a control/surface restyle with no new user operation or IO path. Existing virtualized result rendering remains in place. ### Commits - `3c9dd62c8` expose shared Search surface alignment tokens - `549ca713d` use shared controls in the Search palette - `f1a3529df` use shared actions in Search results - `18b791864` refresh exact Search source pins
Author
Owner

Files+Photos capture finding: the existing Photos Backgrounds retry screenshot helper captures the error state, clicks Retry, then waits for a link named “Open camera”. Its screenshot fixture is “Restyle background.jpg”, so that stale locator times out before the matrix completes. I left the existing expectation unchanged. A separate production-build run captured all six before variants and verified Retry loads the actual “Open Restyle background.jpg” item. The after matrix is running now.

Files+Photos capture finding: the existing Photos Backgrounds retry screenshot helper captures the error state, clicks Retry, then waits for a link named “Open camera”. Its screenshot fixture is “Restyle background.jpg”, so that stale locator times out before the matrix completes. I left the existing expectation unchanged. A separate production-build run captured all six before variants and verified Retry loads the actual “Open Restyle background.jpg” item. The after matrix is running now.
Author
Owner

Post-merge finding on daa684c60: bun run test reports one failure in src/lib/themes.test.ts: “uses the overlay alpha for every page card and one more opaque shared inner tile role.” The test still requires the glass default markup class="card glass-card {cls}" at apps/web/src/lib/themes.test.ts:530. The Settings extension changed that root class to a conditional expression. I will keep the test unchanged and preserve the original glass class while applying the solid state as a separate shared class binding.

Post-merge finding on `daa684c60`: `bun run test` reports one failure in `src/lib/themes.test.ts`: “uses the overlay alpha for every page card and one more opaque shared inner tile role.” The test still requires the glass default markup `class="card glass-card {cls}"` at `apps/web/src/lib/themes.test.ts:530`. The Settings extension changed that root class to a conditional expression. I will keep the test unchanged and preserve the original glass class while applying the solid state as a separate shared class binding.
Author
Owner

Files+Photos restyle is complete.

Head SHA: 304a9bdd82ad0e5734fa76ababf7be27b2b92bef

Built

  • Files Browser, pinned rows, Inspector, Share dialog, Shared by You, Public link, and UploadToast now use shared Card, Pill, OverlaySurface, CopyLink, and FileThumb components for their visible surfaces and actions.
  • Photos empty state, key-photo action, Backgrounds Retry, and file-drop preview use shared Pill and Card components. Existing SegmentedControl, PillGroup, and single-choice selectors were not changed.
  • Card owns fixed-preview fill and drag-preview geometry. Pill owns row, text, media, and full-width action geometry. No feature-local overlays or primitive styling remain for the audited surfaces.
  • The Share screenshot helper masks public-link URLs. These links are bearer capabilities, so they must not appear in issue images.

Screenshots

I attached 133 production-build PNGs to this issue: 66 before and 67 after. They cover every changed surface at 390, 820, and 1440 CSS pixels in light and dark. Phone and tablet captures use 2× output; desktop captures use 1× output. Browser contexts emulate macOS. One extra after image is a duplicate phone-light UploadToast capture.

The Backgrounds Retry capture helper has an old post-click locator. It waits for “Open camera” although its fixture is “Restyle background.jpg.” I left that existing expectation unchanged. A separate production-build capture produced all six before and six after images and verified that Retry loads “Open Restyle background.jpg.” This is a test-helper gap, not a product UX gap.

UX gaps closed / left

Closed: shared controls keep keyboard focus, button semantics, shortcut tooltips, and the shared touch hit floor. Retry was exercised against a real server item. The restyled surfaces keep their existing API, stable-link, and edit paths.

Left: the stale settings-effects.mjs --restyle-retry-screenshots-only locator still times out after its first screenshot. The full visual matrix and Retry behavior were verified with the separate production-build capture.

Expected cost: this is a presentation change. It adds no route, API call, background work, or per-item data operation.

Decisions not specified in DESIGN

  • Use --sidebar-row-weight for shared Pill rows so Files pins keep their existing text weight after their local styling is removed.
  • Use Card’s fill prop when its parent fixes the preview size; this keeps sizing in the shared primitive without layout measurement.
  • Mask public-link URLs in issue screenshots because the URL grants access.

Gates

cd apps/web && bun run check

PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages
perf-lint: PASS; 0 violations; 22615 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
svelte-check found 0 errors and 0 warnings

cd apps/web && bun run test

 Test Files  283 passed (283)
      Tests  1990 passed (1990)
   Start at  19:58:18
   Duration  280.88s (environment 29%, transform 26%, import 23%, tests 16%, setup 5%)

Focused shared-component checks:

 Test Files  5 passed (5)
      Tests  97 passed (97)

Screenshot runs passed for Share (SHARE RESTYLE SCREENSHOTS PASSED; CSP reports: 0 across 2 pages), Inspector (INFO_INSPECTOR_RESTYLE_SCREENSHOTS PASSED), and UploadToast (FILES UPLOAD TOAST RESTYLE SCREENSHOTS PASSED; CSP reports: 0 across 7 pages). Backgrounds Retry passed in the separate capture run.

cargo build -p calternal-server passed to prepare the local screenshot server; no Rust source changed, so Rust crate gates did not apply. Final cleanup: Removed 8648 files, 7.3GiB total.

No push, deploy, or merge was performed by this job. The required origin/dev merge is in the branch history.

Files+Photos restyle is complete. Head SHA: `304a9bdd82ad0e5734fa76ababf7be27b2b92bef` ## Built - Files Browser, pinned rows, Inspector, Share dialog, Shared by You, Public link, and UploadToast now use shared Card, Pill, OverlaySurface, CopyLink, and FileThumb components for their visible surfaces and actions. - Photos empty state, key-photo action, Backgrounds Retry, and file-drop preview use shared Pill and Card components. Existing SegmentedControl, PillGroup, and single-choice selectors were not changed. - Card owns fixed-preview fill and drag-preview geometry. Pill owns row, text, media, and full-width action geometry. No feature-local overlays or primitive styling remain for the audited surfaces. - The Share screenshot helper masks public-link URLs. These links are bearer capabilities, so they must not appear in issue images. ## Screenshots I attached 133 production-build PNGs to this issue: 66 before and 67 after. They cover every changed surface at 390, 820, and 1440 CSS pixels in light and dark. Phone and tablet captures use 2× output; desktop captures use 1× output. Browser contexts emulate macOS. One extra after image is a duplicate phone-light UploadToast capture. The Backgrounds Retry capture helper has an old post-click locator. It waits for “Open camera” although its fixture is “Restyle background.jpg.” I left that existing expectation unchanged. A separate production-build capture produced all six before and six after images and verified that Retry loads “Open Restyle background.jpg.” This is a test-helper gap, not a product UX gap. ## UX gaps closed / left Closed: shared controls keep keyboard focus, button semantics, shortcut tooltips, and the shared touch hit floor. Retry was exercised against a real server item. The restyled surfaces keep their existing API, stable-link, and edit paths. Left: the stale `settings-effects.mjs --restyle-retry-screenshots-only` locator still times out after its first screenshot. The full visual matrix and Retry behavior were verified with the separate production-build capture. Expected cost: this is a presentation change. It adds no route, API call, background work, or per-item data operation. ## Decisions not specified in DESIGN - Use `--sidebar-row-weight` for shared Pill rows so Files pins keep their existing text weight after their local styling is removed. - Use Card’s `fill` prop when its parent fixes the preview size; this keeps sizing in the shared primitive without layout measurement. - Mask public-link URLs in issue screenshots because the URL grants access. ## Gates `cd apps/web && bun run check` ```text PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages perf-lint: PASS; 0 violations; 22615 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. svelte-check found 0 errors and 0 warnings ``` `cd apps/web && bun run test` ```text Test Files 283 passed (283) Tests 1990 passed (1990) Start at 19:58:18 Duration 280.88s (environment 29%, transform 26%, import 23%, tests 16%, setup 5%) ``` Focused shared-component checks: ```text Test Files 5 passed (5) Tests 97 passed (97) ``` Screenshot runs passed for Share (`SHARE RESTYLE SCREENSHOTS PASSED`; CSP reports: 0 across 2 pages), Inspector (`INFO_INSPECTOR_RESTYLE_SCREENSHOTS PASSED`), and UploadToast (`FILES UPLOAD TOAST RESTYLE SCREENSHOTS PASSED`; CSP reports: 0 across 7 pages). Backgrounds Retry passed in the separate capture run. `cargo build -p calternal-server` passed to prepare the local screenshot server; no Rust source changed, so Rust crate gates did not apply. Final cleanup: `Removed 8648 files, 7.3GiB total`. No push, deploy, or merge was performed by this job. The required `origin/dev` merge is in the branch history.
Author
Owner

Report correction and merge note: this job did perform the required local merge of origin/dev in commit bb55b9cc743b45915e43bb98b3e9ff3e9fb1c942 before final gates. It did not push, deploy, or merge into dev or `main.

After that merge, the perf source pins were refreshed by changing only exact hashes for existing entries; rules, limits, scopes, and the total count did not change. The full web check also found two empty focus CSS blocks in shared Calendar components. I removed those empty blocks so the required check could pass; they had no declarations and no rendered effect. These are the only out-of-area source files touched for the gate.

Report correction and merge note: this job did perform the required local merge of `origin/dev` in commit `bb55b9cc743b45915e43bb98b3e9ff3e9fb1c942` before final gates. It did not push, deploy, or merge into `dev` or `main. After that merge, the perf source pins were refreshed by changing only exact hashes for existing entries; rules, limits, scopes, and the total count did not change. The full web check also found two empty focus CSS blocks in shared Calendar components. I removed those empty blocks so the required check could pass; they had no declarations and no rendered effect. These are the only out-of-area source files touched for the gate.
Author
Owner

#1190 final report — Settings restyle

State: implementation committed; final verification is incomplete. Issue remains open. No push or deploy.

Head: 08b8c7ad1fc2d0fa9ba1e25350de6a06ea0ec534

What changed

Settings cards, actions, status badges, overlays, upload targets, and toggle rows now use the shared UI components and tokens. The shared Card, Pill, StatusPill, and OverlaySurface gained small additive variants for the missing solid, compact, drop-target, dialog-size, and Settings-sheet treatments. The default glass Card class remains stable for existing theme checks. Exact performance pins were refreshed after syncing current origin/dev; no new exception scopes, limits, or ratchet counts were added.

There are no new routes, API operations, background jobs, filesystem calls, or scans. Expected work per Settings action is unchanged; this change adds no IO.

Files

  • Auth: apps/web/src/lib/auth/components/{AuthCard,CreateAccountFlow,RecoverFlow,RecoveryKeyEntry,RecoveryKeyWords}.svelte, apps/web/src/lib/styles/auth-ui.css
  • Settings: apps/web/src/routes/settings/[...path]/+page.svelte; account/{AppPasswordsGroup,RecoveryKeySheet}.svelte; admin/SignInGroup.svelte; appearance/{BackgroundGroup,UnsplashSheet}.svelte; apps/CalendarFeedsGroup.svelte; connected-accounts/ConnectedAccountsSection.svelte; jobs/{JobDetails,MyJobsGroup}.svelte; notifications/NotificationsSection.svelte; parts/{RowAction,SettingsCard,StateChip}.svelte, parts/settings-forms.css; plugins/PluginsSection.svelte; voice/VoiceSection.svelte
  • Shared UI and tests: packages/ui/src/components/{Card,OverlaySurface,Pill,StatusPill}.svelte, packages/ui/src/tokens.css, packages/ui/README.md; apps/web/src/lib/components/{Card,OverlaySurface,Pill,StatusPill}.svelte.test.ts; apps/web/src/routes/settings/parts/{ActionPills.svelte.test.ts,SettingsCard.svelte.test.ts}
  • Performance pins: contracts/perf/{registry.json,exceptions.json,adoption-1058.json}

The merge commit daa684c60 syncs current origin/dev; it also includes upstream files outside this issue’s owned area.

UX gaps closed

  • Replaced feature-local card paint, pill styles, and status shells with shared component variants.
  • Kept the upload target keyboard and touch activation on a real button.
  • Preserved shared focus, spacing, state, and motion roles while removing local overrides.

UX gaps left: no interaction gap was found in the captured flows. The final post-merge production screenshots and a complete passing post-fix bun run test run remain outstanding. The visual reviewer has not reviewed a post-merge capture.

Screenshots

The attached before/after archives contain the 17-surface matrix at phone 390, tablet 820, and desktop 1440; 1× and 2×; light and dark; with macOS platform emulation. They were captured before the final origin/dev sync. Local matrix validation found 204 PNGs per side, all dimensions correct, with no missing combinations. The merged production build was not recaptured before the job exceeded its four-hour limit.

Gates

bun run check exited 0 on the merged tree before the final Card class-binding fix:

PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages
perf-lint: PASS; 0 violations; 22615 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
svelte-check found 0 errors and 2 warnings in 2 files

The two warnings are existing empty focus rules in packages/ui/src/components/calendar/AttachmentDeck.svelte and AgendaList.svelte.

The first post-merge full bun run test run caught the Card class contract below. The component now preserves the tested glass class and the focused regression tests pass. The full suite was not rerun after that fix:

Test Files  1 failed | 283 passed (284)
      Tests  1 failed | 1993 passed (1994)
   Start at  20:14:04
   Duration  822.10s (transform 35%, environment 24%, import 23%, tests 13%, setup 5%)
error: script "test" exited with code 1

The failure was themes.test.ts:530, which expected class="card glass-card {cls}". After the fix:

 Test Files  2 passed (2)
      Tests  85 passed (85)
   Start at 20:29:44
   Duration 67.70s (transform 82%, tests 11%, import 5%, environment 2%, setup 1%)

cargo clean output: Removed 0 files. No Rust files differ from current origin/dev, so Rust crate gates were not run. Web build output was removed. Working tree is clean.

Decisions not specified by DESIGN

  • Added Card.material="solid", flatOnSheet, and dropTarget to keep auth, Settings, and upload material inside the shared owner.
  • Added OverlaySurface.dialogSize and sheetChrome="settings" for the Settings presentation.
  • Added compact StatusPill sizing and reused shared Pill tones/shapes for Settings actions and states.

Remaining verification

  • Rerun bun run check and bun run test on 08b8c7ad1 after the Card class-binding fix.
  • Capture and attach the production screenshot matrix from the merged tree.
  • Complete visual review of that post-merge matrix.
## #1190 final report — Settings restyle **State:** implementation committed; final verification is incomplete. Issue remains open. No push or deploy. **Head:** `08b8c7ad1fc2d0fa9ba1e25350de6a06ea0ec534` ### What changed Settings cards, actions, status badges, overlays, upload targets, and toggle rows now use the shared UI components and tokens. The shared `Card`, `Pill`, `StatusPill`, and `OverlaySurface` gained small additive variants for the missing solid, compact, drop-target, dialog-size, and Settings-sheet treatments. The default glass Card class remains stable for existing theme checks. Exact performance pins were refreshed after syncing current `origin/dev`; no new exception scopes, limits, or ratchet counts were added. There are no new routes, API operations, background jobs, filesystem calls, or scans. Expected work per Settings action is unchanged; this change adds no IO. ### Files - Auth: `apps/web/src/lib/auth/components/{AuthCard,CreateAccountFlow,RecoverFlow,RecoveryKeyEntry,RecoveryKeyWords}.svelte`, `apps/web/src/lib/styles/auth-ui.css` - Settings: `apps/web/src/routes/settings/[...path]/+page.svelte`; `account/{AppPasswordsGroup,RecoveryKeySheet}.svelte`; `admin/SignInGroup.svelte`; `appearance/{BackgroundGroup,UnsplashSheet}.svelte`; `apps/CalendarFeedsGroup.svelte`; `connected-accounts/ConnectedAccountsSection.svelte`; `jobs/{JobDetails,MyJobsGroup}.svelte`; `notifications/NotificationsSection.svelte`; `parts/{RowAction,SettingsCard,StateChip}.svelte`, `parts/settings-forms.css`; `plugins/PluginsSection.svelte`; `voice/VoiceSection.svelte` - Shared UI and tests: `packages/ui/src/components/{Card,OverlaySurface,Pill,StatusPill}.svelte`, `packages/ui/src/tokens.css`, `packages/ui/README.md`; `apps/web/src/lib/components/{Card,OverlaySurface,Pill,StatusPill}.svelte.test.ts`; `apps/web/src/routes/settings/parts/{ActionPills.svelte.test.ts,SettingsCard.svelte.test.ts}` - Performance pins: `contracts/perf/{registry.json,exceptions.json,adoption-1058.json}` The merge commit `daa684c60` syncs current `origin/dev`; it also includes upstream files outside this issue’s owned area. ### UX gaps closed - Replaced feature-local card paint, pill styles, and status shells with shared component variants. - Kept the upload target keyboard and touch activation on a real button. - Preserved shared focus, spacing, state, and motion roles while removing local overrides. **UX gaps left:** no interaction gap was found in the captured flows. The final post-merge production screenshots and a complete passing post-fix `bun run test` run remain outstanding. The visual reviewer has not reviewed a post-merge capture. ### Screenshots The attached before/after archives contain the 17-surface matrix at phone 390, tablet 820, and desktop 1440; 1× and 2×; light and dark; with macOS platform emulation. They were captured before the final `origin/dev` sync. Local matrix validation found 204 PNGs per side, all dimensions correct, with no missing combinations. The merged production build was not recaptured before the job exceeded its four-hour limit. - Auth login: [archive](https://git.kayg.org/attachments/ac5438ee-ae37-4e16-9cc4-0b4e2bcf1566) - Auth recovery entry: [archive](https://git.kayg.org/attachments/89b926a4-4f30-45be-9322-5f566cff4be2) - Auth setup: [archive](https://git.kayg.org/attachments/0d63bf6a-74ce-446a-aaf2-7684e3c36486) - Admin sign-in: [archive](https://git.kayg.org/attachments/307d0780-1016-4bd3-9720-d8f841143966) - App passwords: [archive](https://git.kayg.org/attachments/3ef55671-72c4-4abd-8293-3fc8ac8e7947) - Background upload: [archive](https://git.kayg.org/attachments/b43e600f-7c63-40ab-bca3-d710852f542e) - Background work: [archive](https://git.kayg.org/attachments/2b348c1d-0640-47b3-aaab-939210bd3115) - Calendar feeds: [archive](https://git.kayg.org/attachments/4faddce9-7907-493e-9ccc-a88926a84ea2) - Connected accounts: [archive](https://git.kayg.org/attachments/96fc87e2-ce35-48ac-8c3e-c954d517a9cf) - Notifications: [archive](https://git.kayg.org/attachments/642430bc-64e5-4484-862d-90f6162e6365) - Plugins: [archive](https://git.kayg.org/attachments/e075d333-2a8e-42c1-924c-97418ad13f6b) - Recovery key: [archive](https://git.kayg.org/attachments/a622ca55-324d-46d9-abf1-bd55a019db75) - Voice models: [archive](https://git.kayg.org/attachments/d402de99-2724-4895-936f-12e783e17052) ### Gates `bun run check` exited 0 on the merged tree before the final Card class-binding fix: ```text PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages perf-lint: PASS; 0 violations; 22615 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. svelte-check found 0 errors and 2 warnings in 2 files ``` The two warnings are existing empty focus rules in `packages/ui/src/components/calendar/AttachmentDeck.svelte` and `AgendaList.svelte`. The first post-merge full `bun run test` run caught the Card class contract below. The component now preserves the tested glass class and the focused regression tests pass. The full suite was not rerun after that fix: ```text Test Files 1 failed | 283 passed (284) Tests 1 failed | 1993 passed (1994) Start at 20:14:04 Duration 822.10s (transform 35%, environment 24%, import 23%, tests 13%, setup 5%) error: script "test" exited with code 1 ``` The failure was `themes.test.ts:530`, which expected `class="card glass-card {cls}"`. After the fix: ```text Test Files 2 passed (2) Tests 85 passed (85) Start at 20:29:44 Duration 67.70s (transform 82%, tests 11%, import 5%, environment 2%, setup 1%) ``` `cargo clean` output: `Removed 0 files`. No Rust files differ from current `origin/dev`, so Rust crate gates were not run. Web build output was removed. Working tree is clean. ### Decisions not specified by DESIGN - Added `Card.material="solid"`, `flatOnSheet`, and `dropTarget` to keep auth, Settings, and upload material inside the shared owner. - Added `OverlaySurface.dialogSize` and `sheetChrome="settings"` for the Settings presentation. - Added compact `StatusPill` sizing and reused shared Pill tones/shapes for Settings actions and states. ### Remaining verification - Rerun `bun run check` and `bun run test` on `08b8c7ad1` after the Card class-binding fix. - Capture and attach the production screenshot matrix from the merged tree. - Complete visual review of that post-merge matrix.
Author
Owner

Progress update for #1190

The Calendar, Mail, Money, and Agenda before/after screenshot matrices are captured from production builds. Each area has 1x and 2x PNGs in light and dark at 390, 820, and 1440 CSS pixels. I am attaching the archives after upload checks.

Two test-contract regressions found during the web suite were fixed without changing old expectations: Pill now preserves exact child text, and Card keeps the existing glass-card/overlay source contracts mutually exclusive. Focused verification passed: 4 files, 103 tests.

Final web check output: perf-lint: PASS; 0 violations; 22615 scoped exceptions; svelte-check found 0 errors and 4 warnings in 2 files (existing AgendaList empty ruleset and MailView unused swipe selectors).

Full bun run test result on the shared host: Test Files 2 failed | 282 passed (284) and Tests 2 failed | 1994 passed (1996). The unchanged failures were KeyboardShortcutsCard.svelte.test.ts timing out in 5 seconds and SettingsCard.svelte.test.ts expecting .touch-feedback; both passed when run focused: 2 files, 5 tests. I left those tests and their expectations unchanged.

Progress update for #1190 The Calendar, Mail, Money, and Agenda before/after screenshot matrices are captured from production builds. Each area has 1x and 2x PNGs in light and dark at 390, 820, and 1440 CSS pixels. I am attaching the archives after upload checks. Two test-contract regressions found during the web suite were fixed without changing old expectations: Pill now preserves exact child text, and Card keeps the existing glass-card/overlay source contracts mutually exclusive. Focused verification passed: 4 files, 103 tests. Final web check output: `perf-lint: PASS; 0 violations; 22615 scoped exceptions`; `svelte-check found 0 errors and 4 warnings in 2 files` (existing AgendaList empty ruleset and MailView unused swipe selectors). Full `bun run test` result on the shared host: `Test Files 2 failed | 282 passed (284)` and `Tests 2 failed | 1994 passed (1996)`. The unchanged failures were `KeyboardShortcutsCard.svelte.test.ts` timing out in 5 seconds and `SettingsCard.svelte.test.ts` expecting `.touch-feedback`; both passed when run focused: 2 files, 5 tests. I left those tests and their expectations unchanged.
Author
Owner

Starting #1190 on branch job/restyle-search, continuing from head 18b791864eebcc8d7e772f91cd262c9bb54f877f.

Starting #1190 on branch `job/restyle-search`, continuing from head `18b791864eebcc8d7e772f91cd262c9bb54f877f`.
Author
Owner

Inspection findings for #1190:

  • apps/web/src/lib/components/search-dialog.svelte overrides --glass-tray-wash for the shared ProgressiveBlur; its Search-only wash paints an opaque --surface stop. I will remove the override and use the shared filter-only edge blur.
  • apps/web/src/lib/search/SearchResultRow.svelte places navigation descriptions in the inline .meta slot. I will keep Navigate rows title-only, matching the other navigation results.
  • apps/web/src/lib/search/SavedSearchList.svelte already opens its menu on right-click, Shift+F10 / ContextMenu, and the shared touch long-press gesture, but always renders the ⋯ button. I will hide that button for fine pointers and cover the menu paths in e2e.
Inspection findings for #1190: - `apps/web/src/lib/components/search-dialog.svelte` overrides `--glass-tray-wash` for the shared `ProgressiveBlur`; its Search-only wash paints an opaque `--surface` stop. I will remove the override and use the shared filter-only edge blur. - `apps/web/src/lib/search/SearchResultRow.svelte` places `navigation` descriptions in the inline `.meta` slot. I will keep Navigate rows title-only, matching the other navigation results. - `apps/web/src/lib/search/SavedSearchList.svelte` already opens its menu on right-click, Shift+F10 / ContextMenu, and the shared touch long-press gesture, but always renders the ⋯ button. I will hide that button for fine pointers and cover the menu paths in e2e.
Author
Owner

#1190 Calendar + Mail + Money restyle report

Area completed: Calendar + Mail + Money. Head SHA: 9f2a4fd6c2ac32247097df51dcac91c07bc7e84e.

Built

  • Calendar uses shared Pill for date heat cells, time-grid actions and task chips; shared Checkbox owns Task hit geometry; shared Card owns ActivityStack layer materials. Removed local primitive styling in the Calendar surfaces covered by this pass.
  • Mail uses shared Card for the reader overlay material and shared Pill for view actions.
  • Money uses shared Card for forms and shared Pill for register state and row actions.
  • Added small additive Card, Pill and Checkbox API extensions with tests and package documentation. Updated exact perf pins for the changed styles.
  • Screenshot evidence is attached below. All sets are before/after production builds, emulate macOS, and cover light and dark at 390, 820 and 1440 CSS pixels at actual 1x and 2x density.

Files

  • App surfaces: apps/web/src/lib/mail/MailMorphCard.svelte, apps/web/src/lib/mail/MailView.svelte, apps/web/src/routes/calendar/[view]/[date]/+page.svelte, apps/web/src/routes/money/[budget]/[month]/+page.svelte, apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte.
  • Shared UI: packages/ui/src/components/{Card,Checkbox,Pill}.svelte, packages/ui/src/components/calendar/{ActivityStack,AttachmentDeck,TaskCheckbox,TimeGrid,YearHeatmap}.svelte, packages/ui/src/tokens.css, packages/ui/README.md.
  • Tests and evidence helpers: apps/web/src/lib/components/{Card,Checkbox,Pill}.svelte.test.ts, apps/web/e2e/{agenda-decks-822,calendar,mail-layouts,money}.mjs, tests/adversarial/mail_screenshot_fixture.py.
  • Exact perf pin data: contracts/perf/{adoption-1058,exceptions,registry}.json.

UX gaps closed / left

  • Closed: date-cell states and event/photo markers now share one control; Task completion has a shared 44 px target; Calendar preview cards use shared Card material and elevation; Mail view actions and Money register actions use shared Pill behavior; Money form surfaces use Card.
  • Left: the full Web test suite still fails two tests outside these files: KeyboardShortcutsCard.svelte.test.ts > puts the current view group first and closes with Escape timed out at 5000 ms, and SettingsCard.svelte.test.ts > copies the group link after a touch double-tap failed on .touch-feedback. Their focused rerun passed.
  • Left: the full Mail layout E2E reaches the screenshot capture, then times out waiting for its prepared-reader image probe. The original Calendar header runner stopped after phone captures at #tab-calendar[aria-selected=true]; the original Money runner hit a /money/import route mismatch; the original Agenda deck runner failed its fan assertion. Separate capture-only runs completed the required screenshot matrices. These interaction probes need follow-up in their owning test work.

Decisions

  • The design rules did not prescribe exact shared prop names for these states. Kept extensions additive: Card owns surface material/tint/elevation and layout props; Pill owns square Calendar cells and shared semantic action states; Checkbox owns configurable hit size. PillGroup, BlockHoverActions, segmented controls and single-choice selectors were left untouched.
  • The design-rule guard has no named per-area allow-list; it compares modified feature code with origin/dev. The restyle removes the local overrides without changing that guard.

Verification output

bun run check — exit 0:

perf-lint: PASS; 0 violations; 22615 scoped exceptions
svelte-check found 0 errors and 4 warnings in 2 files

bun run test — exit 1:

Test Files  2 failed | 282 passed (284)
Tests  2 failed | 1994 passed (1996)

Focused rerun of the two failing files — exit 0:

Test Files 2 passed (2)
Tests 5 passed (5)

bun run build succeeded. No Rust code changed, so Rust crate gates were not run. cargo clean:

Removed 8633 files, 7.3GiB total

git diff --check passed; worktree is clean. No push, deploy or merge was made.

Screenshot attachments

# #1190 Calendar + Mail + Money restyle report Area completed: Calendar + Mail + Money. Head SHA: `9f2a4fd6c2ac32247097df51dcac91c07bc7e84e`. ## Built - Calendar uses shared `Pill` for date heat cells, time-grid actions and task chips; shared `Checkbox` owns Task hit geometry; shared `Card` owns ActivityStack layer materials. Removed local primitive styling in the Calendar surfaces covered by this pass. - Mail uses shared `Card` for the reader overlay material and shared `Pill` for view actions. - Money uses shared `Card` for forms and shared `Pill` for register state and row actions. - Added small additive `Card`, `Pill` and `Checkbox` API extensions with tests and package documentation. Updated exact perf pins for the changed styles. - Screenshot evidence is attached below. All sets are before/after production builds, emulate macOS, and cover light and dark at 390, 820 and 1440 CSS pixels at actual 1x and 2x density. ## Files - App surfaces: `apps/web/src/lib/mail/MailMorphCard.svelte`, `apps/web/src/lib/mail/MailView.svelte`, `apps/web/src/routes/calendar/[view]/[date]/+page.svelte`, `apps/web/src/routes/money/[budget]/[month]/+page.svelte`, `apps/web/src/routes/money/[budget]/accounts/[[account]]/+page.svelte`. - Shared UI: `packages/ui/src/components/{Card,Checkbox,Pill}.svelte`, `packages/ui/src/components/calendar/{ActivityStack,AttachmentDeck,TaskCheckbox,TimeGrid,YearHeatmap}.svelte`, `packages/ui/src/tokens.css`, `packages/ui/README.md`. - Tests and evidence helpers: `apps/web/src/lib/components/{Card,Checkbox,Pill}.svelte.test.ts`, `apps/web/e2e/{agenda-decks-822,calendar,mail-layouts,money}.mjs`, `tests/adversarial/mail_screenshot_fixture.py`. - Exact perf pin data: `contracts/perf/{adoption-1058,exceptions,registry}.json`. ## UX gaps closed / left - Closed: date-cell states and event/photo markers now share one control; Task completion has a shared 44 px target; Calendar preview cards use shared Card material and elevation; Mail view actions and Money register actions use shared Pill behavior; Money form surfaces use Card. - Left: the full Web test suite still fails two tests outside these files: `KeyboardShortcutsCard.svelte.test.ts > puts the current view group first and closes with Escape` timed out at 5000 ms, and `SettingsCard.svelte.test.ts > copies the group link after a touch double-tap` failed on `.touch-feedback`. Their focused rerun passed. - Left: the full Mail layout E2E reaches the screenshot capture, then times out waiting for its prepared-reader image probe. The original Calendar header runner stopped after phone captures at `#tab-calendar[aria-selected=true]`; the original Money runner hit a `/money/import` route mismatch; the original Agenda deck runner failed its fan assertion. Separate capture-only runs completed the required screenshot matrices. These interaction probes need follow-up in their owning test work. ## Decisions - The design rules did not prescribe exact shared prop names for these states. Kept extensions additive: `Card` owns surface material/tint/elevation and layout props; `Pill` owns square Calendar cells and shared semantic action states; `Checkbox` owns configurable hit size. `PillGroup`, `BlockHoverActions`, segmented controls and single-choice selectors were left untouched. - The design-rule guard has no named per-area allow-list; it compares modified feature code with `origin/dev`. The restyle removes the local overrides without changing that guard. ## Verification output `bun run check` — exit 0: ``` perf-lint: PASS; 0 violations; 22615 scoped exceptions svelte-check found 0 errors and 4 warnings in 2 files ``` `bun run test` — exit 1: ``` Test Files 2 failed | 282 passed (284) Tests 2 failed | 1994 passed (1996) ``` Focused rerun of the two failing files — exit 0: ``` Test Files 2 passed (2) Tests 5 passed (5) ``` `bun run build` succeeded. No Rust code changed, so Rust crate gates were not run. `cargo clean`: ``` Removed 8633 files, 7.3GiB total ``` `git diff --check` passed; worktree is clean. No push, deploy or merge was made. ## Screenshot attachments - [Manifest](https://git.kayg.org/attachments/33be8a97-c4ce-4c27-85ff-04841be86195) - Mail 1x: https://git.kayg.org/attachments/2f618d31-ed20-4613-9905-c610b4cbf7cc - Mail 2x: https://git.kayg.org/attachments/591f402a-3641-41fb-a9bb-827696cb7b4e - Money 1x: https://git.kayg.org/attachments/a9f79019-6447-4976-89f3-99df54e7b42d - Money 2x: https://git.kayg.org/attachments/c4f59293-a184-4c55-a910-6c10919963e8 - Calendar 1x: https://git.kayg.org/attachments/90c7fa4c-ae64-4e24-adfb-4ac0d015d05e - Calendar 2x: https://git.kayg.org/attachments/9c4e95d2-9406-47e1-b774-e2c77b899702 - Agenda decks 1x: https://git.kayg.org/attachments/b6dc95a1-b998-4a25-a66d-0c9d3e325fc6 - Agenda decks 2x: https://git.kayg.org/attachments/02511d40-2101-4857-a632-ad154a63aba4
Author
Owner

Finding during the required web check: scripts/perf-lint --check rejected three coverage.surfaces adoption checkpoints for apps/web/src/lib/canvas/CanvasView.svelte because their hashes did not match the exact live ledger entries. I updated those three hashes in contracts/perf/adoption-1058.json; the scopes, limits, and ratchet counts did not change. Commit: 07b5f08e46d23dec9530f765c67b820d3012f608. I will rerun the web checks after this correction.

Finding during the required web check: `scripts/perf-lint --check` rejected three `coverage.surfaces` adoption checkpoints for `apps/web/src/lib/canvas/CanvasView.svelte` because their hashes did not match the exact live ledger entries. I updated those three hashes in `contracts/perf/adoption-1058.json`; the scopes, limits, and ratchet counts did not change. Commit: `07b5f08e46d23dec9530f765c67b820d3012f608`. I will rerun the web checks after this correction.
Author
Owner

Finding in the first bun run check: NotesExplorer.svelte used event.currentTarget without narrowing Svelte's nullable EventTarget type, so TypeScript reported two errors on the Notes overflow action. Added an HTMLButtonElement guard and committed it as b4dc163e4ed7b8b9709eec3b3433bec2731bac7d. I am rerunning the required gates on the corrected head.

Finding in the first `bun run check`: `NotesExplorer.svelte` used `event.currentTarget` without narrowing Svelte's nullable `EventTarget` type, so TypeScript reported two errors on the Notes overflow action. Added an `HTMLButtonElement` guard and committed it as `b4dc163e4ed7b8b9709eec3b3433bec2731bac7d`. I am rerunning the required gates on the corrected head.
Author
Owner

The next performance scan found the Notes edits had moved exact source fingerprints in the adopted ledger, including the reminder-picker render.bound entry. I refreshed the changed live entries for the Notes and shared UI files touched by this job with scripts/perf-lint --adopt-7c. The refreshed ledger reports perf-lint: PASS; 0 violations; 22359 scoped exceptions; contracts/perf/ratchet.json did not change. Commit: 8df304af044f9a22faeea779987f63f1c17532dd.

The next performance scan found the Notes edits had moved exact source fingerprints in the adopted ledger, including the reminder-picker `render.bound` entry. I refreshed the changed live entries for the Notes and shared UI files touched by this job with `scripts/perf-lint --adopt-7c`. The refreshed ledger reports `perf-lint: PASS; 0 violations; 22359 scoped exceptions`; `contracts/perf/ratchet.json` did not change. Commit: `8df304af044f9a22faeea779987f63f1c17532dd`.
Author
Owner

Notes audit finding: the design-rule guard detected local CSS selectors reaching into shared Pill roots in NoteContents and NotesExplorer. I replaced the Contents tick positioning with row flex alignment, moved Explorer tree depth into an additive shared Pill rowDepth prop, and use layout slots for the per-row action. The focused Pill test passes (11 tests). The remaining guard findings are four pre-existing native buttons in UploadToast.svelte, an out-of-scope Files surface; I left that file unchanged. The Contents CSS change also moved one exact performance checkpoint, which I am refreshing at the same bound.

Notes audit finding: the design-rule guard detected local CSS selectors reaching into shared Pill roots in NoteContents and NotesExplorer. I replaced the Contents tick positioning with row flex alignment, moved Explorer tree depth into an additive shared Pill `rowDepth` prop, and use layout slots for the per-row action. The focused Pill test passes (11 tests). The remaining guard findings are four pre-existing native buttons in UploadToast.svelte, an out-of-scope Files surface; I left that file unchanged. The Contents CSS change also moved one exact performance checkpoint, which I am refreshing at the same bound.
Author
Owner

Post-merge check finding: merging origin/dev changed the exact source hash for the existing CanvasView render.blaze-adapter checkpoint (CanvasView.svelte#each:3a4cbef6167607e4:1:adapter), so scripts/perf-lint --check reported it unused or changed. This is an upstream checkpoint refresh, not a Notes behavior change. I am updating only the exact pin and keeping the ratchet unchanged.

Post-merge check finding: merging origin/dev changed the exact source hash for the existing CanvasView `render.blaze-adapter` checkpoint (`CanvasView.svelte#each:3a4cbef6167607e4:1:adapter`), so `scripts/perf-lint --check` reported it unused or changed. This is an upstream checkpoint refresh, not a Notes behavior change. I am updating only the exact pin and keeping the ratchet unchanged.
Author
Owner

The first requested #1123 e2e attempt captured search-1123-empty-1440-mono.png and stopped in the new footer assertion. The browser reported footer height 47.109375px and scroll-padding-block-end 47.12px; the assertion reported a zero reserve because parseFloat() cannot read the unresolved calc(...) custom property. I am updating the test to compare the resolved footer min-height with the scroll padding, then rerunning the flow.

The first requested #1123 e2e attempt captured `search-1123-empty-1440-mono.png` and stopped in the new footer assertion. The browser reported footer height `47.109375px` and `scroll-padding-block-end` `47.12px`; the assertion reported a zero reserve because `parseFloat()` cannot read the unresolved `calc(...)` custom property. I am updating the test to compare the resolved footer `min-height` with the scroll padding, then rerunning the flow.
Author
Owner

The targeted production-browser run has captured the specified 1093 desktop Tokyo Night preview and exercised the new last-result path. It found that keyboard selection reaches the final result, but the result does not scroll fully above the footer. The panel reports its scroll-padding reserve; I am adding geometry diagnostics to identify why reveal does not honor it before changing the shared Search behavior.

The targeted production-browser run has captured the specified 1093 desktop Tokyo Night preview and exercised the new last-result path. It found that keyboard selection reaches the final result, but the result does not scroll fully above the footer. The panel reports its scroll-padding reserve; I am adding geometry diagnostics to identify why reveal does not honor it before changing the shared Search behavior.
Author
Owner

Notes restyle complete (#1190)

Head SHA: bdc724847125d1f217845e0b57beac712c36d737

Built

  • Extended shared Pill with rowDepth for hierarchical full-width rows. Added component tests and README guidance.
  • Changed NoteContents rail rows to center their shared tick Pill with flex layout. Removed the feature-level Pill-root positioning selector.
  • Changed NotesExplorer to pass tree depth to Pill and use layout slots for the trailing action. Removed feature-level shared-Pill root overrides and the Notes guard allow-list entries.
  • Refreshed exact Notes and Canvas performance pins after the source updates and origin/dev merge.

Shared controls on these surfaces: Pill renders Contents heading actions, explorer rows and per-Note actions; the phone Contents sheet uses shared OverlaySurface; the explorer section actions use the existing shared PillGroup.

Screenshots

Production-build screenshots use macOS platform emulation. Before/after sets cover both surfaces at 390, 820 and 1440 CSS px, in light and dark, at 1x and 2x. Metadata checks confirmed 1x images match viewport dimensions and 2x images are exactly double. Files are under artifacts/restyle-notes/{before,after}/{1x,2x}/{notes,contents}/.

I also packaged the 48 PNGs into four archives under artifacts/restyle-notes/. The fj CLI has no attachment command, and no usable API credential was available to the upload attempt, so the archives remain local and are not attached to this issue.

UX gaps closed

Removed local styling around shared Pills and kept tree indentation within the shared primitive. Contents ticks now align through the row layout.

UX gaps left

No interaction gaps remain in the changed surfaces. Screenshot archives could not be attached to this issue; their local artifact paths are listed above.

Decisions

DESIGN §34 does not define tree-row indentation values. Pill uses a 1.6rem base inset and adds 0.95rem per rowDepth; the calculation is constant-time per row.

Gates

bun run check:

perf-lint: PASS; 0 violations; 22615 scoped exceptions
svelte-check found 0 errors and 2 warnings in 2 files

The two warnings are existing empty CSS rulesets in AttachmentDeck.svelte:1055 and AgendaList.svelte:1277.

bun run test --maxWorkers=2:

design rules: no new shared primitive overrides or hand-rolled buttons (origin/dev baseline)
Test Files  283 passed (283)
      Tests  1992 passed (1992)
   Duration  962.93s

Focused Pill test: 1 file, 11 tests passed. cargo clean: Removed 8648 files, 7.3GiB total. No Rust source changed, so Rust crate gates were not run.

**Notes restyle complete (#1190)** Head SHA: `bdc724847125d1f217845e0b57beac712c36d737` **Built** - Extended shared `Pill` with `rowDepth` for hierarchical full-width rows. Added component tests and README guidance. - Changed `NoteContents` rail rows to center their shared tick Pill with flex layout. Removed the feature-level Pill-root positioning selector. - Changed `NotesExplorer` to pass tree depth to `Pill` and use layout slots for the trailing action. Removed feature-level shared-Pill root overrides and the Notes guard allow-list entries. - Refreshed exact Notes and Canvas performance pins after the source updates and `origin/dev` merge. Shared controls on these surfaces: `Pill` renders Contents heading actions, explorer rows and per-Note actions; the phone Contents sheet uses shared `OverlaySurface`; the explorer section actions use the existing shared `PillGroup`. **Screenshots** Production-build screenshots use macOS platform emulation. Before/after sets cover both surfaces at 390, 820 and 1440 CSS px, in light and dark, at 1x and 2x. Metadata checks confirmed 1x images match viewport dimensions and 2x images are exactly double. Files are under `artifacts/restyle-notes/{before,after}/{1x,2x}/{notes,contents}/`. I also packaged the 48 PNGs into four archives under `artifacts/restyle-notes/`. The `fj` CLI has no attachment command, and no usable API credential was available to the upload attempt, so the archives remain local and are not attached to this issue. **UX gaps closed** Removed local styling around shared Pills and kept tree indentation within the shared primitive. Contents ticks now align through the row layout. **UX gaps left** No interaction gaps remain in the changed surfaces. Screenshot archives could not be attached to this issue; their local artifact paths are listed above. **Decisions** DESIGN §34 does not define tree-row indentation values. `Pill` uses a 1.6rem base inset and adds 0.95rem per `rowDepth`; the calculation is constant-time per row. **Gates** `bun run check`: ```text perf-lint: PASS; 0 violations; 22615 scoped exceptions svelte-check found 0 errors and 2 warnings in 2 files ``` The two warnings are existing empty CSS rulesets in `AttachmentDeck.svelte:1055` and `AgendaList.svelte:1277`. `bun run test --maxWorkers=2`: ```text design rules: no new shared primitive overrides or hand-rolled buttons (origin/dev baseline) Test Files 283 passed (283) Tests 1992 passed (1992) Duration 962.93s ``` Focused Pill test: 1 file, 11 tests passed. `cargo clean`: `Removed 8648 files, 7.3GiB total`. No Rust source changed, so Rust crate gates were not run.
Author
Owner

Starting the targeted #1190 follow-up on branch job/restyle-files, resuming from 304a9bdd82. I will fix the selected burst thumbnail and shared Quick Look progressive blur, add the browser regression assertion, and capture the requested Photos viewer screenshots.

Starting the targeted #1190 follow-up on branch job/restyle-files, resuming from 304a9bdd82ad0e5734fa76ababf7be27b2b92bef. I will fix the selected burst thumbnail and shared Quick Look progressive blur, add the browser regression assertion, and capture the requested Photos viewer screenshots.
Author
Owner

Starting the Settings phone-sheet correction on job/restyle-settings at 08b8c7ad1, from common base 5301e0208. I will merge job/settingsreg-1195 first, fix the full-height phone sheet and add its 390 px e2e assertion, then recapture every Settings section at 390/820/1440 in light and dark.

Starting the Settings phone-sheet correction on `job/restyle-settings` at `08b8c7ad1`, from common base `5301e0208`. I will merge `job/settingsreg-1195` first, fix the full-height phone sheet and add its 390 px e2e assertion, then recapture every Settings section at 390/820/1440 in light and dark.
Author
Owner

The reviewed artifact artifacts/restyle-files-after/photos-key-photo-action-1440-tokyo-night.png shows the selected fourth burst frame as an empty thumbnail. The strip currently leaves every thumbnail loading="lazy"; selection does not make the current frame eager, so the browser can skip loading it while it is outside the horizontal lazy-load margin. I added eager loading for the selected frame and an e2e check for decoded pixels in every burst thumbnail.

The reviewed artifact `artifacts/restyle-files-after/photos-key-photo-action-1440-tokyo-night.png` shows the selected fourth burst frame as an empty thumbnail. The strip currently leaves every thumbnail `loading="lazy"`; selection does not make the current frame eager, so the browser can skip loading it while it is outside the horizontal lazy-load margin. I added eager loading for the selected frame and an e2e check for decoded pixels in every burst thumbnail.
Author
Owner

The post-build #1093 screenshot rerun exposed an e2e issue in the new last-result check: a transient toast could cover the “See all” pointer target. The Search action supports the documented macOS ⌘↩ shortcut, so the check now expands with that keyboard action before moving to the final row. The check remains focused on the final row’s geometry relative to the footer.

The post-build #1093 screenshot rerun exposed an e2e issue in the new last-result check: a transient toast could cover the “See all” pointer target. The Search action supports the documented macOS ⌘↩ shortcut, so the check now expands with that keyboard action before moving to the final row. The check remains focused on the final row’s geometry relative to the footer.
Author
Owner

Evidence from the returned settings-recovery-key-390-1x-dark.png (390×844): the Settings sheet occupies y=212..623, so the Calendar page title remains visible above it and the sheet does not reach the viewport bottom. The recovery group also inherits scroll-margin-top: -1.5rem in SettingsCard.svelte; the route's scrollIntoView({ block: 'start' }) therefore puts its heading under the sheet's sticky header. I merged job/settingsreg-1195 and am wiring its page-wide scrim and Settings header reserve into a shared full-viewport phone sheet. The e2e will check the section page and the Recovery Key deep link.

Evidence from the returned `settings-recovery-key-390-1x-dark.png` (390×844): the Settings sheet occupies y=212..623, so the Calendar page title remains visible above it and the sheet does not reach the viewport bottom. The recovery group also inherits `scroll-margin-top: -1.5rem` in `SettingsCard.svelte`; the route's `scrollIntoView({ block: 'start' })` therefore puts its heading under the sheet's sticky header. I merged `job/settingsreg-1195` and am wiring its page-wide scrim and Settings header reserve into a shared full-viewport phone sheet. The e2e will check the section page and the Recovery Key deep link.
Author
Owner

The #1123 rerun exposed a setup gap in its inherited #1137 sticky-heading check: the compact Atlas query had two options and a 174px scrollport with no scroll range, so the sticky heading could not activate. I kept its geometry and blur assertions unchanged and updated the setup to use the existing ⌘↩ See all action before measuring the sticky state.

The #1123 rerun exposed a setup gap in its inherited #1137 sticky-heading check: the compact Atlas query had two options and a 174px scrollport with no scroll range, so the sticky heading could not activate. I kept its geometry and blur assertions unchanged and updated the setup to use the existing ⌘↩ See all action before measuring the sticky state.
Author
Owner

Completed Search restyle fixes on job/restyle-search.

Head: 4b305a898359858055d1de5458af905229780971

Built: reserved the Search result footer in the scrollport and kept the selected last result above it; removed the opaque mobile footer wash; made Navigate rows title-only; added shared Pill.rowMenuAction behavior so the touch action stays available on coarse pointers while fine-pointer sidebar rows use their context menu. Right-click, Shift+F10, ContextMenu and touch long-press checks are included.

Files changed:

  • apps/web/src/lib/components/search-dialog.svelte
  • apps/web/src/lib/search/SearchResultRow.svelte and .test.ts
  • apps/web/src/lib/search/SavedSearchList.svelte
  • apps/web/e2e/search.mjs
  • packages/ui/src/components/OverlaySurface.svelte
  • packages/ui/src/components/Pill.svelte and packages/ui/README.md
  • apps/web/src/lib/components/Pill.svelte.test.ts
  • contracts/perf/adoption-1058.json, contracts/perf/exceptions.json

Decision: the design rules did not name an API for a row menu action. I added the documented Pill.rowMenuAction prop and kept its position and pointer rules in the shared Pill.

UX gaps closed: selected-last rows are kept above the footer at 1440/820/390 widths in light and dark; mobile Search uses the shared progressive blur without a white slab; Navigate rows show titles only; desktop sidebar rows have no direct ⋯ button and their menu remains reachable by pointer, keyboard and touch.

New screenshot paths:

  • apps/web/artifacts/restyle-search/rerun/search-1190-selected-last-{1440,820,390}-{mono,noir}.png
  • apps/web/artifacts/restyle-search/rerun/search-saved-sidebar-restyle-{1440,820,390}-{mono,noir}.png
  • apps/web/artifacts/restyle-search/rerun/search-palette-empty-390-paper.png
  • artifacts/restyle-search/rerun/search-1093-selected-preview-1440-tokyo-night.png

Gates, output quoted verbatim:

bun run check (exit 0):

perf-lint: PASS; 0 violations; 22615 scoped exceptions
svelte-check found 0 errors and 2 warnings in 2 files

The two warnings are existing empty CSS rulesets in AttachmentDeck.svelte and AgendaList.svelte.

bun run test (exit 0):

 Test Files  283 passed (283)
      Tests  1987 passed (1987)
   Start at  00:33:09
   Duration  253.98s (environment 28%, transform 25%, import 24%, tests 16%, setup 6%)

The post-build #1093 run completed all #1190 selected-last and sidebar assertions and captured the new screenshots, then timed out in the additional Atlas preview lookup. The requested SEARCH_E2E_1123_ONLY=1 rerun had passed earlier in this job; after the final build, reruns stopped at the inherited #1137 sticky-heading check because the Atlas results had no scroll range (latest diagnostic: 8 options, scrollTop=0, clientHeight=scrollHeight=729). I did not change that assertion. These are remaining e2e verification gaps outside the three #1190 UI fixes.

Completed Search restyle fixes on `job/restyle-search`. Head: `4b305a898359858055d1de5458af905229780971` Built: reserved the Search result footer in the scrollport and kept the selected last result above it; removed the opaque mobile footer wash; made Navigate rows title-only; added shared `Pill.rowMenuAction` behavior so the touch action stays available on coarse pointers while fine-pointer sidebar rows use their context menu. Right-click, Shift+F10, ContextMenu and touch long-press checks are included. Files changed: - `apps/web/src/lib/components/search-dialog.svelte` - `apps/web/src/lib/search/SearchResultRow.svelte` and `.test.ts` - `apps/web/src/lib/search/SavedSearchList.svelte` - `apps/web/e2e/search.mjs` - `packages/ui/src/components/OverlaySurface.svelte` - `packages/ui/src/components/Pill.svelte` and `packages/ui/README.md` - `apps/web/src/lib/components/Pill.svelte.test.ts` - `contracts/perf/adoption-1058.json`, `contracts/perf/exceptions.json` Decision: the design rules did not name an API for a row menu action. I added the documented `Pill.rowMenuAction` prop and kept its position and pointer rules in the shared Pill. UX gaps closed: selected-last rows are kept above the footer at 1440/820/390 widths in light and dark; mobile Search uses the shared progressive blur without a white slab; Navigate rows show titles only; desktop sidebar rows have no direct ⋯ button and their menu remains reachable by pointer, keyboard and touch. New screenshot paths: - `apps/web/artifacts/restyle-search/rerun/search-1190-selected-last-{1440,820,390}-{mono,noir}.png` - `apps/web/artifacts/restyle-search/rerun/search-saved-sidebar-restyle-{1440,820,390}-{mono,noir}.png` - `apps/web/artifacts/restyle-search/rerun/search-palette-empty-390-paper.png` - `artifacts/restyle-search/rerun/search-1093-selected-preview-1440-tokyo-night.png` Gates, output quoted verbatim: `bun run check` (exit 0): ``` perf-lint: PASS; 0 violations; 22615 scoped exceptions svelte-check found 0 errors and 2 warnings in 2 files ``` The two warnings are existing empty CSS rulesets in `AttachmentDeck.svelte` and `AgendaList.svelte`. `bun run test` (exit 0): ``` Test Files 283 passed (283) Tests 1987 passed (1987) Start at 00:33:09 Duration 253.98s (environment 28%, transform 25%, import 24%, tests 16%, setup 6%) ``` The post-build #1093 run completed all #1190 selected-last and sidebar assertions and captured the new screenshots, then timed out in the additional Atlas preview lookup. The requested `SEARCH_E2E_1123_ONLY=1` rerun had passed earlier in this job; after the final build, reruns stopped at the inherited #1137 sticky-heading check because the Atlas results had no scroll range (latest diagnostic: 8 options, `scrollTop=0`, `clientHeight=scrollHeight=729`). I did not change that assertion. These are remaining e2e verification gaps outside the three #1190 UI fixes.
Author
Owner

The focused real-server screenshot run uploaded all five burst files, but the fixture timed out waiting for all thumbnail derivatives. The server logged ERROR calternal_plugin::media_sandbox: native media command failed; ... cause=NamespaceResources, and two thumbnails stayed unavailable. I will merge origin/dev once and retry with its local media sandbox ceiling change before final verification.

The focused real-server screenshot run uploaded all five burst files, but the fixture timed out waiting for all thumbnail derivatives. The server logged `ERROR calternal_plugin::media_sandbox: native media command failed; ... cause=NamespaceResources`, and two thumbnails stayed unavailable. I will merge origin/dev once and retry with its local media sandbox ceiling change before final verification.
Author
Owner

Merged origin/dev as 67fff73ba. Resolved the shared Card and StatusPill conflicts by keeping both branches' props, behavior, tests and docs. The merged live perf inventory required 277 exact source-hash refreshes; each live scope and limit was preserved, and no exception or adoption checkpoint was removed. bun run check will verify the result.

Merged `origin/dev` as `67fff73ba`. Resolved the shared `Card` and `StatusPill` conflicts by keeping both branches' props, behavior, tests and docs. The merged live perf inventory required 277 exact source-hash refreshes; each live scope and limit was preserved, and no exception or adoption checkpoint was removed. `bun run check` will verify the result.
Author
Owner

#1190 final report

Branch: job/restyle-files
Head: 70d6f0bc5c895835c41f8fc5003716ee28d89003
Working tree: clean

Built

  • PhotoViewer.svelte eagerly loads the selected burst frame thumbnail. Other frames remain lazy. The Photos e2e fixture uploads a real five-frame burst, waits for all five generated thumbnails, scrolls each choice into view, and asserts every img has naturalWidth > 0, including the selected frame.
  • Shared QuickLook.svelte omits the full-width ProgressiveBlur band in fullscreen Photos. The floating controls keep their shared glass material. The e2e screenshot path asserts that the band is absent.
  • Refreshed exact performance hashes after the required origin/dev merge. The ledger still has 22,548 scopes: 328 existing scope hashes changed, with no scopes added or removed, no recorded limits changed, and no ratchet change.

Files for the fix: apps/web/src/lib/photos/PhotoViewer.svelte, apps/web/e2e/photos.mjs, packages/ui/src/components/viewer/QuickLook.svelte, contracts/perf/adoption-1058.json, contracts/perf/exceptions.json.

Screenshots

Captured from the production web build with macOS platform emulation, at CSS viewport widths 390, 820 and 1440, in paper-white and tokyo-night. The six actual-size screenshots are attached:

Verification

The focused production e2e run ended with:

PHOTOS RESTYLE SCREENSHOTS PASSED
CSP REPORTS photos: 0 across 3 pages

bun run check summary (verbatim):

perf-lint: PASS; 0 violations; 22548 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/restyle-files/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test summary (verbatim):

 Test Files  287 passed (287)
      Tests  2040 passed (2040)
   Start at  02:21:30
   Duration  379.03s (environment 27%, transform 26%, import 24%, tests 18%, setup 5%)

The suite also printed jsdom scrollTo() and CSS parser notices; all tests passed.

UX gaps closed

  • Selected burst thumbnail no longer appears as an empty box; all five frame images decode in the e2e assertion.
  • Full-width top blur no longer paints corner marks over fullscreen Photos.

UX gaps left / known gaps

  • No known user-visible gaps found in this scope. The six screenshots are ready for the visual reviewer.
  • The full browser smoke suite remains for the merge round: cd apps/web && bun run test:e2e — verify the integrated browser flows after the branch merge. No API behavior changed in this job.

Decisions

  • docs/DESIGN.md does not specify whether fullscreen Photos should show a full-width progressive blur across the photo edge and stage gutters. I omitted that band in this shared fullscreen viewer because the filtering caused the reported corner artifacts; the floating controls retain shared glass.
  • Expected thumbnail cost: one selected thumbnail is requested eagerly when opening a burst; the remaining N-1 frame thumbnails stay lazy until needed. The real five-frame e2e burst checks the decode path.

Commits: a290e77a4 (selected burst thumbnail), 15fed8c8d (required origin/dev merge), 47516aac2 (exact performance pins), 70d6f0bc5 (shared fullscreen blur fix).

**#1190 final report** Branch: `job/restyle-files` Head: `70d6f0bc5c895835c41f8fc5003716ee28d89003` Working tree: clean **Built** - `PhotoViewer.svelte` eagerly loads the selected burst frame thumbnail. Other frames remain lazy. The Photos e2e fixture uploads a real five-frame burst, waits for all five generated thumbnails, scrolls each choice into view, and asserts every `img` has `naturalWidth > 0`, including the selected frame. - Shared `QuickLook.svelte` omits the full-width `ProgressiveBlur` band in fullscreen Photos. The floating controls keep their shared glass material. The e2e screenshot path asserts that the band is absent. - Refreshed exact performance hashes after the required `origin/dev` merge. The ledger still has 22,548 scopes: 328 existing scope hashes changed, with no scopes added or removed, no recorded limits changed, and no ratchet change. Files for the fix: `apps/web/src/lib/photos/PhotoViewer.svelte`, `apps/web/e2e/photos.mjs`, `packages/ui/src/components/viewer/QuickLook.svelte`, `contracts/perf/adoption-1058.json`, `contracts/perf/exceptions.json`. **Screenshots** Captured from the production web build with macOS platform emulation, at CSS viewport widths 390, 820 and 1440, in paper-white and tokyo-night. The six actual-size screenshots are attached: - 1440: [paper-white](https://git.kayg.org/attachments/b0404ede-a9bd-4ea2-9465-f46098deb503), [tokyo-night](https://git.kayg.org/attachments/52f1a02f-5d4b-4f71-bee2-2cf45567bd42) - 820: [paper-white](https://git.kayg.org/attachments/2a6c4d81-cd23-4e09-924e-12def07ae95d), [tokyo-night](https://git.kayg.org/attachments/7a18001e-a004-4bf2-8229-04ece40ad13a) - 390: [paper-white](https://git.kayg.org/attachments/23ecd84d-b350-4ad9-a24f-8317af20f787), [tokyo-night](https://git.kayg.org/attachments/8f5f4c6d-d7d3-4830-9599-fee6cdabf0a3) **Verification** The focused production e2e run ended with: ```text PHOTOS RESTYLE SCREENSHOTS PASSED CSP REPORTS photos: 0 across 3 pages ``` `bun run check` summary (verbatim): ```text perf-lint: PASS; 0 violations; 22548 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/restyle-files/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` summary (verbatim): ```text Test Files 287 passed (287) Tests 2040 passed (2040) Start at 02:21:30 Duration 379.03s (environment 27%, transform 26%, import 24%, tests 18%, setup 5%) ``` The suite also printed jsdom `scrollTo()` and CSS parser notices; all tests passed. **UX gaps closed** - Selected burst thumbnail no longer appears as an empty box; all five frame images decode in the e2e assertion. - Full-width top blur no longer paints corner marks over fullscreen Photos. **UX gaps left / known gaps** - No known user-visible gaps found in this scope. The six screenshots are ready for the visual reviewer. - The full browser smoke suite remains for the merge round: `cd apps/web && bun run test:e2e` — verify the integrated browser flows after the branch merge. No API behavior changed in this job. **Decisions** - `docs/DESIGN.md` does not specify whether fullscreen Photos should show a full-width progressive blur across the photo edge and stage gutters. I omitted that band in this shared fullscreen viewer because the filtering caused the reported corner artifacts; the floating controls retain shared glass. - Expected thumbnail cost: one selected thumbnail is requested eagerly when opening a burst; the remaining `N-1` frame thumbnails stay lazy until needed. The real five-frame e2e burst checks the decode path. Commits: `a290e77a4` (selected burst thumbnail), `15fed8c8d` (required `origin/dev` merge), `47516aac2` (exact performance pins), `70d6f0bc5` (shared fullscreen blur fix).
Author
Owner

Starting #1190 follow-up on branch job/restyle-search. Worktree start SHA: 4b305a8983. I will trace the filter option alignment to the earlier Pill change, add a focused e2e assertion, verify Notes/Files/Tags sidebar rows against origin/dev, and capture the requested palette screenshots.

Starting #1190 follow-up on branch job/restyle-search. Worktree start SHA: 4b305a898359858055d1de5458af905229780971. I will trace the filter option alignment to the earlier Pill change, add a focused e2e assertion, verify Notes/Files/Tags sidebar rows against origin/dev, and capture the requested palette screenshots.
Author
Owner

Finding: artifacts/restyle-search/rerun/search-1190-selected-last-1440-noir.png shows TYPE options starting around x=192 while the TYPE heading starts around x=134; the same centered layout repeats under DATE, TAG, FOLDER and PERSON. The rowMenuAction class is only attached to SavedSearchList’s menu button, so it cannot affect these facet rows. Search changed its native facet buttons to shared Pill buttons; the feature-scoped .facet root rules do not style a child component root, and Pill centers the content wrapper by default. I will add an opt-in start-aligned Pill layout for these desktop facet rows and leave other Pill users at their current default.

Finding: artifacts/restyle-search/rerun/search-1190-selected-last-1440-noir.png shows TYPE options starting around x=192 while the TYPE heading starts around x=134; the same centered layout repeats under DATE, TAG, FOLDER and PERSON. The `rowMenuAction` class is only attached to SavedSearchList’s menu button, so it cannot affect these facet rows. Search changed its native facet buttons to shared `Pill` buttons; the feature-scoped `.facet` root rules do not style a child component root, and Pill centers the content wrapper by default. I will add an opt-in start-aligned Pill layout for these desktop facet rows and leave other Pill users at their current default.
Author
Owner

Found during the 1440px production review: .content has a negative shadow margin that overlapped .rail-edge, so pointer input landed on content and the rail stayed at 256px. The separator now sits above that gutter. A focused production check confirms the edge receives the drag, reaches 280px, and two shared 48px keyboard steps reach the existing 184px minimum. The complete 1440px light and dark captures now pass.

Found during the 1440px production review: `.content` has a negative shadow margin that overlapped `.rail-edge`, so pointer input landed on content and the rail stayed at 256px. The separator now sits above that gutter. A focused production check confirms the edge receives the drag, reaches 280px, and two shared 48px keyboard steps reach the existing 184px minimum. The complete 1440px light and dark captures now pass.
Author
Owner

Completed: Settings restyle follow-up

Branch: job/restyle-settings
Head: ccd5502471df71dcd973f148e767c9b7d4541386

What changed

  • The phone Settings sheet fills the viewport. Its own header remains visible, content starts below the header, and there are no visible sheet slab edges. This uses the shared OverlaySurface component and shared tokens.
  • Recovery Key deep links place the group heading below sheet chrome.
  • The desktop rail resize hit zone stays above the content shadow, so pointer dragging reaches the separator.
  • The 390 px e2e check asserts the section heading is inside the sheet and below its header, and that the sheet bottom reaches the viewport bottom within 1 px.
  • The review e2e resets and resizes the rail using the shared separator keyboard step. The CSS changes add no per-item work or IO; runtime layout cost is O(1) per sheet/rail.
  • Refreshed exact live source hashes for the Settings performance contracts without changing their scopes or limits.

UX gaps closed

  • Fixed the clipped phone heading, hard bottom edge, empty sheet area, left slab edge, and underlying page title visible above the sheet.
  • Fixed pointer resizing being intercepted by content.
  • Captured all 32 live Settings sections at 390, 820 and 1440 px in light and dark themes. The screenshots use macOS platform emulation and real local API data.

UX gaps left

  • No known Settings interaction gap remains from this review.
  • The existing apps/web/e2e/settings-overlay-1195.mjs setup times out at getByLabel('Budget name') on the current empty Money route, before it reaches the overlay. I did not change that unrelated setup. I checked the real shared Settings scrim separately from a real Calendar route; it passed at 390, 820 and 1440 px in both themes.
  • The screenshots are attached for the visual review.

Screenshots

Files

  • apps/web/src/routes/settings/[...path]/+page.svelte
  • apps/web/e2e/settings-review-50.mjs
  • packages/ui/src/components/OverlaySurface.svelte
  • contracts/perf/exceptions.json
  • contracts/perf/adoption-1058.json

Decisions

  • Used the shared OverlaySurface full-viewport size for the phone sheet. The Settings-specific choice is to keep its heading in the sheet header and start section content below that header.
  • Removed the local negative scroll offset and kept the shared scroll inset, so deep links do not place headings behind sheet chrome.
  • The rail review seeds 280 px before two shared 48 px keyboard steps to reach the existing 184 px minimum. This keeps the test aligned with the shared separator step and minimum.

Verification

bun run check exited 0. Relevant output, verbatim:

PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages
perf-lint: PASS; 0 violations; 22548 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Warn: Do not use empty rulesets (css)
svelte-check found 0 errors and 1 warning in 1 file

The one warning is the existing empty CSS ruleset in packages/ui/src/components/calendar/AttachmentDeck.svelte:1055.

bun run test exited 0. Output, verbatim:

 Test Files  288 passed (288)
      Tests  2045 passed (2045)
   Start at  04:20:27
   Duration  488.34s (transform 28%, environment 26%, import 24%, tests 17%, setup 5%)

The review e2e passed its requested section matrix and route checks. Output, verbatim:

SETTINGS PAGES 390-light: captured 32 live section pages
SETTINGS PAGES 390-dark: captured 32 live section pages
SETTINGS PAGES 820-light: captured 32 live section pages
SETTINGS PAGES 820-dark: captured 32 live section pages
SETTINGS PAGES 1440-light: captured 32 live section pages
SETTINGS PAGES 1440-dark: captured 32 live section pages
PASS 26 legacy Settings URLs resolve to their canonical homes
PASS the Calendar overflow menu opens its Tab Settings page

The separate Calendar-route scrim review passed at all six width/theme combinations. bun run build exited 0; final output:

Compressed 915 static variants; saved 21491247 bytes.

git diff --check and node --check apps/web/e2e/settings-review-50.mjs exited 0 with no output. No Rust source changed, so Rust crate gates were not run. Cleanup output, verbatim:

Removed 8660 files, 7.9GiB total
## Completed: Settings restyle follow-up Branch: `job/restyle-settings` Head: `ccd5502471df71dcd973f148e767c9b7d4541386` ### What changed - The phone Settings sheet fills the viewport. Its own header remains visible, content starts below the header, and there are no visible sheet slab edges. This uses the shared `OverlaySurface` component and shared tokens. - Recovery Key deep links place the group heading below sheet chrome. - The desktop rail resize hit zone stays above the content shadow, so pointer dragging reaches the separator. - The 390 px e2e check asserts the section heading is inside the sheet and below its header, and that the sheet bottom reaches the viewport bottom within 1 px. - The review e2e resets and resizes the rail using the shared separator keyboard step. The CSS changes add no per-item work or IO; runtime layout cost is O(1) per sheet/rail. - Refreshed exact live source hashes for the Settings performance contracts without changing their scopes or limits. ### UX gaps closed - Fixed the clipped phone heading, hard bottom edge, empty sheet area, left slab edge, and underlying page title visible above the sheet. - Fixed pointer resizing being intercepted by content. - Captured all 32 live Settings sections at 390, 820 and 1440 px in light and dark themes. The screenshots use macOS platform emulation and real local API data. ### UX gaps left - No known Settings interaction gap remains from this review. - The existing `apps/web/e2e/settings-overlay-1195.mjs` setup times out at `getByLabel('Budget name')` on the current empty Money route, before it reaches the overlay. I did not change that unrelated setup. I checked the real shared Settings scrim separately from a real Calendar route; it passed at 390, 820 and 1440 px in both themes. - The screenshots are attached for the visual review. ### Screenshots - [390 px, all sections, light and dark](https://git.kayg.org/attachments/12964008-3dd1-4746-8598-e2aa6dbe6db1) - [820 px, all sections, light and dark](https://git.kayg.org/attachments/900874aa-8140-44e6-bffc-56d5cec7575b) - [1440 px, all sections, light and dark](https://git.kayg.org/attachments/45314d74-317a-457e-8d73-536d6e85ad72) - [Shared scrim check for #1195](https://git.kayg.org/attachments/9734329d-3b0c-4f3e-a981-727ee432ad99) ### Files - `apps/web/src/routes/settings/[...path]/+page.svelte` - `apps/web/e2e/settings-review-50.mjs` - `packages/ui/src/components/OverlaySurface.svelte` - `contracts/perf/exceptions.json` - `contracts/perf/adoption-1058.json` ### Decisions - Used the shared `OverlaySurface` `full-viewport` size for the phone sheet. The Settings-specific choice is to keep its heading in the sheet header and start section content below that header. - Removed the local negative scroll offset and kept the shared scroll inset, so deep links do not place headings behind sheet chrome. - The rail review seeds 280 px before two shared 48 px keyboard steps to reach the existing 184 px minimum. This keeps the test aligned with the shared separator step and minimum. ### Verification `bun run check` exited 0. Relevant output, verbatim: ```text PASS production dependency licences: 759 locked package releases across apps/web, apps/docs and packages perf-lint: PASS; 0 violations; 22548 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Warn: Do not use empty rulesets (css) svelte-check found 0 errors and 1 warning in 1 file ``` The one warning is the existing empty CSS ruleset in `packages/ui/src/components/calendar/AttachmentDeck.svelte:1055`. `bun run test` exited 0. Output, verbatim: ```text Test Files 288 passed (288) Tests 2045 passed (2045) Start at 04:20:27 Duration 488.34s (transform 28%, environment 26%, import 24%, tests 17%, setup 5%) ``` The review e2e passed its requested section matrix and route checks. Output, verbatim: ```text SETTINGS PAGES 390-light: captured 32 live section pages SETTINGS PAGES 390-dark: captured 32 live section pages SETTINGS PAGES 820-light: captured 32 live section pages SETTINGS PAGES 820-dark: captured 32 live section pages SETTINGS PAGES 1440-light: captured 32 live section pages SETTINGS PAGES 1440-dark: captured 32 live section pages PASS 26 legacy Settings URLs resolve to their canonical homes PASS the Calendar overflow menu opens its Tab Settings page ``` The separate Calendar-route scrim review passed at all six width/theme combinations. `bun run build` exited 0; final output: ```text Compressed 915 static variants; saved 21491247 bytes. ``` `git diff --check` and `node --check apps/web/e2e/settings-review-50.mjs` exited 0 with no output. No Rust source changed, so Rust crate gates were not run. Cleanup output, verbatim: ```text Removed 8660 files, 7.9GiB total ```
Author
Owner

Completed on job/restyle-search.

Change

Added an opt-in alignStart prop to shared Pill and used it only on desktop Search facet options. The facet labels now use the same --toolbar-gap inset as their section headings. The default Pill layout and phone chip rail stay unchanged. Counts follow their labels.

The real-browser e2e checks all five facet sections and asserts each option label starts within 1 px of its heading. It also checks that counts do not overlap labels.

Verification

bun run check — exit 0:

perf-lint: PASS; 0 violations; 22548 scoped exceptions
svelte-check found 0 errors and 1 warning in 1 file

The one warning is the existing empty CSS ruleset in packages/ui/src/components/calendar/AttachmentDeck.svelte:1055.

bun run test — exit 0:

Ran 136 tests in 0.058s
OK
8 pass
0 fail
Test Files  287 passed (287)
Tests  2038 passed (2038)
Duration 650.81s (environment 26%, transform 26%, import 23%, tests 18%, setup 6%)

Real-server production e2e — exit 0:

PASS #1093 palette states and #1190 footer/sidebar checks across the requested review widths
CSP REPORTS search: 0 across 2 pages

The Search filter screenshots use macOS emulation and cover 1440 px and 390 px in light (mono) and dark (noir). The Notes, Files and Tags sidebar crops match the detached origin/dev build at 3601719b8 pixel-for-pixel in both themes: changed pixels 0 for each crop.

Review artifacts

The four Search filter captures are in artifacts/restyle-search/rerun/. The origin/current/sidebar pixel-diff captures are in artifacts/restyle-search/sidebar-diffs-1190/.

The installed fj issue comment command has no attachment/upload option, so these screenshots remain in the worktree for review and are not committed.

Decision

DESIGN §32 does not specify how a shared Pill should expose row alignment. I added the smallest opt-in prop and enabled it only for desktop Search facets; other Pill users are unaffected.

Head: 4aacba651ac91179b33c630aff774a8d22bbd076 (Align Search filter facets with headings). Required origin/dev merge is in 02ecbacf6.

Completed on `job/restyle-search`. ## Change Added an opt-in `alignStart` prop to shared `Pill` and used it only on desktop Search facet options. The facet labels now use the same `--toolbar-gap` inset as their section headings. The default Pill layout and phone chip rail stay unchanged. Counts follow their labels. The real-browser e2e checks all five facet sections and asserts each option label starts within 1 px of its heading. It also checks that counts do not overlap labels. ## Verification `bun run check` — exit 0: ``` perf-lint: PASS; 0 violations; 22548 scoped exceptions svelte-check found 0 errors and 1 warning in 1 file ``` The one warning is the existing empty CSS ruleset in `packages/ui/src/components/calendar/AttachmentDeck.svelte:1055`. `bun run test` — exit 0: ``` Ran 136 tests in 0.058s OK 8 pass 0 fail Test Files 287 passed (287) Tests 2038 passed (2038) Duration 650.81s (environment 26%, transform 26%, import 23%, tests 18%, setup 6%) ``` Real-server production e2e — exit 0: ``` PASS #1093 palette states and #1190 footer/sidebar checks across the requested review widths CSP REPORTS search: 0 across 2 pages ``` The Search filter screenshots use macOS emulation and cover 1440 px and 390 px in light (`mono`) and dark (`noir`). The Notes, Files and Tags sidebar crops match the detached `origin/dev` build at `3601719b8` pixel-for-pixel in both themes: changed pixels `0` for each crop. ## Review artifacts The four Search filter captures are in `artifacts/restyle-search/rerun/`. The origin/current/sidebar pixel-diff captures are in `artifacts/restyle-search/sidebar-diffs-1190/`. The installed `fj issue comment` command has no attachment/upload option, so these screenshots remain in the worktree for review and are not committed. ## Decision DESIGN §32 does not specify how a shared Pill should expose row alignment. I added the smallest opt-in prop and enabled it only for desktop Search facets; other Pill users are unaffected. Head: `4aacba651ac91179b33c630aff774a8d22bbd076` (`Align Search filter facets with headings`). Required `origin/dev` merge is in `02ecbacf6`.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
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-v0#1190
No description provided.