From a9f702a7157e5d7e1e17740556fd245f55a835d9 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 19 Apr 2026 19:18:57 +0800 Subject: [PATCH] feat(ui): add security banner markup + styles (approved variant A) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HTML + CSS for the canary leak / ML block banner. Structure matches the approved mockup from /plan-design-review 2026-04-19 (variant A — centered alert-heavy): * Red alert-circle SVG icon (no stock shield, intentional — matches the "serious but not scary" tone the review chose) * "Session terminated" Satoshi Bold 18px red headline * "— prompt injection detected from {domain}" DM Sans zinc subtitle * Expandable "What happened" chevron button (aria-expanded/aria-controls) * Layer list rendered in JetBrains Mono with amber tabular-nums scores * Close X in top-right, 28px hit area, focus-visible amber outline Enter animation: slide-down 8px + fade, 250ms, cubic-bezier(0.16,1,0.3,1) — matches DESIGN.md motion spec. Respects `role="alert"` + `aria-live="assertive"` so screen readers announce on appearance. Escape-to-dismiss hook is in the JS follow-up commit. Design tokens all via CSS variables (--error, --amber-400, --amber-500, --zinc-*, --font-display, --font-mono, --radius-*) — already established in the stylesheet. No new color constants introduced. JS wiring lands in the next commit so this diff stays focused on presentation layer only. Co-Authored-By: Claude Opus 4.7 (1M context) --- extension/sidepanel.css | 132 +++++++++++++++++++++++++++++++++++++++ extension/sidepanel.html | 26 ++++++++ 2 files changed, 158 insertions(+) diff --git a/extension/sidepanel.css b/extension/sidepanel.css index 5b99b7bf..0939a350 100644 --- a/extension/sidepanel.css +++ b/extension/sidepanel.css @@ -87,6 +87,138 @@ flex: 1; } +/* ─── Security Banner ───────────────────────────────────────────── + Variant A approved in /plan-design-review 2026-04-19. Centered + alert-heavy. Fires on security_event — canary leaks + ML BLOCK + verdicts. Trust UX: layer names + confidence scores in mono so + the user can see exactly WHY the session was terminated. +*/ + +.security-banner { + position: relative; + padding: 20px 16px; + text-align: center; + background: rgba(20, 20, 20, 0.98); + border-bottom: 1px solid rgba(239, 68, 68, 0.3); + animation: securityBannerEnter 250ms cubic-bezier(0.16, 1, 0.3, 1); +} + +@keyframes securityBannerEnter { + from { opacity: 0; transform: translateY(-8px); } + to { opacity: 1; transform: translateY(0); } +} + +.security-banner-close { + position: absolute; + top: 6px; + right: 6px; + width: 28px; + height: 28px; + background: transparent; + border: none; + color: var(--zinc-500, #71717A); + font-size: 20px; + line-height: 1; + cursor: pointer; + border-radius: var(--radius-md, 8px); + padding: 0; +} +.security-banner-close:hover { + background: rgba(255, 255, 255, 0.05); + color: var(--zinc-300, #D4D4D8); +} +.security-banner-close:focus-visible { + outline: 2px solid var(--amber-500); + outline-offset: 2px; +} + +.security-banner-icon { + color: var(--error); + display: flex; + justify-content: center; + margin-bottom: 8px; +} + +.security-banner-title { + font-family: var(--font-display, 'Satoshi', sans-serif); + font-weight: 700; + font-size: 18px; + color: var(--error); + margin-bottom: 2px; +} + +.security-banner-subtitle { + font-family: var(--font-body, 'DM Sans', sans-serif); + font-size: 13px; + color: var(--zinc-400, #A1A1AA); + margin-bottom: 12px; +} + +.security-banner-expand { + display: inline-flex; + align-items: center; + gap: 6px; + background: transparent; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: var(--radius-md, 8px); + padding: 6px 12px; + color: var(--zinc-300, #D4D4D8); + font-family: var(--font-body, 'DM Sans', sans-serif); + font-size: 12px; + cursor: pointer; +} +.security-banner-expand:hover { + background: rgba(255, 255, 255, 0.04); +} +.security-banner-expand:focus-visible { + outline: 2px solid var(--amber-500); + outline-offset: 2px; +} +.security-banner-chevron { + transition: transform 200ms ease-out; +} + +.security-banner-details { + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + text-align: left; +} + +.security-banner-section-label { + font-family: var(--font-mono, 'JetBrains Mono', monospace); + font-size: 10px; + letter-spacing: 0.08em; + color: var(--zinc-500, #71717A); + margin-bottom: 6px; +} + +.security-banner-layers { + display: flex; + flex-direction: column; + gap: 4px; +} + +.security-banner-layer { + display: flex; + justify-content: space-between; + align-items: center; + padding: 4px 8px; + background: rgba(255, 255, 255, 0.02); + border-radius: var(--radius-sm, 4px); + font-family: var(--font-mono, 'JetBrains Mono', monospace); + font-size: 12px; +} + +.security-banner-layer-name { + color: var(--zinc-300, #D4D4D8); +} + +.security-banner-layer-score { + color: var(--amber-400); + font-variant-numeric: tabular-nums; +} + .conn-btn { font-size: 9px; font-family: var(--font-mono); diff --git a/extension/sidepanel.html b/extension/sidepanel.html index 33c77f1f..1824cda4 100644 --- a/extension/sidepanel.html +++ b/extension/sidepanel.html @@ -14,6 +14,32 @@ + + +