Design System
Visual tokens, typography, and component patterns for chris-tien.com
Color Palette
Typography
Font stack: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif
Buttons
| Variant | Background | Border | Radius | Weight | Padding |
|---|---|---|---|---|---|
| Primary | #fff → #e5e5e5 | 2px solid #fff | 999px (pill) | 700 | 0.6rem 2rem |
| Secondary | #000 → #1a1a1a | 2px solid #fff | 999px (pill) | 400 | 0.6rem 2rem |
| Tertiary | transparent | none | n/a | 400 | 0 (icon + label) |
| Auth / Form | #fff → #ddd | none | 8px | 600 | 0.75rem (full width) |
Form Elements
| Property | Value |
|---|---|
| Background | #000 |
| Border | 1px solid #333 → #fff on focus |
| Border radius | 8px |
| Padding | 0.75rem 1rem |
| Font size | 1rem |
| Transition | border-color 0.2s |
Components
Breadcrumb
Project Card
Modal (Quick Links)
Quick Links
Direct links to all projects and pages on the site.
Auth Gate
Chris Tien
Enter password to continue
Category Tile
Large clickable card used as a category entry point. Square corners, dark surface, background emoji at low opacity, white bottom-border animation on hover.
| Property | Value |
|---|---|
| Background | #0a0a0a |
| Border | 1px solid #1a1a1a → #333 on hover |
| Border radius | 0 (square — intentional gallery aesthetic) |
| Min height | 200px (desktop), 160px (mobile) |
| Bottom accent | ::after, height 2px, #fff, width 0 → 100% on hover (0.5s) |
| Icon | position: absolute top-right, opacity 0.06 → 0.18 + scale(1.1) on hover |
| Title | 1.8rem / 900 / uppercase / ls -0.03em |
| Description | 0.75rem / uppercase / ls 0.08em / color #888 |
Filter Pill
Sub-category filter tabs. Distinct from primary/secondary CTAs — lighter weight, 1px border, used for filtering project lists.
| Property | Value |
|---|---|
| Border | 1px solid #222 (inactive) / 1px solid #fff (active) |
| Border radius | 999px (pill) |
| Padding | 0.45rem 0.9rem |
| Font size | 0.85rem |
| Inactive | color #555, bg transparent |
| Hover | color #aaa, border #333 |
| Active | bg #fff, color #000, border #fff |
| Count label | 0.72rem, opacity 0.6 (0.5 when active) |
Search Input — Underline Variant
Used on category landing pages. No background or box — bottom border only, uppercase text, brighter placeholder than the standard input.
| Property | Value |
|---|---|
| Border | bottom only: 1px solid #555 → #fff on focus |
| Background | none (transparent) |
| Border radius | 0 |
| Padding | 0.85rem 0.25rem |
| Font size | 1rem, uppercase, ls 0.05em |
| Placeholder | rgba(255,255,255,0.3) |
| Icon color | #888 |
| Transition | border-color 0.2s |
Recent Card
Used on the projects hub to surface the 3 newest projects. Emoji thumbnail with grayscale filter (color on hover), optional "Newest" badge, title slide on hover.
| Property | Value |
|---|---|
| Thumbnail | aspect-ratio 16/10, bg #111, emoji centered at 3rem |
| Filter | grayscale(100%) opacity 0.8 → grayscale(0%) opacity 1 on hover (0.5s) |
| Badge | position: absolute top-left, bg #fff, color #000, 0.6rem/900/uppercase |
| Title | 1.1rem / 700 / uppercase / ls -0.01em; translateX(4px) on hover (0.3s) |
| Meta | 0.65rem / uppercase / ls 0.1em / color #888 |
| Description | 0.8rem / color #666 / lh 1.55 / 2-line clamp |
| Grid | 3 columns desktop, 2 columns ≤768px, 1 column ≤480px |
Ticker Strip
Full-width auto-scrolling strip with seamless loop. Animates on all screen sizes.
| Property | Value |
|---|---|
| Position | Top of page, above main content |
| Height | Auto (content-based) |
| Background | #050505 |
| Border | 1px solid #1a1a1a (bottom) |
| Animation | 40s linear infinite (translateX 0 → -50%) |
| On Hover | animation-play-state: paused |
| Edge Mask | ::before / ::after gradient fades (left/right) |
| Seamless Loop | JS duplicates all items (second copy hidden visually) |
Mini Card Strip
Horizontal swipeable carousel showing project emoji + name. Mobile-only component.
| Property | Value |
|---|---|
| Display | Mobile only (@media max-width: 480px) |
| Overflow | overflow-x: auto; scrollbar hidden |
| Scroll Behavior | -webkit-overflow-scrolling: touch (momentum scroll) |
| Card Sizing | flex-shrink: 0; min-width: 76px |
| Card Gap | 0.5rem |
| Padding | 1rem 1.25rem (vertical | horizontal) |
| Card Content | Emoji icon + project name (centered) |
Spacing Scale
Border Radius
Transitions & Motion
| Duration | Properties | Used on |
|---|---|---|
| 0.15s | color | Breadcrumb links, project arrows, text links |
| 0.2s | background, border-color, transform, box-shadow | Buttons (hover), inputs (focus), logo cards (hover) |
| 0.3s | color, transform | Briefing link on root page; recent card title slide |
| 0.5s | opacity, transform, filter, width | Category tile icon fade/scale; recent card grayscale; tile bottom-border expand |
Hover Transforms
| Element | Transform |
|---|---|
| Project card arrow → | translateX(3px) |
| Logo card | translateY(-3px) |
| Recent card title | translateX(4px) |
| Category tile icon | scale(1.1) |
Responsive Breakpoints
| Breakpoint | Applies to | Key Changes |
|---|---|---|
| max-width: 768px | Gallery hub, Games, Explorations pages | Recent grid: 3→2 columns; project grid view: 3→2 columns |
| max-width: 768px | Brands / logo grid | Grid: 3 columns (down from 4), gap 0.75rem |
| max-width: 640px | Full-screen games (test4) | Mobile breadcrumb bar replaces sidebar |
| max-width: 480px | All pages (primary mobile breakpoint) | h1 → 1.9rem; padding → 1.25rem horiz; footer stacks vertically; logo grid → 2 columns |
Baseline mobile target: 375px (iPhone SE). All layouts use width: 100% with max-width caps — never fixed widths. Content pages: max-width: 760px. Grid / dashboard pages: max-width: 960px. Gallery / hub pages (projects, games, explorations): max-width: 1100px.
Z-Index Layers
| z-index | Layer |
|---|---|
| 99999 | Auth gate (#ct-auth-gate) — always on top |
| 100 | Quick Links modal overlay |
| 1–10 | Sticky headers, game overlays (project-specific) |
| 0 | Default page content |