diff --git a/docs/architecture.md b/docs/architecture.md
index cf8be50..801199c 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -372,8 +372,9 @@ component; tokens → `ui/src/styles.css`.
walker check the flag themselves.
- `file-icons.ts` — extension → category map driving glyphs, colors
(fixed `--icon-*` tokens from Oxide's hue scales) and the Kind column.
-- `icons.ts` — the one icon registry (TDesign, `@ng-icons/tdesign-icons`), passed to
- `provideIcons` in `app.config.ts`. Icon names are plain strings in templates and
+- `icons.ts` — the one icon registry (TDesign, `@ng-icons/tdesign-icons`, plus one
+ redrawn glyph: `pixelAdd`, TDesign's + on the 14px pixel grid so it stays sharp
+ on 1x screens), passed to `provideIcons` in `app.config.ts`. Icon names are plain strings in templates and
the build never checks them: an unregistered name renders nothing (console error
only), so every name used anywhere must be listed here.
- `platform.ts` — preload-global readers (`PLATFORM`, `APP_MODE`,
diff --git a/docs/gotchas.md b/docs/gotchas.md
index 6d69b03..9172509 100644
--- a/docs/gotchas.md
+++ b/docs/gotchas.md
@@ -82,6 +82,14 @@ touching the adjacent code.
it. Per-template picks had drifted to 12 sizes, and neighbours stopped
matching: a 14.4px cog beside a 12.8px +, and a 12px + beside 9.6px × in
the shortcut chips.
+- **On a 1x screen, a TDesign line through the icon's centre smears at any
+ small size.** At 12 or 14px the centre is a pixel boundary, so a ~1px bar
+ covers two pixels at half ink. A 1px stroke alone doesn't help, because the
+ bar stays centred on the boundary. This is geometry, not Electrobun:
+ headless Chrome renders the same. So the + is `pixelAdd` (`icons.ts`),
+ redrawn on the 14px grid with 1px bars at 7.5, which fill whole pixels at 1x
+ and at 2x. It's tuned for `--icon-size-sm` only. Arrow shafts (↑ →) have
+ the same issue if it ever shows.
## The interface scale (root font-size lever)
diff --git a/ui/src/app/core/context-menu.service.ts b/ui/src/app/core/context-menu.service.ts
index 303e72b..3d46d7e 100644
--- a/ui/src/app/core/context-menu.service.ts
+++ b/ui/src/app/core/context-menu.service.ts
@@ -180,7 +180,7 @@ export class ContextMenuService {
const t = (key: string) => this.i18n.t(key);
const last = ctx.tabCount <= 1;
return [
- { label: t('ctx.tabNew'), action: 'tab:new', shortcut: 'new-tab', icon: 'tdesignAdd' },
+ { label: t('ctx.tabNew'), action: 'tab:new', shortcut: 'new-tab', icon: 'pixelAdd' },
{ type: 'separator' },
{
label: t('ctx.tabClose'),
diff --git a/ui/src/app/core/icons.ts b/ui/src/app/core/icons.ts
index b658cd9..a84fa0e 100644
--- a/ui/src/app/core/icons.ts
+++ b/ui/src/app/core/icons.ts
@@ -3,7 +3,6 @@
// plain strings in templates — the build never checks them, so every name used
// anywhere must be listed here (an unregistered one renders nothing).
import {
- tdesignAdd,
tdesignArrowLeft,
tdesignArrowRight,
tdesignArrowUp,
@@ -37,8 +36,15 @@ import {
tdesignVideo,
} from "@ng-icons/tdesign-icons";
+// TDesign's + redrawn on the pixel grid of --icon-size-sm (14px). Its own glyph
+// centres 24-grid strokes on the box's middle, a pixel boundary at 14px, so on a
+// 1x screen both bars smear over two pixels at half ink. These bars are 1px wide
+// on a half pixel (7.5): whole pixels at 1x and 2x, half a pixel off-centre.
+const pixelAdd =
+ '';
+
export const APP_ICONS = {
- tdesignAdd,
+ pixelAdd,
tdesignArrowLeft,
tdesignArrowRight,
tdesignArrowUp,
diff --git a/ui/src/app/skins/shadlike/connection-manager/connection-manager.html b/ui/src/app/skins/shadlike/connection-manager/connection-manager.html
index b0a9d46..5f16ff0 100644
--- a/ui/src/app/skins/shadlike/connection-manager/connection-manager.html
+++ b/ui/src/app/skins/shadlike/connection-manager/connection-manager.html
@@ -36,7 +36,7 @@
[title]="shortcuts.tip(i18n.t('connMgr.newConnectionHint'), 'conn-new')"
class="flex items-center gap-1 px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground"
>
-