diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css index 2ca6ebc..58c3201 100644 --- a/frontend/src/styles/index.css +++ b/frontend/src/styles/index.css @@ -19,9 +19,11 @@ --color-ink-on: #ffffff; --color-charcoal: #3d3d3d; --color-graphite: #636363; - - /* DESIGN.md: body line-height 1.4 when substituting Inter */ - font-size: 16.5px; + /* Semantic status tokens — WCAG AA on canvas and slab surfaces */ + --color-success: #16a34a; + --color-success-soft: #dcfce7; + --color-warn: #d97706; + --color-warn-soft: #fef3c7; } /* Dark mode overrides */ @@ -38,6 +40,11 @@ --color-ink-on: #111827; --color-charcoal: #d1d5db; --color-graphite: #9ca3af; + /* Semantic status tokens — dark variants, WCAG AA on #111827 slab */ + --color-success: #22c55e; + --color-success-soft: #14532d; + --color-warn: #f59e0b; + --color-warn-soft: #78350f; } html, @@ -48,6 +55,8 @@ body { @apply bg-canvas text-ink font-sans antialiased; + font-size: 16px; + line-height: 1.4; font-feature-settings: 'cv11', 'ss01'; } @@ -57,19 +66,20 @@ h4, h5, h6 { - line-height: 1; + line-height: 1.1; font-weight: 500; } } @layer components { /* - * DESIGN.md component recipes. - * Buttons stay sharp (rounded-md = 4px); cards stay soft (rounded-xl = 16px). + * Terminal-SOC brutalist component recipes. + * border-radius: 0 everywhere except .badge-pill-* (status pills only). + * No transition-* on any interactive surface. */ .btn-primary { - @apply inline-flex items-center justify-center gap-xs bg-primary text-white uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors; + @apply inline-flex items-center justify-center gap-xs bg-primary text-white uppercase font-semibold text-[14px] leading-[1.4] rounded-none px-xl py-sm h-11; } .btn-primary:hover { @apply bg-primary-deep; @@ -78,19 +88,19 @@ @apply bg-steel cursor-not-allowed; } - /* btn-ink uses fixed dark slab so it doesn't invert in dark mode */ + /* btn-ink: fixed dark slab — does not invert in dark mode */ .btn-ink { - @apply inline-flex items-center justify-center gap-xs bg-slab text-white uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors; + @apply inline-flex items-center justify-center gap-xs bg-slab text-slab-text uppercase font-semibold text-[14px] leading-[1.4] rounded-none px-xl py-sm h-11; } .btn-ink:hover { - @apply bg-paper; + @apply opacity-80; } .btn-ink:disabled { @apply bg-steel cursor-not-allowed; } .btn-outline { - @apply inline-flex items-center justify-center gap-xs bg-canvas text-primary border border-primary uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors; + @apply inline-flex items-center justify-center gap-xs bg-canvas text-primary border border-primary uppercase font-semibold text-[14px] leading-[1.4] rounded-none px-xl py-sm h-11; } .btn-outline:hover { @apply bg-primary-soft; @@ -100,37 +110,41 @@ } .btn-outline-ink { - @apply inline-flex items-center justify-center gap-xs bg-canvas text-ink border border-ink uppercase tracking-[0.7px] font-semibold text-[14px] leading-[1.4] rounded-md px-xl py-sm h-11 transition-colors; + @apply inline-flex items-center justify-center gap-xs bg-canvas text-ink border border-ink uppercase font-semibold text-[14px] leading-[1.4] rounded-none px-xl py-sm h-11; } .btn-outline-ink:hover { @apply bg-cloud; } .btn-text-link { - @apply inline-flex items-center gap-xxs text-primary font-medium text-[16px] leading-[1.38] underline-offset-2 hover:underline; + @apply inline-flex items-center gap-xxs text-primary font-medium text-[16px] leading-[1.4] underline-offset-2 hover:underline; } .text-input { - @apply block w-full bg-canvas text-ink rounded-md border border-steel px-md py-sm h-11 text-[16px] leading-[1.38] focus:outline-none focus:border-ink; + @apply block w-full bg-canvas text-ink rounded-none border border-steel px-md py-sm h-11 text-[16px] leading-[1.4] focus:outline-none focus:border-primary; } + /* Panel / card — hairline border, no shadow, no radius */ .card-product { - @apply bg-canvas rounded-xl p-xl shadow-soft-lift; - } - .dark .card-product { - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.32); + @apply bg-paper border border-hairline rounded-none p-md; } - /* Fixed-color modal backdrop — must not use themed ink (inverts in dark mode) */ + /* Fixed modal backdrop — must not use themed ink (inverts in dark mode) */ .modal-backdrop { background-color: rgba(0, 0, 0, 0.6); } + /* Status pill badges — ONLY surfaces with rounded-pill */ .badge-pill-ink { - @apply inline-flex items-center bg-ink text-white rounded-lg px-3 py-[6px] text-[14px] leading-[1.3] font-medium; + @apply inline-flex items-center bg-ink text-white rounded-pill px-3 py-[6px] text-[14px] leading-[1.3] font-medium; } .badge-pill-outline { - @apply inline-flex items-center bg-canvas text-ink border border-ink rounded-lg px-3 py-[6px] text-[14px] leading-[1.3] font-medium; + @apply inline-flex items-center bg-canvas text-ink border border-ink rounded-pill px-3 py-[6px] text-[14px] leading-[1.3] font-medium; + } + + /* MITRE technique tags — angular, not pills */ + .tag-mitre { + @apply inline-flex items-center bg-cloud text-ink border border-hairline rounded-none px-2 py-[2px] font-mono text-[12px] leading-[1.33]; } } diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts index 2fee123..6ccf51c 100644 --- a/frontend/tailwind.config.ts +++ b/frontend/tailwind.config.ts @@ -1,8 +1,8 @@ import type { Config } from 'tailwindcss'; /** - * Tokens mirror DESIGN.md. - * Forma DJR Micro substitut: Inter (bundled locally via @fontsource-variable/inter). + * Tokens mirror DESIGN.md (terminal-SOC aesthetic, sprint 7). + * Inter Variable: body/headers/labels. JetBrains Mono Variable: data cells only. * Dark mode: class-based, toggled by adding 'dark' to . */ const config: Config = { @@ -11,7 +11,7 @@ const config: Config = { theme: { extend: { colors: { - // Brand & Accent — primary stays fixed (HP Electric Blue never inverts) + // Brand & Accent — primary stays fixed (never inverts) primary: { DEFAULT: '#024ad8', bright: '#296ef9', @@ -34,10 +34,19 @@ const config: Config = { }, charcoal: 'var(--color-charcoal)', graphite: 'var(--color-graphite)', - // Fixed dark slab — never inverts in dark mode (utility strip, footer, dark bands) + // Fixed dark slab — never inverts in dark mode slab: '#111827', 'slab-text': '#f9fafb', 'slab-muted': '#6b7280', + // Semantic status tokens — light+dark variants via CSS vars + success: { + DEFAULT: 'var(--color-success)', + soft: 'var(--color-success-soft)', + }, + warn: { + DEFAULT: 'var(--color-warn)', + soft: 'var(--color-warn-soft)', + }, // Semantic / decorative — fixed (not themeable) bloom: { coral: '#ff5050', @@ -53,26 +62,28 @@ const config: Config = { }, fontFamily: { sans: ['"Inter Variable"', 'Inter', 'Arial', 'sans-serif'], + mono: ['"JetBrains Mono Variable"', '"JetBrains Mono"', 'ui-monospace', 'monospace'], }, fontSize: { - // DESIGN.md typography scale - 'display-xxl': ['72px', { lineHeight: '1.0', fontWeight: '500' }], - 'display-xl': ['56px', { lineHeight: '1.0', fontWeight: '500' }], - 'display-lg': ['44px', { lineHeight: '1.0', fontWeight: '500' }], - 'display-md': ['32px', { lineHeight: '1.0', fontWeight: '500' }], - 'display-sm': ['24px', { lineHeight: '1.17', fontWeight: '500' }], - 'display-xs': ['20px', { lineHeight: '1.0', fontWeight: '500' }], - 'body-lg': ['18px', { lineHeight: '1.33', fontWeight: '400' }], - 'body-md': ['16px', { lineHeight: '1.38', fontWeight: '400' }], - 'body-emphasis': ['16px', { lineHeight: '1.38', fontWeight: '500' }], + // Terminal-SOC display scale — reduced per §0 D9 + 'display-xxl': ['40px', { lineHeight: '1.1', fontWeight: '500' }], + 'display-xl': ['32px', { lineHeight: '1.1', fontWeight: '500' }], + 'display-lg': ['28px', { lineHeight: '1.1', fontWeight: '500' }], + 'display-md': ['24px', { lineHeight: '1.1', fontWeight: '500' }], + 'display-sm': ['20px', { lineHeight: '1.1', fontWeight: '500' }], + 'display-xs': ['16px', { lineHeight: '1.1', fontWeight: '600' }], + 'body-lg': ['18px', { lineHeight: '1.4', fontWeight: '400' }], + 'body-md': ['16px', { lineHeight: '1.4', fontWeight: '400' }], + 'body-emphasis': ['16px', { lineHeight: '1.4', fontWeight: '500' }], 'caption-md': ['14px', { lineHeight: '1.5', fontWeight: '400' }], 'caption-bold': ['14px', { lineHeight: '1.3', fontWeight: '700' }], 'caption-sm': ['12px', { lineHeight: '1.33', fontWeight: '400' }], - 'link-md': ['16px', { lineHeight: '1.38', fontWeight: '500' }], - 'button-md': ['14px', { lineHeight: '1.4', fontWeight: '600', letterSpacing: '0.7px' }], + 'link-md': ['16px', { lineHeight: '1.4', fontWeight: '500' }], + 'button-md': ['14px', { lineHeight: '1.4', fontWeight: '600' }], + 'button-sm': ['12.6px', { lineHeight: '1.0', fontWeight: '700' }], }, spacing: { - // DESIGN.md spacing tokens (named, complement Tailwind defaults) + // Named tokens complement Tailwind defaults xxs: '4px', xs: '8px', sm: '12px', @@ -80,19 +91,15 @@ const config: Config = { lg: '20px', xl: '24px', xxl: '32px', - section: '80px', + section: '48px', }, borderRadius: { - // DESIGN.md radius tokens + // Brutalist: 0 everywhere except status pills and avatars none: '0px', - xs: '2px', - sm: '3px', - md: '4px', - lg: '8px', - xl: '16px', pill: '9999px', }, boxShadow: { + // Kept in config for backwards compat but no component should apply them 'soft-lift': '0 2px 8px rgba(26, 26, 26, 0.08)', floating: '0 8px 24px rgba(26, 26, 26, 0.12)', 'soft-lift-dark': '0 2px 8px rgba(0, 0, 0, 0.32)',