JJK.engineer — Design Tokens
For Claude Code: Reference this file when writing any CSS. All visual values come from these tokens. Never hardcode colors, font sizes, spacing, or breakpoints — always use the corresponding --jjk-* custom property. If a value you need isn’t here, ask the developer before inventing one.
Last Updated: February 13, 2025
Color System
The palette reads as “serious technical publication” in both modes. Accent color provides just enough personality without screaming “look at me.” All colors must maintain WCAG AA contrast ratios against their intended backgrounds.
Light Mode (default)
--jjk-color-bg |
#FAFAF8 |
Page background — warm white, not sterile |
--jjk-color-surface |
#FFFFFF |
Cards, elevated containers |
--jjk-color-surface-alt |
#F0EFEB |
Subtle differentiation — code blocks, callout backgrounds |
--jjk-color-ink |
#1A1A1A |
Primary text — near-black, easy on the eyes |
--jjk-color-ink-muted |
#6B6B6B |
Secondary text — dates, captions, metadata |
--jjk-color-ink-faint |
#A3A3A3 |
Tertiary text — placeholders, disabled states |
--jjk-color-accent |
#B45309 |
Burnt orange — links, interactive elements, the “corporate safety sign” energy |
--jjk-color-accent-hover |
#92400E |
Darker accent for hover states |
--jjk-color-accent-subtle |
#FEF3C7 |
Light amber wash — accent backgrounds, highlights |
--jjk-color-on-accent |
#FFFFFF |
Text/icons placed directly on accent-colored surfaces (buttons, badges) |
--jjk-color-border |
#E5E5E0 |
Dividers, card borders — barely there |
--jjk-color-border-strong |
#C5C5BE |
Emphasized borders when needed |
--jjk-color-danger |
#DC2626 |
Errors, destructive actions |
--jjk-color-success |
#16A34A |
Confirmations, positive states |
--jjk-color-draft-banner |
#FBBF24 |
Draft post banner background |
--jjk-color-scheduled-banner |
#60A5FA |
Scheduled post banner background |
Dark Mode (prefers-color-scheme: dark)
--jjk-color-bg |
#141413 |
Deep warm black |
--jjk-color-surface |
#1E1E1C |
Elevated surfaces |
--jjk-color-surface-alt |
#2A2A27 |
Code blocks, callouts |
--jjk-color-ink |
#E8E8E3 |
Primary text — warm off-white |
--jjk-color-ink-muted |
#9C9C95 |
Secondary text |
--jjk-color-ink-faint |
#6B6B65 |
Tertiary text |
--jjk-color-accent |
#F59E0B |
Amber — slightly brighter in dark mode for contrast |
--jjk-color-accent-hover |
#FBBF24 |
Lighter on hover in dark mode |
--jjk-color-accent-subtle |
#292218 |
Muted amber wash |
--jjk-color-on-accent |
#FFFFFF |
Unchanged — white maintains contrast on amber |
--jjk-color-border |
#2E2E2B |
Subtle dividers |
--jjk-color-border-strong |
#4A4A45 |
Emphasized borders |
--jjk-color-danger |
#EF4444 |
Slightly brighter for dark backgrounds |
--jjk-color-success |
#22C55E |
Slightly brighter for dark backgrounds |
--jjk-color-draft-banner |
#92400E |
Darker amber for dark mode |
--jjk-color-scheduled-banner |
#1E40AF |
Darker blue for dark mode |
Background Decoration Layer
--jjk-color-decoration |
0, 0, 0 (light) / 255, 255, 255 (dark) |
RGB base for SVG background elements — used with rgba() |
--jjk-decoration-opacity |
0.04 |
Default opacity for background SVGs — barely visible until you look |
Typography
The type system pairs a clean serif for headings (the “serious publication” energy) with a readable sans-serif for body text. Monospace for code. All sizes use a modular scale.
Font Families
--jjk-font-heading |
'Playfair Display' |
Georgia, 'Times New Roman', serif |
--jjk-font-body |
'Inter' |
system-ui, -apple-system, sans-serif |
--jjk-font-mono |
'JetBrains Mono' |
'Fira Code', 'Cascadia Code', monospace |
Font Sizes (modular scale, base 1rem = 16px, ratio ~1.25)
--jjk-text-xs |
0.75rem |
Fine print, legal jokes |
--jjk-text-sm |
0.875rem |
Captions, metadata, tag labels |
--jjk-text-base |
1rem |
Body text |
--jjk-text-lg |
1.125rem |
Lead paragraphs, slightly emphasized body |
--jjk-text-xl |
1.25rem |
H4, sub-sub-headings |
--jjk-text-2xl |
1.5rem |
H3 |
--jjk-text-3xl |
1.875rem |
H2 |
--jjk-text-4xl |
2.25rem |
H1 (post titles) |
--jjk-text-5xl |
3rem |
Hero/display text (rare) |
Line Heights
--jjk-leading-tight |
1.25 |
Headings |
--jjk-leading-normal |
1.6 |
Body text — generous for reading comfort |
--jjk-leading-loose |
1.8 |
Spacious layouts if needed |
Font Weights
--jjk-weight-normal |
400 |
Body text |
--jjk-weight-medium |
500 |
Slightly emphasized text, nav items |
--jjk-weight-semibold |
600 |
Sub-headings, bold UI elements |
--jjk-weight-bold |
700 |
Headings, strong emphasis |
Spacing
Eight-point grid. Every spacing value is a multiple of 0.5rem (8px). Do not invent spacing values outside this scale.
--jjk-space-1 |
0.25rem |
Tight internal padding (icon gaps) |
--jjk-space-2 |
0.5rem |
Compact padding, inline element gaps |
--jjk-space-3 |
0.75rem |
Button padding, tight card padding |
--jjk-space-4 |
1rem |
Default element spacing |
--jjk-space-6 |
1.5rem |
Section internal padding |
--jjk-space-8 |
2rem |
Between content blocks |
--jjk-space-12 |
3rem |
Between major sections |
--jjk-space-16 |
4rem |
Page-level vertical rhythm |
--jjk-space-24 |
6rem |
Large section separators, hero spacing |
Layout
--jjk-content-width |
42rem |
Max width for prose content — optimal reading line length |
--jjk-wide-width |
64rem |
Max width for wider layouts (tools, dashboards) |
--jjk-full-width |
80rem |
Max width for the outermost page container |
--jjk-sidebar-width |
16rem |
Navigation sidebar when present |
--jjk-header-height |
3.5rem |
Sticky header height |
Aspect Ratios
--jjk-aspect-cover |
16 / 9 |
Post feature images — hero and card thumbnail |
Breakpoints
Mobile-first. Styles default to mobile, then layer on complexity at wider viewports.
--jjk-bp-sm |
640px |
Large phones, small tablets |
--jjk-bp-md |
768px |
Tablets |
--jjk-bp-lg |
1024px |
Small desktops, landscape tablets |
--jjk-bp-xl |
1280px |
Standard desktops |
--jjk-bp-2xl |
1536px |
Wide desktops |
Note: CSS custom properties can’t be used in @media queries. Use these values directly in media queries but keep them consistent with the tokens documented here. If using a build step or CSS-in-JS that supports variable media queries in the future, migrate to tokens then.
Borders & Radii
--jjk-radius-sm |
0.25rem |
Subtle rounding — tags, small buttons |
--jjk-radius-md |
0.5rem |
Cards, input fields |
--jjk-radius-lg |
0.75rem |
Modals, large containers |
--jjk-radius-full |
9999px |
Pills, avatars |
--jjk-border-width |
1px |
Default border width |
--jjk-border-width-thick |
2px |
Table headers, active tab underlines |
Component Sizing
--jjk-badge-size |
1.25rem |
Notification badge min-width & height |
Heatmap Palette
GitHub contribution-graph palette used for the timeclock heatmap. Responds to light/dark theme via tokens.
--jjk-heatmap-level-1 |
#9be9a8 |
#0e4429 |
--jjk-heatmap-level-2 |
#40c463 |
#006d32 |
--jjk-heatmap-level-3 |
#30a14e |
#26a641 |
--jjk-heatmap-level-4 |
#216e39 |
#39d353 |
Level 0 uses the existing --jjk-color-surface-alt token.
Transitions
--jjk-transition-fast |
120ms ease |
Hover states, micro-interactions |
--jjk-transition-normal |
200ms ease |
Most UI transitions |
--jjk-transition-slow |
350ms ease |
Expanding panels, layout shifts |
--jjk-transition-color |
200ms ease |
Color/background transitions — used for dark/light mode switch |
Shadows
--jjk-shadow-sm |
0 1px 2px rgba(0,0,0,0.06) |
Subtle lift — tags, small elements |
--jjk-shadow-md |
0 2px 8px rgba(0,0,0,0.08) |
Cards, dropdowns |
--jjk-shadow-lg |
0 8px 24px rgba(0,0,0,0.12) |
Modals, floating elements |
Dark mode should reduce shadow intensity since dark surfaces don’t cast visible shadows — rely on border or surface color differentiation instead.
Z-Index Scale
Defined scale prevents z-index wars. Do not use arbitrary z-index values.
--jjk-z-base |
0 |
Default stacking |
--jjk-z-raised |
10 |
Sticky elements within flow |
--jjk-z-header |
100 |
Sticky header |
--jjk-z-dropdown |
200 |
Dropdowns, popovers |
--jjk-z-modal |
300 |
Modal overlays |
--jjk-z-toast |
400 |
Notifications, toasts |
--jjk-z-tooltip |
500 |
Tooltips (always on top) |
Token Gaps — Planned Additions
These gaps exist in the current codebase. Add the tokens here (and to tokens.css) before fixing the affected files.
--jjk-color-accent-rgb |
180, 83, 9 |
rgba() in pulse-ring animation (investors.component.css lines 529, 535, 538) |
--jjk-color-danger-rgb |
220, 38, 38 |
rgba() for danger focus ring and error background (contact.component.css lines 132, 201) |
Use the same pattern as --jjk-color-decoration: store as bare RGB components (R, G, G) so consumers can write rgba(var(--jjk-color-accent-rgb), 0.4).
Dark mode values: --jjk-color-accent-rgb: 245, 158, 11 / --jjk-color-danger-rgb: 239, 68, 68.
These tokens are the single source of truth for all visual values. If a component needs a value not listed here, add it to this file first — then use it. Never hardcode.