feat(design): refresh tailwind tokens for brutalist terminal aesthetic
This commit is contained in:
@@ -19,9 +19,11 @@
|
|||||||
--color-ink-on: #ffffff;
|
--color-ink-on: #ffffff;
|
||||||
--color-charcoal: #3d3d3d;
|
--color-charcoal: #3d3d3d;
|
||||||
--color-graphite: #636363;
|
--color-graphite: #636363;
|
||||||
|
/* Semantic status tokens — WCAG AA on canvas and slab surfaces */
|
||||||
/* DESIGN.md: body line-height 1.4 when substituting Inter */
|
--color-success: #16a34a;
|
||||||
font-size: 16.5px;
|
--color-success-soft: #dcfce7;
|
||||||
|
--color-warn: #d97706;
|
||||||
|
--color-warn-soft: #fef3c7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark mode overrides */
|
/* Dark mode overrides */
|
||||||
@@ -38,6 +40,11 @@
|
|||||||
--color-ink-on: #111827;
|
--color-ink-on: #111827;
|
||||||
--color-charcoal: #d1d5db;
|
--color-charcoal: #d1d5db;
|
||||||
--color-graphite: #9ca3af;
|
--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,
|
html,
|
||||||
@@ -48,6 +55,8 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-canvas text-ink font-sans antialiased;
|
@apply bg-canvas text-ink font-sans antialiased;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
font-feature-settings: 'cv11', 'ss01';
|
font-feature-settings: 'cv11', 'ss01';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,19 +66,20 @@
|
|||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1;
|
line-height: 1.1;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
/*
|
/*
|
||||||
* DESIGN.md component recipes.
|
* Terminal-SOC brutalist component recipes.
|
||||||
* Buttons stay sharp (rounded-md = 4px); cards stay soft (rounded-xl = 16px).
|
* border-radius: 0 everywhere except .badge-pill-* (status pills only).
|
||||||
|
* No transition-* on any interactive surface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.btn-primary {
|
.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 {
|
.btn-primary:hover {
|
||||||
@apply bg-primary-deep;
|
@apply bg-primary-deep;
|
||||||
@@ -78,19 +88,19 @@
|
|||||||
@apply bg-steel cursor-not-allowed;
|
@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 {
|
.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 {
|
.btn-ink:hover {
|
||||||
@apply bg-paper;
|
@apply opacity-80;
|
||||||
}
|
}
|
||||||
.btn-ink:disabled {
|
.btn-ink:disabled {
|
||||||
@apply bg-steel cursor-not-allowed;
|
@apply bg-steel cursor-not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline {
|
.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 {
|
.btn-outline:hover {
|
||||||
@apply bg-primary-soft;
|
@apply bg-primary-soft;
|
||||||
@@ -100,37 +110,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-outline-ink {
|
.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 {
|
.btn-outline-ink:hover {
|
||||||
@apply bg-cloud;
|
@apply bg-cloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-text-link {
|
.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 {
|
.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 {
|
.card-product {
|
||||||
@apply bg-canvas rounded-xl p-xl shadow-soft-lift;
|
@apply bg-paper border border-hairline rounded-none p-md;
|
||||||
}
|
|
||||||
.dark .card-product {
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 {
|
.modal-backdrop {
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Status pill badges — ONLY surfaces with rounded-pill */
|
||||||
.badge-pill-ink {
|
.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 {
|
.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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { Config } from 'tailwindcss';
|
import type { Config } from 'tailwindcss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokens mirror DESIGN.md.
|
* Tokens mirror DESIGN.md (terminal-SOC aesthetic, sprint 7).
|
||||||
* Forma DJR Micro substitut: Inter (bundled locally via @fontsource-variable/inter).
|
* Inter Variable: body/headers/labels. JetBrains Mono Variable: data cells only.
|
||||||
* Dark mode: class-based, toggled by adding 'dark' to <html>.
|
* Dark mode: class-based, toggled by adding 'dark' to <html>.
|
||||||
*/
|
*/
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
@@ -11,7 +11,7 @@ const config: Config = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
// Brand & Accent — primary stays fixed (HP Electric Blue never inverts)
|
// Brand & Accent — primary stays fixed (never inverts)
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: '#024ad8',
|
DEFAULT: '#024ad8',
|
||||||
bright: '#296ef9',
|
bright: '#296ef9',
|
||||||
@@ -34,10 +34,19 @@ const config: Config = {
|
|||||||
},
|
},
|
||||||
charcoal: 'var(--color-charcoal)',
|
charcoal: 'var(--color-charcoal)',
|
||||||
graphite: 'var(--color-graphite)',
|
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: '#111827',
|
||||||
'slab-text': '#f9fafb',
|
'slab-text': '#f9fafb',
|
||||||
'slab-muted': '#6b7280',
|
'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)
|
// Semantic / decorative — fixed (not themeable)
|
||||||
bloom: {
|
bloom: {
|
||||||
coral: '#ff5050',
|
coral: '#ff5050',
|
||||||
@@ -53,26 +62,28 @@ const config: Config = {
|
|||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['"Inter Variable"', 'Inter', 'Arial', 'sans-serif'],
|
sans: ['"Inter Variable"', 'Inter', 'Arial', 'sans-serif'],
|
||||||
|
mono: ['"JetBrains Mono Variable"', '"JetBrains Mono"', 'ui-monospace', 'monospace'],
|
||||||
},
|
},
|
||||||
fontSize: {
|
fontSize: {
|
||||||
// DESIGN.md typography scale
|
// Terminal-SOC display scale — reduced per §0 D9
|
||||||
'display-xxl': ['72px', { lineHeight: '1.0', fontWeight: '500' }],
|
'display-xxl': ['40px', { lineHeight: '1.1', fontWeight: '500' }],
|
||||||
'display-xl': ['56px', { lineHeight: '1.0', fontWeight: '500' }],
|
'display-xl': ['32px', { lineHeight: '1.1', fontWeight: '500' }],
|
||||||
'display-lg': ['44px', { lineHeight: '1.0', fontWeight: '500' }],
|
'display-lg': ['28px', { lineHeight: '1.1', fontWeight: '500' }],
|
||||||
'display-md': ['32px', { lineHeight: '1.0', fontWeight: '500' }],
|
'display-md': ['24px', { lineHeight: '1.1', fontWeight: '500' }],
|
||||||
'display-sm': ['24px', { lineHeight: '1.17', fontWeight: '500' }],
|
'display-sm': ['20px', { lineHeight: '1.1', fontWeight: '500' }],
|
||||||
'display-xs': ['20px', { lineHeight: '1.0', fontWeight: '500' }],
|
'display-xs': ['16px', { lineHeight: '1.1', fontWeight: '600' }],
|
||||||
'body-lg': ['18px', { lineHeight: '1.33', fontWeight: '400' }],
|
'body-lg': ['18px', { lineHeight: '1.4', fontWeight: '400' }],
|
||||||
'body-md': ['16px', { lineHeight: '1.38', fontWeight: '400' }],
|
'body-md': ['16px', { lineHeight: '1.4', fontWeight: '400' }],
|
||||||
'body-emphasis': ['16px', { lineHeight: '1.38', fontWeight: '500' }],
|
'body-emphasis': ['16px', { lineHeight: '1.4', fontWeight: '500' }],
|
||||||
'caption-md': ['14px', { lineHeight: '1.5', fontWeight: '400' }],
|
'caption-md': ['14px', { lineHeight: '1.5', fontWeight: '400' }],
|
||||||
'caption-bold': ['14px', { lineHeight: '1.3', fontWeight: '700' }],
|
'caption-bold': ['14px', { lineHeight: '1.3', fontWeight: '700' }],
|
||||||
'caption-sm': ['12px', { lineHeight: '1.33', fontWeight: '400' }],
|
'caption-sm': ['12px', { lineHeight: '1.33', fontWeight: '400' }],
|
||||||
'link-md': ['16px', { lineHeight: '1.38', fontWeight: '500' }],
|
'link-md': ['16px', { lineHeight: '1.4', fontWeight: '500' }],
|
||||||
'button-md': ['14px', { lineHeight: '1.4', fontWeight: '600', letterSpacing: '0.7px' }],
|
'button-md': ['14px', { lineHeight: '1.4', fontWeight: '600' }],
|
||||||
|
'button-sm': ['12.6px', { lineHeight: '1.0', fontWeight: '700' }],
|
||||||
},
|
},
|
||||||
spacing: {
|
spacing: {
|
||||||
// DESIGN.md spacing tokens (named, complement Tailwind defaults)
|
// Named tokens complement Tailwind defaults
|
||||||
xxs: '4px',
|
xxs: '4px',
|
||||||
xs: '8px',
|
xs: '8px',
|
||||||
sm: '12px',
|
sm: '12px',
|
||||||
@@ -80,19 +91,15 @@ const config: Config = {
|
|||||||
lg: '20px',
|
lg: '20px',
|
||||||
xl: '24px',
|
xl: '24px',
|
||||||
xxl: '32px',
|
xxl: '32px',
|
||||||
section: '80px',
|
section: '48px',
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
// DESIGN.md radius tokens
|
// Brutalist: 0 everywhere except status pills and avatars
|
||||||
none: '0px',
|
none: '0px',
|
||||||
xs: '2px',
|
|
||||||
sm: '3px',
|
|
||||||
md: '4px',
|
|
||||||
lg: '8px',
|
|
||||||
xl: '16px',
|
|
||||||
pill: '9999px',
|
pill: '9999px',
|
||||||
},
|
},
|
||||||
boxShadow: {
|
boxShadow: {
|
||||||
|
// Kept in config for backwards compat but no component should apply them
|
||||||
'soft-lift': '0 2px 8px rgba(26, 26, 26, 0.08)',
|
'soft-lift': '0 2px 8px rgba(26, 26, 26, 0.08)',
|
||||||
floating: '0 8px 24px rgba(26, 26, 26, 0.12)',
|
floating: '0 8px 24px rgba(26, 26, 26, 0.12)',
|
||||||
'soft-lift-dark': '0 2px 8px rgba(0, 0, 0, 0.32)',
|
'soft-lift-dark': '0 2px 8px rgba(0, 0, 0, 0.32)',
|
||||||
|
|||||||
Reference in New Issue
Block a user