design system · v1
nebula
nebula is the design system that powers bryanchasko.com — a cosmic palette of deep navy, lavender accent, and aws orange highlight. every page on this site is built from the tokens documented below. dark mode is the default voice; light mode is a courtesy.
palette
brand chips first, semantic mappings second. semantic vars are the right citation in component css — brand vars are the source
brand
semantic
--color-primary
--nebula-purple
primary action color--color-primary-hover
--nebula-lavender
primary hover state--color-accent
--nebula-orange
highlight + cta accent--color-link
--nebula-purple
anchor color (light)--color-link-hover
--nebula-lavender-chip
anchor hover (light)--color-border
--gray-200
card + divider borders--color-border-hover
--nebula-lavender
interactive border highlighttypography
system stack — defaulting to platform fonts means crisp render at every viewport, zero web-font cost, no flash of unstyled text
font stacks
--font-bodythe quick brown fox jumps over the lazy dog
ui + prose
--font-monothe quick brown fox jumps over the lazy dog
code, terminal greeting, var names
type scale
cosmic chip caption
body-secondary, meta
paragraph body
lead paragraph
card title
section h3
section h2
page h1
line height
--line-height-tight
1.25stacking lines at this rhythm. the cosmic ledger keeps its accounting clean even as it stretches across the viewport. each line earns its place
headings
--line-height-base
1.6stacking lines at this rhythm. the cosmic ledger keeps its accounting clean even as it stretches across the viewport. each line earns its place
body prose
--line-height-relaxed
1.75stacking lines at this rhythm. the cosmic ledger keeps its accounting clean even as it stretches across the viewport. each line earns its place
long-form notes
spacing
a 4-based scale doubling at each step until the gutter takes over. measure twice, gap once
radius
chip → pill, the curve grows as the surface widens. nothing is ever fully square except code
elevation
dark mode reads as depth; light mode reads as paper. the elevation stack is the same idea drawn twice
--color-backgroundpage canvas
--color-background-secondarysubtle separation, code backgrounds
--color-builder-card-bgbuilder card section, dark callouts
--nebula-card-navydark theme cards (lifted)
shadow
shadows do the work of suggesting depth without committing to it. small for separation, xl for modal weight
motion
three transition durations. fast for attention, base for confirmation, slow for arrival. every easing is the same cubic-bezier — variation is duration, not curve
hover any swatch above to feel the timing
components
specimens of the most-used composed atoms — buttons, cards, code, callouts. each renders with the live theme css so this page stays honest
buttons
card
cards use the glassmorphism gradient + nebula border. hover lifts via translate-Y and amplifies the corner glow
learn more →callout / chip
--nebula-purplecode block
:root {
--color-primary: var(--nebula-purple);
--color-accent: var(--nebula-orange);
--space-md: 1rem;
}containers
three boundaries do all the layout work — page, prose, and gutter
--container-max-width
1200pxouter page bound
--content-max-width
65chprose column (45-75 char read-width)
--container-padding
var(--space-lg)gutter on narrow screens
source
the canonical token file. this page renders from a curated mirror at
data/theme.yaml. when the two diverge the css below wins.
PRs welcome
themes/bryan-chasko-theme/assets/css/core/tokens.css
/* ============================================
CANONICAL DESIGN TOKENS — single source of truth
This is the ONE place every CSS custom property (design token) is defined.
Loaded FIRST in the core bundle (see layouts/partials/head.html) so every
consumer sees tokens defined before use.
Layers:
1. layout primitives (relocated from core/theme-vars.css)
2. brand + palette primitives (relocated from extended/nebula.css)
3. semantic color mappings (light) + dark overrides
4. legacy PaperMod bridge (--theme/--entry/--primary/... -> semantics)
5. resolved dangling refs (container/content max-width, brand aliases, social gradients)
Do NOT redefine base color tokens in component or extended files.
============================================ */
:root {
/* ============================================
LAYOUT PRIMITIVES (relocated from core/theme-vars.css)
============================================ */
--gap: 24px;
--content-gap: 20px;
--nav-width: 1024px;
--main-width: 720px;
--header-height: 60px;
--footer-height: 60px;
--radius: 8px;
color-scheme: light;
/* ============================================
CORE BRAND COLORS
Primary identity colors used across all UI
============================================ */
--brand-dark-navy: #1c2230;
--brand-purple: #5e41a2;
--brand-lavender: #8169c5;
--brand-orange: #ff9900;
--brand-orange-dark: #e68a00;
--brand-lavender-light: #a78bfa;
/* Legacy aliases (backwards compatibility) */
--nebula-dark-navy: var(--brand-dark-navy);
--nebula-purple: var(--brand-purple);
--nebula-lavender: var(--brand-lavender);
--nebula-orange: var(--brand-orange);
--nebula-orange-dark: var(--brand-orange-dark);
/* ============================================
WEBGL PALETTE A: VIBRANT COSMIC
Purple/Teal clash for dynamic energy effects
Use for: Particle systems, active states,
high-energy animations
============================================ */
--cosmic-base: #1c2230; /* Dark navy foundation */
--cosmic-primary: #5e41a2; /* Deep purple */
--cosmic-accent: #ff9900; /* Vibrant orange */
--cosmic-energy: #00fa9a; /* Medium spring green - NEW */
--cosmic-teal: #00ced1; /* Dark turquoise */
--cosmic-purple-bright: #9d4edd; /* Bright purple highlight */
/* ============================================
WEBGL PALETTE B: SOFT TECH
Clean, readable modern aesthetic
Use for: UI overlays, tooltips, cards,
professional/business contexts
============================================ */
--tech-base: #f9fafb; /* Light gray foundation */
--tech-primary: #8169c5; /* Lavender */
--tech-accent: #a78bfa; /* Light lavender */
--tech-gold: #ffd700; /* Gold - NEW (replaces orange) */
--tech-slate: #475569; /* Slate gray for contrast */
--tech-cyan: #06b6d4; /* Cyan for interactive elements */
/* ============================================
NEUTRAL GRAYS
Systematic gray scale for backgrounds,
borders, text hierarchy
============================================ */
--white: #ffffff;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-300: #d1d5db;
--gray-400: #9ca3af;
--gray-500: #6b7280;
--gray-600: #4b5563;
--gray-700: #374151;
--gray-800: #2d3748;
--gray-900: #1f2937;
--gray-950: #111827;
--black-light: #444;
--black: #333;
/* ============================================
SYNTAX HIGHLIGHTING - CATPPUCCIN MACCHIATO
Code editor theme colors
============================================ */
--syntax-bg: #24273a;
--syntax-text: #cad3f5;
--syntax-error: #ed8796;
--syntax-keyword: #c6a0f6;
--syntax-constant: #f5a97f;
--syntax-name: #8bd5ca;
--syntax-function: #8aadf4;
--syntax-builtin: #91d7e3;
--syntax-class: #eed49f;
--syntax-variable: #f4dbd6;
--syntax-string: #a6da95;
--syntax-comment: #6e738d;
--syntax-highlight-bg: #474733;
--syntax-line-number: #8087a2;
--syntax-diff-bg: #363a4f;
/* ============================================
SEMANTIC COLOR MAPPINGS - LIGHT MODE
Context-specific color assignments
============================================ */
--color-primary: var(--brand-purple);
--color-primary-hover: var(--brand-lavender);
--color-accent: var(--brand-orange);
--color-accent-dark: var(--brand-orange-dark);
--color-dark: var(--brand-dark-navy);
/* Light Theme Colors */
--color-background: var(--white);
--color-background-secondary: var(--gray-50);
--color-text: var(--gray-900);
--color-text-secondary: var(--gray-500);
--color-text-muted: var(--black-light);
--color-link: var(--brand-purple);
--color-link-hover: var(--brand-lavender);
--color-border: var(--gray-200);
--color-border-hover: var(--brand-lavender);
/* WebGL scene defaults (light mode) */
--webgl-palette: vibrant-cosmic;
--webgl-primary: var(--cosmic-primary);
--webgl-accent: var(--cosmic-accent);
--webgl-energy: var(--cosmic-energy);
/* Spacing Scale */
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 1.5rem; /* 24px */
--space-xl: 2rem; /* 32px */
--space-2xl: 3rem; /* 48px */
--space-3xl: 4rem; /* 64px */
/* Typography */
--font-body:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
Cantarell, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
--font-heading: var(--font-body);
--font-mono:
ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo,
monospace, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
--font-size-xs: 0.75rem; /* 12px */
--font-size-sm: 0.875rem; /* 14px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.125rem; /* 18px */
--font-size-xl: 1.25rem; /* 20px */
--font-size-2xl: 1.5rem; /* 24px */
--font-size-3xl: 1.875rem; /* 30px */
--font-size-4xl: 2.25rem; /* 36px */
--line-height-tight: 1.25;
--line-height-base: 1.6;
--line-height-relaxed: 1.75;
/* Border Radius */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md:
0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg:
0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl:
0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
/* Transitions */
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-base: 200ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: 300ms cubic-bezier(0.4, 0, 0.2, 1);
/* ============================================
DECOMPOSED TIMING + EASING TOKENS (#27)
Additive — --transition-* remain unchanged.
Consumers opt in; existing code unaffected.
============================================ */
--ease-out: cubic-bezier(0.4, 0, 0.2, 1);
--duration-fast: 150ms;
--duration-base: 200ms;
--duration-slow: 300ms;
/* Entrance stagger — per-card delay increment for page-load reveal (#34) */
--stagger: 80ms;
/* ============================================
SEMANTIC STATE COLORS (#27)
Coordinates with existing palette:
--color-info aligns with --tech-cyan
--color-warning aligns with --brand-orange-dark
============================================ */
--color-success: #10b981;
--color-danger: #ef4444;
--color-info: var(--tech-cyan); /* #06b6d4 */
--color-warning: var(--brand-orange-dark); /* #e68a00 */
/* Focus ring — light mode default (#27) */
--focus-ring: 2px solid var(--color-primary);
/* ============================================
RESOLVED DANGLING REFS (backlog item 1, step 6)
Previously consumed via var() but never defined — the
property silently dropped. Defined here once.
============================================ */
/* outer container width — matches --nav-width */
--container-max-width: 1024px;
/* text column width — matches --main-width */
--content-max-width: 720px;
/* rename drift: aliased to the current deep-space background token.
no existing token held this value; canonical deep-space is #0b0e14. */
--nebula-deep-space: #0b0e14;
/* rename drift: alias to --nebula-purple (#5E41A2), one true value */
--nebula-core-brand-purple: var(--nebula-purple);
/* social card branded backgrounds (team decision).
github: dark neutral via surface tokens where possible */
--gradient-github: linear-gradient(135deg, #2b3137 0%, #1a1e22 100%);
/* instagram brand gradient */
--gradient-insta: linear-gradient(
135deg,
#833ab4 0%,
#fd1d1d 50%,
#fcb045 100%
);
}
/* Dark Theme Overrides */
[data-theme="dark"] {
color-scheme: dark;
--color-background: var(--brand-dark-navy);
--color-background-secondary: var(--gray-800);
--color-text: var(--gray-100);
--color-text-secondary: var(--gray-300);
--color-text-muted: var(--gray-400);
--color-link: var(--brand-lavender);
--color-link-hover: var(--brand-lavender-light);
--color-border: var(--gray-700);
--color-border-hover: var(--brand-lavender);
/* Focus ring override — lavender for dark-mode contrast (#27) */
--focus-ring: 2px solid var(--brand-lavender);
/* WebGL scene defaults (dark mode) */
--webgl-primary: var(--cosmic-purple-bright);
--webgl-accent: var(--cosmic-energy);
--webgl-energy: var(--cosmic-teal);
}
/* Legacy PaperMod Variable Mappings for Compatibility */
:root {
--theme: var(--color-background);
--entry: var(--color-background-secondary);
--primary: var(--color-text);
--secondary: var(--color-text-secondary);
--tertiary: var(--color-background-secondary);
--content: var(--color-text);
--hljs-bg: var(--gray-50);
--code-bg: var(--gray-100);
--border: var(--color-border);
/* code-block-bg: NOT part of the PaperMod semantic bridge — kept as a
literal (relocated from core/theme-vars.css) to preserve resolved value */
--code-block-bg: rgb(28, 29, 33);
}
[data-theme="dark"] {
--theme: var(--color-background);
--entry: var(--color-background-secondary);
--primary: var(--color-text);
--secondary: var(--color-text-secondary);
--tertiary: var(--color-background-secondary);
--content: var(--color-text);
--hljs-bg: var(--gray-800);
--code-bg: var(--gray-700);
--border: var(--color-border);
--code-block-bg: rgb(46, 46, 51);
}