From 4f3373660904f43bc3bbc9ad777d6f77209153bb Mon Sep 17 00:00:00 2001
From: seonghobae <8172694+seonghobae@users.noreply.github.com>
Date: Mon, 28 Sep 2026 18:54:53 +0000
Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20[=EC=99=B8?=
=?UTF-8?q?=EB=B6=80=20=EB=A7=81=ED=81=AC=20=EC=A0=91=EA=B7=BC=EC=84=B1=20?=
=?UTF-8?q?=EB=B0=8F=20UX=20=EA=B0=9C=EC=84=A0]?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
외부 링크에 대한 접근성과 UI를 개선합니다.
- `target="_blank"` 링크에 `.sr-only` 클래스로 "새 탭에서 열림" 텍스트 추가
- 외부 링크임을 알리는 아이콘 삽입 (시각적 개선 및 `aria-hidden="true"`)
- 긴 URL이 레이아웃을 깨는 것을 방지하기 위해 `word-break: break-all`이 전역으로 적용되지 않고 `.ext-link` 유틸리티 클래스로 제한되도록 스코핑
---
.jules/palette.md | 4 ++++
scanner/dashboard/index.html | 8 ++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index ea004e2d2..b20cb4c3b 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -81,3 +81,7 @@
## 2026-08-12 - Skip to Content Accessibility
**Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load.
**Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline.
+
+## 2026-10-24 - 외부 링크 접근성 강화 및 스타일 스코핑
+**Learning:** `target="_blank"` 속성을 가진 외부 링크에 시각적(아이콘) 표시는 제공하지만, 스크린 리더 등 보조 기기 사용자를 위한 텍스트 경고(`새 탭에서 열림` 등)를 누락하거나, 긴 URL 단어를 강제 줄바꿈하기 위한 `word-break: break-all`을 링크 전체에 전역으로 적용하면 UI 레이아웃이 무너지거나 접근성이 저하된다.
+**Action:** 외부 링크에는 항상 화면에 보이지 않는 `.sr-only` 클래스의 텍스트 설명과, 보조 기기에서 무시되는 `aria-hidden="true"` 아이콘을 병행 제공하라. 또한 줄바꿈 등 특수 스타일은 전역 선택자(`a`) 대신 `.ext-link`와 같은 전용 유틸리티 클래스로 스코프를 제한하라.
diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html
index 132bc31b2..1adc2c4cb 100644
--- a/scanner/dashboard/index.html
+++ b/scanner/dashboard/index.html
@@ -82,7 +82,11 @@
body.drag-active::after{content:"Drop findings.json here";position:fixed;inset:0;z-index:99;background:rgba(37,110,244,.08);border:4px dashed var(--primary);display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:var(--primary);pointer-events:none;backdrop-filter:blur(2px)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
a{color:var(--primary)}
- .skip-link{position:absolute;top:-48px;left:0;background:var(--primary);color:#fff;padding:8px 16px;z-index:100;font-weight:700;border-radius:0 0 8px 0;transition:top .2s}\n .skip-link:focus{top:0;outline:3px solid #fff;outline-offset:2px;box-shadow:0 0 0 5px var(--primary)}\n
+ .skip-link{position:absolute;top:-48px;left:0;background:var(--primary);color:#fff;padding:8px 16px;z-index:100;font-weight:700;border-radius:0 0 8px 0;transition:top .2s}
+ .skip-link:focus{top:0;outline:3px solid #fff;outline-offset:2px;box-shadow:0 0 0 5px var(--primary)}
+ .ext-link{display:inline-flex;align-items:center;gap:4px;word-break:break-all}
+ .ext-icon{width:12px;height:12px;fill:currentColor;flex-shrink:0}
+
@@ -281,7 +285,7 @@
Dashboard
function openDetail(f){
lastFocus = document.activeElement;
const s = String(f.severity||'INFO').toUpperCase();
- const refs = (f.references||[]).map(r=>`${esc(r)}`).join(' ');
+ const refs = (f.references||[]).map(r=>`${esc(r)}(새 탭에서 열림)`).join(' ');
const owasp = (f.owasp||[]).join(', ');
const cwe = (f.cwe||[]).join(', ');
const d = document.getElementById('detail');
From 5fdc3723384d3dc12fe98e6317050be821ef7d25 Mon Sep 17 00:00:00 2001
From: Seongho Bae
Date: Sat, 3 Oct 2026 18:53:11 +0900
Subject: [PATCH 2/3] chore: retire duplicate .jules/palette.md delta in favor
of #1361
---
.jules/palette.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/.jules/palette.md b/.jules/palette.md
index b20cb4c3b..ea004e2d2 100644
--- a/.jules/palette.md
+++ b/.jules/palette.md
@@ -81,7 +81,3 @@
## 2026-08-12 - Skip to Content Accessibility
**Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load.
**Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline.
-
-## 2026-10-24 - 외부 링크 접근성 강화 및 스타일 스코핑
-**Learning:** `target="_blank"` 속성을 가진 외부 링크에 시각적(아이콘) 표시는 제공하지만, 스크린 리더 등 보조 기기 사용자를 위한 텍스트 경고(`새 탭에서 열림` 등)를 누락하거나, 긴 URL 단어를 강제 줄바꿈하기 위한 `word-break: break-all`을 링크 전체에 전역으로 적용하면 UI 레이아웃이 무너지거나 접근성이 저하된다.
-**Action:** 외부 링크에는 항상 화면에 보이지 않는 `.sr-only` 클래스의 텍스트 설명과, 보조 기기에서 무시되는 `aria-hidden="true"` 아이콘을 병행 제공하라. 또한 줄바꿈 등 특수 스타일은 전역 선택자(`a`) 대신 `.ext-link`와 같은 전용 유틸리티 클래스로 스코프를 제한하라.
From 1687847dbef9d228b7587c779930cdff3e2f596d Mon Sep 17 00:00:00 2001
From: Seongho Bae
Date: Sat, 3 Oct 2026 18:53:13 +0900
Subject: [PATCH 3/3] chore: retire duplicate scanner/dashboard/index.html
delta in favor of #1361
---
scanner/dashboard/index.html | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html
index 1adc2c4cb..132bc31b2 100644
--- a/scanner/dashboard/index.html
+++ b/scanner/dashboard/index.html
@@ -82,11 +82,7 @@
body.drag-active::after{content:"Drop findings.json here";position:fixed;inset:0;z-index:99;background:rgba(37,110,244,.08);border:4px dashed var(--primary);display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:var(--primary);pointer-events:none;backdrop-filter:blur(2px)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
a{color:var(--primary)}
- .skip-link{position:absolute;top:-48px;left:0;background:var(--primary);color:#fff;padding:8px 16px;z-index:100;font-weight:700;border-radius:0 0 8px 0;transition:top .2s}
- .skip-link:focus{top:0;outline:3px solid #fff;outline-offset:2px;box-shadow:0 0 0 5px var(--primary)}
- .ext-link{display:inline-flex;align-items:center;gap:4px;word-break:break-all}
- .ext-icon{width:12px;height:12px;fill:currentColor;flex-shrink:0}
-
+ .skip-link{position:absolute;top:-48px;left:0;background:var(--primary);color:#fff;padding:8px 16px;z-index:100;font-weight:700;border-radius:0 0 8px 0;transition:top .2s}\n .skip-link:focus{top:0;outline:3px solid #fff;outline-offset:2px;box-shadow:0 0 0 5px var(--primary)}\n
@@ -285,7 +281,7 @@