# Design Tokens CSS custom properties (design tokens) for the Evidence-Weighted Score component suite. ## Score Colors ### Bucket Colors ```css :root { /* Act Now (90-100) - Critical priority */ --score-bucket-act-now: #DC2626; --score-bucket-act-now-light: #FEE2E2; --score-bucket-act-now-dark: #991B1B; /* Schedule Next (70-89) - High priority */ --score-bucket-schedule-next: #D97706; --score-bucket-schedule-next-light: #FEF3C7; --score-bucket-schedule-next-dark: #92400E; /* Investigate (40-69) - Medium priority */ --score-bucket-investigate: #2563EB; --score-bucket-investigate-light: #DBEAFE; --score-bucket-investigate-dark: #1E40AF; /* Watchlist (0-39) - Low priority */ --score-bucket-watchlist: #6B7280; --score-bucket-watchlist-light: #F3F4F6; --score-bucket-watchlist-dark: #374151; } ``` ### Flag Colors ```css :root { /* Live Signal - Active runtime signals */ --score-flag-live-signal: #16A34A; --score-flag-live-signal-light: #DCFCE7; --score-flag-live-signal-dark: #166534; /* Proven Path - Verified reachability */ --score-flag-proven-path: #2563EB; --score-flag-proven-path-light: #DBEAFE; --score-flag-proven-path-dark: #1E40AF; /* Vendor N/A - Vendor not affected */ --score-flag-vendor-na: #6B7280; --score-flag-vendor-na-light: #F3F4F6; --score-flag-vendor-na-dark: #374151; /* Speculative - Unconfirmed evidence */ --score-flag-speculative: #D97706; --score-flag-speculative-light: #FEF3C7; --score-flag-speculative-dark: #92400E; } ``` ## Component Tokens ### ScorePill ```css :root { --score-pill-font-family: system-ui, -apple-system, sans-serif; --score-pill-font-weight: 600; --score-pill-border-radius: 4px; /* Size: Small */ --score-pill-sm-height: 20px; --score-pill-sm-min-width: 24px; --score-pill-sm-padding: 0 4px; --score-pill-sm-font-size: 12px; /* Size: Medium */ --score-pill-md-height: 24px; --score-pill-md-min-width: 32px; --score-pill-md-padding: 0 6px; --score-pill-md-font-size: 14px; /* Size: Large */ --score-pill-lg-height: 28px; --score-pill-lg-min-width: 40px; --score-pill-lg-padding: 0 8px; --score-pill-lg-font-size: 16px; /* Interactive states */ --score-pill-hover-scale: 1.05; --score-pill-focus-ring: 2px solid var(--color-focus); --score-pill-focus-offset: 2px; } ``` ### ScoreBadge ```css :root { --score-badge-font-family: system-ui, -apple-system, sans-serif; --score-badge-font-weight: 500; --score-badge-border-radius: 4px; /* Size: Small */ --score-badge-sm-height: 20px; --score-badge-sm-padding: 2px 6px; --score-badge-sm-font-size: 11px; --score-badge-sm-icon-size: 12px; /* Size: Medium */ --score-badge-md-height: 24px; --score-badge-md-padding: 4px 8px; --score-badge-md-font-size: 12px; --score-badge-md-icon-size: 14px; /* Icon-only mode */ --score-badge-icon-only-size: 20px; --score-badge-icon-only-padding: 4px; } ``` ### ScoreBreakdownPopover ```css :root { --score-popover-max-width: 360px; --score-popover-padding: 16px; --score-popover-border-radius: 8px; --score-popover-background: #FFFFFF; --score-popover-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); /* Dimension bars */ --score-dimension-bar-height: 8px; --score-dimension-bar-radius: 4px; --score-dimension-bar-bg: #E5E7EB; /* Header */ --score-popover-header-font-size: 24px; --score-popover-header-font-weight: 700; /* Labels */ --score-popover-label-font-size: 12px; --score-popover-label-color: #6B7280; /* Explanations */ --score-popover-explanation-font-size: 13px; --score-popover-explanation-color: #374151; } ``` ### ScoreHistoryChart ```css :root { --score-chart-line-color: #3B82F6; --score-chart-line-width: 2px; --score-chart-area-fill: rgba(59, 130, 246, 0.1); --score-chart-area-gradient-start: rgba(59, 130, 246, 0.2); --score-chart-area-gradient-end: rgba(59, 130, 246, 0); /* Data points */ --score-chart-point-size: 6px; --score-chart-point-hover-size: 8px; --score-chart-point-border-width: 2px; --score-chart-point-border-color: #FFFFFF; /* Grid */ --score-chart-grid-color: #E5E7EB; --score-chart-grid-width: 1px; /* Bands */ --score-chart-band-opacity: 0.1; /* Axis */ --score-chart-axis-color: #9CA3AF; --score-chart-axis-font-size: 11px; /* Tooltip */ --score-chart-tooltip-bg: #1F2937; --score-chart-tooltip-color: #FFFFFF; --score-chart-tooltip-padding: 8px 12px; --score-chart-tooltip-radius: 6px; } ``` ## Dark Mode ```css @media (prefers-color-scheme: dark) { :root { /* Backgrounds */ --score-popover-background: #1F2937; --score-chart-tooltip-bg: #374151; /* Text */ --score-popover-label-color: #D1D5DB; --score-popover-explanation-color: #F9FAFB; /* Borders */ --score-dimension-bar-bg: #374151; --score-chart-grid-color: #374151; /* Adjust bucket light colors for dark mode */ --score-bucket-act-now-light: rgba(220, 38, 38, 0.2); --score-bucket-schedule-next-light: rgba(217, 119, 6, 0.2); --score-bucket-investigate-light: rgba(37, 99, 235, 0.2); --score-bucket-watchlist-light: rgba(107, 114, 128, 0.2); } } ``` ## Semantic Tokens ```css :root { /* Focus states */ --color-focus: #3B82F6; --color-focus-ring: rgba(59, 130, 246, 0.3); /* Interactive */ --color-interactive: #3B82F6; --color-interactive-hover: #2563EB; --color-interactive-active: #1D4ED8; /* Status */ --color-success: #16A34A; --color-warning: #D97706; --color-error: #DC2626; --color-info: #2563EB; /* Neutral */ --color-text-primary: #111827; --color-text-secondary: #6B7280; --color-text-disabled: #9CA3AF; --color-border: #E5E7EB; --color-background: #FFFFFF; --color-surface: #F9FAFB; } ``` ## Usage in Components ### SCSS Import ```scss // styles/_tokens.scss @use 'sass:map'; $score-buckets: ( 'act-now': ( color: var(--score-bucket-act-now), light: var(--score-bucket-act-now-light), dark: var(--score-bucket-act-now-dark), ), 'schedule-next': ( color: var(--score-bucket-schedule-next), light: var(--score-bucket-schedule-next-light), dark: var(--score-bucket-schedule-next-dark), ), 'investigate': ( color: var(--score-bucket-investigate), light: var(--score-bucket-investigate-light), dark: var(--score-bucket-investigate-dark), ), 'watchlist': ( color: var(--score-bucket-watchlist), light: var(--score-bucket-watchlist-light), dark: var(--score-bucket-watchlist-dark), ), ); @mixin bucket-colors($bucket) { $colors: map.get($score-buckets, $bucket); background-color: map.get($colors, color); color: white; &.light { background-color: map.get($colors, light); color: map.get($colors, dark); } } ``` ### TypeScript Constants ```typescript // score-colors.ts export const SCORE_BUCKET_COLORS = { ActNow: { bg: '#DC2626', light: '#FEE2E2', dark: '#991B1B', }, ScheduleNext: { bg: '#D97706', light: '#FEF3C7', dark: '#92400E', }, Investigate: { bg: '#2563EB', light: '#DBEAFE', dark: '#1E40AF', }, Watchlist: { bg: '#6B7280', light: '#F3F4F6', dark: '#374151', }, } as const; export const SCORE_FLAG_COLORS = { 'live-signal': { bg: '#16A34A', light: '#DCFCE7' }, 'proven-path': { bg: '#2563EB', light: '#DBEAFE' }, 'vendor-na': { bg: '#6B7280', light: '#F3F4F6' }, 'speculative': { bg: '#D97706', light: '#FEF3C7' }, } as const; export function getBucketColor(score: number): string { if (score >= 90) return SCORE_BUCKET_COLORS.ActNow.bg; if (score >= 70) return SCORE_BUCKET_COLORS.ScheduleNext.bg; if (score >= 40) return SCORE_BUCKET_COLORS.Investigate.bg; return SCORE_BUCKET_COLORS.Watchlist.bg; } ``` ## Accessibility Notes - All color combinations meet WCAG 2.1 AA contrast requirements (4.5:1 for text) - Bucket colors use both color and position/labels for identification - Flag badges use icons in addition to colors - Focus states use high-contrast ring colors ## Related Files - `src/Web/StellaOps.Web/src/styles/_tokens.scss` - SCSS token definitions - `src/Web/StellaOps.Web/src/app/core/constants/score-colors.ts` - TypeScript constants