diff --git a/BRANDING.md b/BRANDING.md
index 10cb47fe..0f0e84c4 100644
--- a/BRANDING.md
+++ b/BRANDING.md
@@ -37,7 +37,7 @@ All SDK colors are expressed as `--dc-*` CSS custom properties. Host application
| Token | Light | Dark | Usage |
|-------|-------|------|-------|
-| `--dc-verified` | `#16a34a` | `#22c55e` | Verified citation |
+| `--dc-verified` | `#10b981` | `#34d399` | Verified citation (emerald-500 / emerald-400) |
| `--dc-partial` | `#f59e0b` | `#fbbf24` | Partial match |
| `--dc-destructive` | `#ef4444` | `#f87171` | Not found / error |
| `--dc-pending` | `#a1a1aa` | `#71717a` | Pending / loading |
diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss
index e84b6309..1e78d9a0 100644
--- a/docs/_sass/custom/custom.scss
+++ b/docs/_sass/custom/custom.scss
@@ -679,6 +679,10 @@ pre {
border: 1px solid var(--border-color);
}
+.search-result-doc .search-result-icon {
+ color: var(--link-color);
+}
+
// -----------------------------------------------------
// Tables - Clean single thin borders (no double borders)
// border-collapse eliminates double borders between cells
diff --git a/docs/agents/branding.md b/docs/agents/branding.md
index 462a0bd3..1c83b852 100644
--- a/docs/agents/branding.md
+++ b/docs/agents/branding.md
@@ -41,7 +41,7 @@ The Tailwind classes `bg-dc-*`, `text-dc-*`, `border-dc-*` are registered via `@
| Token | Light Default | Dark Default | Usage |
|-------|--------------|--------------|-------|
-| `--dc-verified` | `#16a34a` | `#22c55e` | Verified/success indicator |
+| `--dc-verified` | `#10b981` | `#34d399` | Verified/success indicator (emerald-500 / emerald-400) |
| `--dc-partial` | `#f59e0b` | `#fbbf24` | Partial match / warning indicator |
| `--dc-destructive` | `#ef4444` | `#f87171` | Error/not-found indicator |
| `--dc-pending` | `#a1a1aa` | `#71717a` | Pending/loading indicator |
diff --git a/docs/styling.md b/docs/styling.md
index e4c785e2..e07d2965 100644
--- a/docs/styling.md
+++ b/docs/styling.md
@@ -25,10 +25,10 @@ Override these CSS variables to theme all DeepCitation components at once:
```css
:root {
/* Status indicator colors */
- --dc-verified-color: #16a34a; /* Green - verified/exact match (default: green-600) */
- --dc-partial-color: #f59e0b; /* Amber - partial match (default: amber-500) */
- --dc-error-color: #ef4444; /* Red - not found/hallucination (default: red-500) */
- --dc-pending-color: #9ca3af; /* Gray - loading/pending (default: gray-400) */
+ --dc-verified: #10b981; /* Emerald - verified/exact match (default: emerald-500) */
+ --dc-partial: #f59e0b; /* Amber - partial match (default: amber-500) */
+ --dc-destructive: #ef4444; /* Red - not found/hallucination (default: red-500) */
+ --dc-pending: #9ca3af; /* Gray - loading/pending (default: gray-400) */
/* Wavy underline for "not found" status (non-linter variants) */
--dc-wavy-underline-color: #ef4444; /* Default: red-500 */
@@ -53,10 +53,10 @@ Override these CSS variables to theme all DeepCitation components at once:
```css
@media (prefers-color-scheme: dark) {
:root {
- --dc-verified-color: #4ade80; /* green-400 */
- --dc-partial-color: #fbbf24; /* amber-400 */
- --dc-error-color: #f87171; /* red-400 */
- --dc-pending-color: #6b7280; /* gray-500 */
+ --dc-verified: #34d399; /* emerald-400 */
+ --dc-partial: #fbbf24; /* amber-400 */
+ --dc-destructive: #f87171; /* red-400 */
+ --dc-pending: #6b7280; /* gray-500 */
--dc-linter-success: #6aab85;
--dc-linter-warning: #fbbf24;
--dc-linter-error: #d47d7c;
@@ -68,10 +68,10 @@ Override these CSS variables to theme all DeepCitation components at once:
/* Or with a class-based approach (Tailwind dark mode) */
.dark {
- --dc-verified-color: #4ade80;
- --dc-partial-color: #fbbf24;
- --dc-error-color: #f87171;
- --dc-pending-color: #6b7280;
+ --dc-verified: #34d399;
+ --dc-partial: #fbbf24;
+ --dc-destructive: #f87171;
+ --dc-pending: #6b7280;
--dc-document-canvas-bg-light: #f3f4f6;
--dc-document-canvas-bg-dark: #1f2937;
}
@@ -165,22 +165,22 @@ Target specific citation elements using data attributes and selectors:
/* Verified citations - specific styling */
[data-dc-indicator="verified"] {
- color: var(--dc-verified-color);
+ color: var(--dc-verified);
}
/* Partial match citations */
[data-dc-indicator="partial"] {
- color: var(--dc-partial-color);
+ color: var(--dc-partial);
}
/* Not found / hallucination citations */
[data-dc-indicator="error"] {
- color: var(--dc-error-color);
+ color: var(--dc-destructive);
}
/* Pending / loading citations */
[data-dc-indicator="pending"] {
- color: var(--dc-pending-color);
+ color: var(--dc-pending);
}
/* Citation trigger element */
diff --git a/src/__tests__/CitationContentDisplay.test.tsx b/src/__tests__/CitationContentDisplay.test.tsx
index aa4e6e81..4c036b93 100644
--- a/src/__tests__/CitationContentDisplay.test.tsx
+++ b/src/__tests__/CitationContentDisplay.test.tsx
@@ -73,7 +73,7 @@ describe("CitationContentDisplay — footnote variant", () => {
/>,
);
const sup = container.querySelector("sup");
- expect(sup?.className).toContain("text-green-600");
+ expect(sup?.className).toContain("text-dc-verified");
});
it("renders amber for partial match status", () => {
@@ -89,7 +89,7 @@ describe("CitationContentDisplay — footnote variant", () => {
/>,
);
const sup = container.querySelector("sup");
- expect(sup?.className).toContain("text-amber-500");
+ expect(sup?.className).toContain("text-dc-partial");
});
it("renders red for miss status", () => {
@@ -105,7 +105,7 @@ describe("CitationContentDisplay — footnote variant", () => {
/>,
);
const sup = container.querySelector("sup");
- expect(sup?.className).toContain("text-red-500");
+ expect(sup?.className).toContain("text-dc-destructive");
});
it("applies wavy underline style for miss state", () => {
diff --git a/src/__tests__/UrlCitationComponent.test.tsx b/src/__tests__/UrlCitationComponent.test.tsx
index 04160f5d..907106d4 100644
--- a/src/__tests__/UrlCitationComponent.test.tsx
+++ b/src/__tests__/UrlCitationComponent.test.tsx
@@ -50,9 +50,8 @@ describe("UrlCitationComponent", () => {
const checkIcon = container.querySelector("svg");
expect(checkIcon).toBeInTheDocument();
- // The wrapper should have green color class
- const statusWrapper = container.querySelector(".text-green-600");
- expect(statusWrapper).toBeInTheDocument();
+ // The check icon uses the --dc-verified CSS custom property so host themes can override it
+ expect(checkIcon).toHaveStyle({ color: "var(--dc-verified, #10b981)" });
});
it("shows lock icon when blocked", () => {
diff --git a/src/__tests__/caretIndicator.test.tsx b/src/__tests__/caretIndicator.test.tsx
index fdd44a98..03572393 100644
--- a/src/__tests__/caretIndicator.test.tsx
+++ b/src/__tests__/caretIndicator.test.tsx
@@ -85,16 +85,16 @@ describe("Caret Indicator Variant", () => {
});
// ==========================================================================
- // ACTIVE DARKENING
+ // COLOR STAYS GRAY REGARDLESS OF OPEN STATE (no inverted active style)
// ==========================================================================
- it("uses inverted text color (text-white) when open", () => {
+ it("uses gray text when open (no inverted active style)", () => {
const { container } = render();
const pill = container.querySelector("[data-dc-indicator='caret']") as HTMLElement;
- expect(pill.classList.contains("text-white")).toBe(true);
+ expect(pill.classList.contains("text-slate-500")).toBe(true);
});
- it("uses lighter gray (text-slate-500) when closed", () => {
+ it("uses gray text when closed", () => {
const { container } = render();
const pill = container.querySelector("[data-dc-indicator='caret']") as HTMLElement;
expect(pill.classList.contains("text-slate-500")).toBe(true);
diff --git a/src/__tests__/rendering/htmlRenderer.test.ts b/src/__tests__/rendering/htmlRenderer.test.ts
index 16862a48..d817f752 100644
--- a/src/__tests__/rendering/htmlRenderer.test.ts
+++ b/src/__tests__/rendering/htmlRenderer.test.ts
@@ -106,7 +106,7 @@ describe("renderCitationsAsHtml", () => {
it("generates dark theme styles", () => {
const output = renderCitationsAsHtml(simpleInput, { theme: "dark" });
- expect(output.styles).toContain("#4ade80"); // dark mode green
+ expect(output.styles).toContain("#34d399"); // dark mode emerald-400
});
it("generates auto theme styles with media query", () => {
diff --git a/src/drawing/citationDrawing.ts b/src/drawing/citationDrawing.ts
index 10a0c322..929eb065 100644
--- a/src/drawing/citationDrawing.ts
+++ b/src/drawing/citationDrawing.ts
@@ -15,11 +15,12 @@ import { safeSplit } from "../utils/regexSafety.js";
/**
* Highlight color category for citation annotations.
- * - 'blue': exact / full-phrase match
+ * - 'green': exact / full-phrase match (VERIFIED)
* - 'amber': partial match (anchorText-only or value-only)
* - 'red': not-found (AI claimed location overlay)
+ * - 'blue': legacy alias for 'green' — kept for backward compatibility
*/
-export type HighlightColor = "blue" | "amber" | "red";
+export type HighlightColor = "green" | "blue" | "amber" | "red";
// =============================================================================
// Color Constants
@@ -28,9 +29,14 @@ export type HighlightColor = "blue" | "amber" | "red";
/** Border width for citation bracket outlines (px). */
export const CITATION_LINE_BORDER_WIDTH = 2;
-/** Blue bracket color for exact/full-phrase matches. */
+/** Green bracket color for verified / exact-match citations (BRANDING.md VERIFIED, emerald-500). */
+export const SIGNAL_GREEN = "#10b981";
+/** Lighter green for dark-mode contexts (BRANDING.md VERIFIED luminous, emerald-400). */
+export const SIGNAL_GREEN_DARK = "#34d399";
+
+/** @deprecated Use SIGNAL_GREEN. Kept for any external consumers still referencing blue brackets. */
export const SIGNAL_BLUE = "#005595";
-/** Lighter blue for dark-mode contexts. */
+/** @deprecated Use SIGNAL_GREEN_DARK. */
export const SIGNAL_BLUE_DARK = "#77bff6";
/** Amber bracket color for partial matches (Tailwind amber-400). */
@@ -88,12 +94,14 @@ export function getBracketWidth(height: number): number {
/**
* Returns the bracket stroke color for a given highlight category.
- * Blue for exact matches, amber for partial matches, red for not-found.
+ * Green for verified/exact matches, amber for partial matches, red for not-found.
+ * "blue" is a legacy alias that resolves to the deprecated SIGNAL_BLUE value.
*/
-export function getBracketColor(highlightColor: HighlightColor = "blue"): string {
+export function getBracketColor(highlightColor: HighlightColor = "green"): string {
if (highlightColor === "amber") return SIGNAL_AMBER;
if (highlightColor === "red") return SIGNAL_RED;
- return SIGNAL_BLUE;
+ if (highlightColor === "blue") return SIGNAL_BLUE; // legacy
+ return SIGNAL_GREEN;
}
// =============================================================================
diff --git a/src/drawing/index.ts b/src/drawing/index.ts
index 7bc9197e..71b44408 100644
--- a/src/drawing/index.ts
+++ b/src/drawing/index.ts
@@ -21,6 +21,8 @@ export {
SIGNAL_AMBER,
SIGNAL_BLUE,
SIGNAL_BLUE_DARK,
+ SIGNAL_GREEN,
+ SIGNAL_GREEN_DARK,
SIGNAL_RED,
SPOTLIGHT_BORDER_RADIUS,
SPOTLIGHT_PADDING,
diff --git a/src/react/Citation.tsx b/src/react/Citation.tsx
index 2f5bb124..96f55827 100644
--- a/src/react/Citation.tsx
+++ b/src/react/Citation.tsx
@@ -25,6 +25,7 @@ import {
SPINNER_TIMEOUT_MS,
TAP_SLOP_PX,
TOUCH_CLICK_DEBOUNCE_MS,
+ VERIFIED_COLOR_STYLE,
} from "./constants.js";
import { DefaultPopoverContent, type PopoverViewState } from "./DefaultPopoverContent.js";
import { resolveEvidenceSrc, resolveExpandedImage } from "./EvidenceTray.js";
@@ -1490,12 +1491,12 @@ const PendingDot = () => (
);
/**
- * Green verified checkmark indicator.
- * Uses green-600 color to match DOT_COLORS.green for visual consistency.
+ * Verified checkmark indicator.
+ * Color tracks --dc-verified so it stays in sync with the status dot and quote border.
*/
const VerifiedCheck = () => (
-
-
+
+
);
diff --git a/src/react/CitationAnnotationOverlay.tsx b/src/react/CitationAnnotationOverlay.tsx
index 7aaddb14..48048a93 100644
--- a/src/react/CitationAnnotationOverlay.tsx
+++ b/src/react/CitationAnnotationOverlay.tsx
@@ -4,18 +4,31 @@ import {
BOX_PADDING,
CITATION_LINE_BORDER_WIDTH,
computeKeySpanHighlight,
- getBracketColor,
getBracketWidth,
OVERLAY_COLOR,
SPOTLIGHT_BORDER_RADIUS,
SPOTLIGHT_PADDING,
} from "../drawing/citationDrawing.js";
import type { DeepTextItem } from "../types/boxes.js";
-import { HITBOX_EXTEND_8 } from "./constants.js";
+import {
+ ERROR_COLOR_DEFAULT,
+ ERROR_COLOR_VAR,
+ HITBOX_EXTEND_8,
+ PARTIAL_COLOR_DEFAULT,
+ PARTIAL_COLOR_VAR,
+ VERIFIED_COLOR_DEFAULT,
+ VERIFIED_COLOR_VAR,
+} from "./constants.js";
import { useTranslation } from "./i18n.js";
import { CloseIcon } from "./icons.js";
import { toPercentRect } from "./overlayGeometry.js";
+// Hoisted bracket color strings — all inputs are static module-level constants,
+// so these never change and avoid per-render string allocations during zoom/pan.
+const VERIFIED_BRACKET_COLOR = `var(${VERIFIED_COLOR_VAR}, ${VERIFIED_COLOR_DEFAULT})`;
+const PARTIAL_BRACKET_COLOR = `var(${PARTIAL_COLOR_VAR}, ${PARTIAL_COLOR_DEFAULT})`;
+const ERROR_BRACKET_COLOR = `var(${ERROR_COLOR_VAR}, ${ERROR_COLOR_DEFAULT})`;
+
const NONE: React.CSSProperties = { pointerEvents: "none" };
/** Dismiss button size in px (matches Tailwind `size-7` = 1.75rem = 28px). */
@@ -50,7 +63,8 @@ function SecondaryBrackets({
const rect = toPercentRect(deepItem, renderScale, imageNaturalWidth, imageNaturalHeight);
if (!rect) return null;
- const bracketColor = getBracketColor(color === "muted" ? "blue" : "amber");
+ // amber → partial-match color; muted → verified color at lower opacity (distal supporting evidence)
+ const bracketColor = color === "muted" ? VERIFIED_BRACKET_COLOR : PARTIAL_BRACKET_COLOR;
const opacity = color === "muted" ? 0.35 : 0.5;
const baseLeft = parseFloat(rect.left);
@@ -143,9 +157,14 @@ export function CitationAnnotationOverlay({
// Bail out if geometry is invalid (zero dimensions, NaN, Infinity, etc.)
if (!rect) return null;
- const bracketColor = getBracketColor(
- highlightColor === "amber" ? "amber" : highlightColor === "red" ? "red" : "blue",
- );
+ // All bracket colors resolve through --dc-* tokens so a host override to any
+ // one token automatically keeps brackets, status indicators, and quote borders in sync.
+ const bracketColor =
+ highlightColor === "amber"
+ ? PARTIAL_BRACKET_COLOR
+ : highlightColor === "red"
+ ? ERROR_BRACKET_COLOR
+ : VERIFIED_BRACKET_COLOR;
// Compute pixel height for bracket width calculation
const heightPx = phraseMatchDeepItem.height * renderScale.y;
diff --git a/src/react/CitationContentDisplay.tsx b/src/react/CitationContentDisplay.tsx
index 7a60fae1..78816254 100644
--- a/src/react/CitationContentDisplay.tsx
+++ b/src/react/CitationContentDisplay.tsx
@@ -13,6 +13,7 @@ import { isUrlCitation } from "../types/citation.js";
import { getInteractionClasses } from "./CitationContentDisplay.utils.js";
import { CitationStatusIndicator, type CitationStatusIndicatorProps } from "./CitationStatusIndicator.js";
import {
+ CARET_INDICATOR_SIZE_STYLE,
DOT_COLORS,
DOT_INDICATOR_SIZE_STYLE,
ERROR_COLOR_STYLE,
@@ -22,7 +23,7 @@ import {
SUPERSCRIPT_STYLE,
VERIFIED_COLOR_STYLE,
} from "./constants.js";
-import { CheckIcon, XIcon } from "./icons.js";
+import { CheckIcon, ChevronDownIcon, XIcon } from "./icons.js";
import { handleImageError } from "./imageUtils.js";
import type { CitationContent, CitationRenderProps, CitationVariant } from "./types.js";
import { cn } from "./utils.js";
@@ -151,11 +152,11 @@ export const CitationContentDisplay = ({
if (shouldShowSpinner) {
footnoteStatusClasses = "text-slate-500 dark:text-slate-400";
} else if (isMiss) {
- footnoteStatusClasses = "text-red-500 dark:text-red-400";
+ footnoteStatusClasses = "text-dc-destructive";
} else if (isPartialMatch) {
- footnoteStatusClasses = "text-amber-500 dark:text-amber-400";
+ footnoteStatusClasses = "text-dc-partial";
} else if (isVerified) {
- footnoteStatusClasses = "text-green-600 dark:text-green-500";
+ footnoteStatusClasses = "text-dc-verified";
} else {
footnoteStatusClasses = "text-slate-500 dark:text-slate-400";
}
@@ -315,14 +316,10 @@ export const CitationContentDisplay = ({
return ;
}
if (iv === "caret") {
- const colorStyle = isMiss
- ? ERROR_COLOR_STYLE
- : isPartialMatch
- ? PARTIAL_COLOR_STYLE
- : VERIFIED_COLOR_STYLE;
+ const caretColor = isMiss ? "text-red-500 dark:text-red-400" : "text-slate-500 dark:text-slate-400";
return (
-
- {isMiss ? : }
+
+
);
}
diff --git a/src/react/CitationStatusIndicator.tsx b/src/react/CitationStatusIndicator.tsx
index da444942..0198028e 100644
--- a/src/react/CitationStatusIndicator.tsx
+++ b/src/react/CitationStatusIndicator.tsx
@@ -181,26 +181,12 @@ export const CitationStatusIndicator = ({
// Only flip when popover is above; down-caret already points toward a bottom popover.
const shouldFlip = isOpen === true && popoverSide === "top";
- // Color: miss → red, open → inverted (high contrast), default → muted gray.
- const pillTextClass = isMiss
- ? "text-red-500 dark:text-red-400"
- : isOpen
- ? "text-white dark:text-slate-900"
- : "text-slate-500 dark:text-slate-400";
-
- // Pill background: miss → red tint, open → solid dark/light (inverted), default → subtle slate.
- const pillBgClass = isMiss
- ? "bg-red-50 dark:bg-red-950"
- : isOpen
- ? "bg-slate-800 dark:bg-slate-100"
- : "bg-slate-100/60 dark:bg-slate-800/40";
-
if (shouldShowSpinner) {
return (
);
}
+
+ // Color: miss → red, default → muted gray.
+ const pillTextClass = isMiss ? "text-red-500 dark:text-red-400" : "text-slate-500 dark:text-slate-400";
+ const pillBgClass = isMiss ? "bg-red-50 dark:bg-red-950" : "bg-slate-100/60 dark:bg-slate-800/40";
+
return (
@@ -1010,10 +1010,10 @@ export function DefaultPopoverContent({
const isFullPage = viewState === "expanded-page";
const claimBorderColor = isMiss
- ? "border-red-500 dark:border-red-400"
+ ? "border-dc-destructive"
: isPartialMatch
- ? "border-amber-500 dark:border-amber-400"
- : "border-green-500 dark:border-green-600";
+ ? "border-dc-partial"
+ : "border-dc-verified";
// Unified summaryContent: success shows keyhole with onImageClick; miss/partial shows
// keyhole or search analysis depending on what's available.
diff --git a/src/react/EvidenceTray.tsx b/src/react/EvidenceTray.tsx
index e2c644bf..27932862 100644
--- a/src/react/EvidenceTray.tsx
+++ b/src/react/EvidenceTray.tsx
@@ -11,12 +11,13 @@
import type React from "react";
import { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
-import { isStrategyOverride, shouldHighlightAnchorText } from "../drawing/citationDrawing.js";
+import { type HighlightColor, isStrategyOverride, shouldHighlightAnchorText } from "../drawing/citationDrawing.js";
import type { DeepTextItem, ScreenBox } from "../types/boxes.js";
import type { CitationStatus } from "../types/citation.js";
import type { SearchAttempt } from "../types/search.js";
import type { PageImage, Verification } from "../types/verification.js";
import { CitationAnnotationOverlay } from "./CitationAnnotationOverlay.js";
+import { getStatusFromVerification } from "./citationStatus.js";
import { computeKeyholeOffset } from "./computeKeyholeOffset.js";
import {
BLINK_ENTER_EASING,
@@ -1334,6 +1335,15 @@ export function InlineExpandedImage({
const [overlayHidden, setOverlayHidden] = useState(initialOverlayHidden);
// When showOverlay is provided by parent (header panel mode), it overrides internal state.
const effectiveOverlayHidden = showOverlay !== undefined ? !showOverlay : overlayHidden;
+
+ // Overlay bracket color derived from verification status (green/amber/red).
+ // Memoized: getStatusFromVerification walks searchAttempts, and this component
+ // re-renders at 60fps during zoom/pan — verification is stable across those renders.
+ const overlayHighlightColor = useMemo((): HighlightColor => {
+ const s = getStatusFromVerification(verification);
+ return s.isMiss ? "red" : s.isPartialMatch ? "amber" : "green";
+ }, [verification]);
+
// Manual zoom override: null = use fitted zoom (automatic), number = user-selected zoom.
// Replaces the previous zoom + hasManualZoomRef pattern to avoid setState in effects.
const [manualZoom, setManualZoom] = useState(null);
@@ -1725,6 +1735,7 @@ export function InlineExpandedImage({
clampZoomRaw,
clampZoom,
gestureAnchorRef: expandedWheelAnchorRef,
+ requireCtrl: true,
onZoomCommit: (z: number) => {
setManualZoom(z);
},
@@ -2022,7 +2033,7 @@ export function InlineExpandedImage({
...(!annotationVtRect ? { viewTransitionName: DC_EVIDENCE_VT_NAME } : {}),
...(fill ? {} : { maxHeight: "min(600px, 80dvh)" }),
overscrollBehavior: "none",
- cursor: isDragging ? "move" : "zoom-out",
+ cursor: isDragging ? "grabbing" : "zoom-out",
...HIDE_SCROLLBAR_STYLE,
}}
onDragStart={e => e.preventDefault()}
@@ -2161,7 +2172,7 @@ export function InlineExpandedImage({
renderScale={renderScale}
imageNaturalWidth={naturalWidth}
imageNaturalHeight={naturalHeight}
- highlightColor={verification?.status === "not_found" ? "red" : verification?.highlightColor}
+ highlightColor={overlayHighlightColor}
anchorTextDeepItem={verification?.status === "not_found" ? undefined : effectiveAnchorItem}
anchorText={verification?.verifiedAnchorText}
fullPhrase={verification?.verifiedFullPhrase}
diff --git a/src/react/constants.ts b/src/react/constants.ts
index 78cf91f8..b9b07205 100644
--- a/src/react/constants.ts
+++ b/src/react/constants.ts
@@ -55,8 +55,8 @@ export const MISS_WAVY_UNDERLINE_STYLE: React.CSSProperties = {
* Override via `--dc-verified` on `:root` or `.dark`, or use ``.
*/
export const VERIFIED_COLOR_VAR = "--dc-verified";
-/** Default verified indicator color */
-export const VERIFIED_COLOR_DEFAULT = "#16a34a";
+/** Default verified indicator color (emerald-500, BRANDING.md VERIFIED) */
+export const VERIFIED_COLOR_DEFAULT = "#10b981";
/**
* CSS custom property name for partial match indicator color.
diff --git a/src/rendering/html/styles.ts b/src/rendering/html/styles.ts
index 5a11e30f..f4b00ef8 100644
--- a/src/rendering/html/styles.ts
+++ b/src/rendering/html/styles.ts
@@ -19,13 +19,13 @@ interface ThemeColors {
*/
const STATUS_COLORS: { light: ThemeColors; dark: ThemeColors } = {
light: {
- verified: { text: "#16a34a", bg: "#f0fdf4", border: "#bbf7d0" },
+ verified: { text: "#10b981", bg: "#ecfdf5", border: "#a7f3d0" },
partial: { text: "#d97706", bg: "#fffbeb", border: "#fde68a" },
notFound: { text: "#dc2626", bg: "#fef2f2", border: "#fecaca" },
pending: { text: "#6b7280", bg: "#f9fafb", border: "#e5e7eb" },
},
dark: {
- verified: { text: "#4ade80", bg: "#052e16", border: "#166534" },
+ verified: { text: "#34d399", bg: "#022c22", border: "#065f46" },
partial: { text: "#fbbf24", bg: "#451a03", border: "#92400e" },
notFound: { text: "#f87171", bg: "#450a0a", border: "#991b1b" },
pending: { text: "#9ca3af", bg: "#1f2937", border: "#374151" },
diff --git a/src/rendering/testing/HtmlPreview.tsx b/src/rendering/testing/HtmlPreview.tsx
index c32313dc..c58abdb0 100644
--- a/src/rendering/testing/HtmlPreview.tsx
+++ b/src/rendering/testing/HtmlPreview.tsx
@@ -79,11 +79,11 @@ function getPreviewCss(): string {
return [
".dc-preview-scope .dc-citation { cursor: pointer; }",
".dc-preview-scope .dc-citation a { color: inherit; text-decoration: none; }",
- ".dc-preview-scope .dc-verified { color: #16a34a; }",
+ ".dc-preview-scope .dc-verified { color: #10b981; }",
".dc-preview-scope .dc-partial { color: #f59e0b; }",
".dc-preview-scope .dc-not-found { color: #ef4444; }",
".dc-preview-scope .dc-pending { color: #9ca3af; }",
- ".dc-preview-scope span.dc-citation.dc-verified { text-decoration: underline solid #16a34a; text-underline-offset: 3px; }",
+ ".dc-preview-scope span.dc-citation.dc-verified { text-decoration: underline solid #10b981; text-underline-offset: 3px; }",
".dc-preview-scope span.dc-citation.dc-partial { text-decoration: underline dashed #f59e0b; text-underline-offset: 3px; }",
".dc-preview-scope span.dc-citation.dc-not-found { text-decoration: underline wavy #ef4444; text-underline-offset: 3px; }",
".dc-preview-scope span.dc-citation.dc-pending { text-decoration: underline dotted #9ca3af; text-underline-offset: 3px; }",
@@ -256,7 +256,7 @@ function selfContainedHtml(): string {
"