diff --git a/ui/src/app.test.ts b/ui/src/app.test.ts
--- a/ui/src/app.test.ts
+++ b/ui/src/app.test.ts
@@ -216,6 +216,21 @@ test('clicking a row, or barely moving it, opens its urgent issues', async () =>
   assert.equal(stored(h, 'order'), null, 'a click is not a reorder');
 });
 
+test('links are anchors the keyboard can reach, and opening one leaves the window where it is', async () => {
+  const h = await setup();
+  const link = h.row('gamma').querySelector<HTMLAnchorElement>('.repo .link')!;
+  assert.equal(link.tagName, 'A');
+  assert.equal(link.getAttribute('href'), 'https://github.com/o/gamma');
+  const click = new h.win.MouseEvent('click', { bubbles: true, cancelable: true }) as unknown as Event;
+  link.dispatchEvent(click);
+  assert.ok(click.defaultPrevented, 'the host opens the URL, not the webview');
+  const middle = new h.win.MouseEvent('auxclick', { bubbles: true, cancelable: true, button: 1 }) as unknown as Event;
+  link.dispatchEvent(middle);
+  assert.ok(middle.defaultPrevented, 'a middle click opens no second window');
+  assert.equal(h.view(), 'repos');
+  assert.deepEqual(h.calls.filter((c) => c.cmd === 'open_url').map((c) => c.args?.url), ['https://github.com/o/gamma']);
+});
+
 test('links in a row open on GitHub without dragging or switching views', async () => {
   const h = await setup();
   const link = h.row('gamma').querySelector<HTMLElement>('.repo .link')!;
@@ -329,6 +344,18 @@ test('urgent view lists every repo’s issues, filters to critical, and opens th
   assert.equal(h.calls.at(-1)?.args?.url, 'https://github.com/o/x/issues/1');
 });
 
+test('urgent issues can be reached with Tab and opened with Enter', async () => {
+  const h = await setup();
+  h.doc.querySelector<HTMLElement>('[data-view="urgent"]')!.click();
+  const item = h.doc.querySelectorAll<HTMLElement>('.urgent-item')[1]!;
+  assert.equal(item.tabIndex, 0);
+  assert.equal(item.getAttribute('role'), 'link');
+  item.dispatchEvent(new h.win.KeyboardEvent('keydown', { key: 'a', bubbles: true }) as unknown as Event);
+  assert.ok(!h.calls.some((c) => c.cmd === 'open_url'), 'other keys do nothing');
+  item.dispatchEvent(new h.win.KeyboardEvent('keydown', { key: 'Enter', bubbles: true }) as unknown as Event);
+  assert.deepEqual(h.calls.filter((c) => c.cmd === 'open_url').map((c) => c.args?.url), ['https://github.com/o/x/issues/3']);
+});
+
 // ───────────────────────────── host ─────────────────────────────
 
 test('keyboard shortcuts and buttons call the host', async () => {
diff --git a/ui/src/app.ts b/ui/src/app.ts
--- a/ui/src/app.ts
+++ b/ui/src/app.ts
@@ -93,12 +93,18 @@ export function start(api: Api): () => void {
   };
 
   function openUrl(url: string, ev?: Event): void {
+    ev?.preventDefault();
     ev?.stopPropagation();
     api.invoke('open_url', { url }).catch((e: unknown) => console.warn(e));
   }
 
+  // A real anchor, so Tab reaches it and Enter opens it; the host opens the URL and the webview stays put.
   const link = (text: string, url: string, cls = ''): HTMLElement =>
-    el('span', { class: `link ${cls}`, onclick: (e: Event) => openUrl(url, e) }, text);
+    el('a', {
+      class: `link ${cls}`, href: url, draggable: 'false',
+      onclick: (e: Event) => openUrl(url, e),
+      onauxclick: (e: Event) => e.preventDefault(),
+    }, text);
 
   /** The repo's app icon; repos without one (libraries) get a lettered tile, unfetched ones a blank. */
   function appIcon(entry: Pick<RepoEntry, 'repo'> & Partial<RepoEntry>): HTMLElement {
@@ -334,7 +340,11 @@ export function start(api: Api): () => void {
     const SEVERE = /crash|panic|freeze|hang|data loss|corruption|won't|blank|security/;
     $('urgent-list').replaceChildren(...items.map((u) => {
       const a = Math.min(1, u.score / 90) * 0.5;
-      return el('li', { class: `urgent-item${u.critical ? ' critical' : ''}`, onclick: () => openUrl(u.url), title: u.url },
+      return el('li', {
+        class: `urgent-item${u.critical ? ' critical' : ''}`, title: u.url, tabindex: '0', role: 'link',
+        onclick: () => openUrl(u.url),
+        onkeydown: (e: KeyboardEvent) => { if (e.key === 'Enter') openUrl(u.url, e); },
+      },
         el('span', { class: 'score', style: `background: rgb(var(--hot-rgb) / ${a.toFixed(2)})` }, String(u.score)),
         el('span', { class: 'u-repo' }, appIcon(snap.repos.find((r) => r.repo === u.repo) ?? { repo: u.repo }), shortName(u.repo)),
         el('div', { class: 'u-title' },
diff --git a/ui/style.css b/ui/style.css
--- a/ui/style.css
+++ b/ui/style.css
@@ -36,7 +36,7 @@
 html, body { margin: 0; height: 100%; overflow: hidden; background: transparent; }
 body { font: 12px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: var(--fg); -webkit-font-smoothing: antialiased; }
 button, select { color: inherit; font: inherit; cursor: pointer; }
-button:focus-visible, select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
+button:focus-visible, select:focus-visible, .link:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
 svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
 
 .app { height: 100%; display: flex; flex-direction: column; background: rgb(var(--bg) / var(--opacity)); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; position: relative; }
@@ -106,6 +106,7 @@ tr.stale .repo .dot { background: var(--warn); }
 tr.error .repo .dot { background: var(--bad); }
 tr.stale td:not(:first-child) { opacity: .55; }
 .muted { color: var(--muted); }
+.link { color: inherit; text-decoration: none; }
 .fetched { display: inline-flex; align-items: center; gap: 3px; }
 .row-refresh { background: none; border: 0; padding: 0; width: 11px; height: 11px; display: inline-grid; place-items: center; color: var(--muted); opacity: .45; cursor: pointer; }
 .row-refresh svg { width: 10px; height: 10px; stroke-width: 1.8; }
@@ -130,6 +131,7 @@ tfoot td { color: var(--muted); font-weight: 600; border-bottom: 0; position: st
 .urgent-list { list-style: none; margin: 0; padding: 0; }
 .urgent-item { display: grid; grid-template-columns: 44px 112px 1fr auto; gap: 10px; align-items: baseline; padding: 7px 15px; border-bottom: 1px solid var(--border); cursor: pointer; }
 .urgent-item:hover { background: var(--row-hover); }
+.urgent-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
 .score { font-weight: 700; text-align: center; border-radius: 4px; font-variant-numeric: tabular-nums; }
 .u-repo { display: flex; align-items: center; gap: 5px; color: var(--muted); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
 .u-title { min-width: 0; }
